Jdbc Clojure core.async。如何用go块惰性下载里面用open?

Jdbc Clojure core.async。如何用go块惰性下载里面用open?,jdbc,clojure,lazy-evaluation,core.async,Jdbc,Clojure,Lazy Evaluation,Core.async,这是我上一个问题的继续 我想按部分从数据库下载数据。最初我下载前500行,然后发送请求获取下500行,依此类推,直到我从服务器接收到所有数据 我写了代码: (jdbc/atomic conn (with-open [cursor (jdbc/fetch-lazy conn [sql_query])] (let [lazyseq (jdbc/cursor->lazyseq cursor) counter (atom 1)] (swap! lazyseq_m

这是我上一个问题的继续

我想按部分从数据库下载数据。最初我下载前500行,然后发送请求获取下500行,依此类推,直到我从服务器接收到所有数据

我写了代码:

(jdbc/atomic conn
 (with-open [cursor (jdbc/fetch-lazy conn [sql_query])]
   (let [lazyseq (jdbc/cursor->lazyseq cursor)
         counter (atom 1)]
     (swap! lazyseq_maps assoc :session_id {:get_next? (chan 1) :over_500 (chan 1) :data []})
     (>!! (:get_next? (:session_id @lazyseq_maps)) true)
     (go
       (doseq [row lazyseq]
         (swap! counter inc)
         (when (<! (:get_next? (:session_id @lazyseq_maps)))
           (swap! lazyseq_maps update-in [:session_id :data] conj row)
           (if (not= 0 (mod @counter 500))
             (>! (:get_next? (:session_id @lazyseq_maps)) true)
             (>! (:over_500 (:session_id @lazyseq_maps)) true))))
        ;
        (close! (:get_next? (:session_id @lazyseq_maps)))
        (close! (:over_500 (:session_id @lazyseq_maps)))
        (.close conn))

     (when (<!! (:over_500 (:session_id @lazyseq_maps))) {:message "over 500 rows"
                                                          :id :session_id
                                                          :data (:data (:session_id @lazyseq_maps))}))))
(jdbc/原子连接
(使用open[cursor(jdbc/fetch-lazy-conn[sql\u-query])]
(让[lazyseq(jdbc/cursor->lazyseq cursor)
计数器(原子1)]
(swap!lazyseq_maps assoc:session_id{:get_next?(chan 1):超过500(chan 1):数据[])
(>!!(:get_next?(:session_id@lazyseq_maps))true)
(去
(doseq[第lazyseq行]
(交换柜台公司)
(何时(!(:get_next?(:session_id@lazyseq_maps))true)
(>!(:超过500(:session_id@lazyseq_maps))真)
;
(关闭!(:get_next?(:session_id@lazyseq_maps)))
(关闭!(:超过500(:session_id@lazyseq_maps)))
(关闭控制室)
(何时)(
我在doseq循环的帮助下获取行。当doseq通过500行时,我停止循环
(当),并等待来自外部的信号来获取下一个500行

但这里我有一个问题。当我发送信号时,程序抛出错误“Resultset is closed”(结果集关闭)。也就是说,连接在打开的作用域外部关闭。但我不明白为什么,因为go块放在打开的作用域内部。你能帮我解决这个问题吗?

(go…
立即返回,因此,
(打开时…)

您可能希望以另一种方式进行:


(转到(打开…)

但是,请注意,此过程可能会保留数据库连接(一种稀缺资源!)很长时间,这可能是不可取的,而且由于
go
块的存在,这与使用“轻量级”线程的好处是背道而驰的

  • 也许可以为每个批重新打开数据库连接
  • 也许您可以将整个结果集流式传输到外部存储(例如AWS S3),并让客户对此进行投票

除非您使用的是内存严重受限的系统,否则我建议您立即将所有行加载到RAM并关闭DB连接。否则,您的完整解决方案可能会非常复杂,难以测试和推理

如果您有数千万行,那么您可以在某些分区中获取它们