异步Clojure http-kit客户端,将回调写入数据库SQLITE3



我在写入sqlite表时被http-kit async行为所困。

数据库的I/O取决于我是将代码发送到boot补充还是以boot脚本运行。I/O仅在REPL案例中进行。我想念什么?这是我的代码:

#!/usr/bin/env boot                                                                                                                                             
(defn deps [new-deps]                                                                                                                                           
  (boot.core/merge-env! :dependencies new-deps))                                                                                                                
(deps '[                                                                                                                                                        
        [http-kit  "2.2.0"]                                                                                                         
        [org.clojure/core.async  "0.2.395"]                                                                                                                     
        [org.clojure/java.jdbc  "0.7.0-alpha1"]                                                                                                                 
        [org.xerial/sqlite-jdbc  "3.16.1"]                                                                                                                      
        [org.slf4j/slf4j-nop "1.7.22"]                                                                                                                          
        ])                                                                                                                                                      
(require                                                                                                                                                        
         '[org.httpkit.client :as http]                                                                                                                         
         '[clojure.java.jdbc :as jdbc]                                                                                                                          
         )                                                                                                                                                      

(def db-spec                                                                                                                                                    
  {:classname "org.sqlite.JDBC"                                                                                                                                 
   :subprotocol "sqlite"                                                                                                                                        
   :subname "sqlite.db"})                                                                                                                                       
;(jdbc/db-do-commands                                                                                                                                           
  ;db-spec                                                                                                                                                      
  ;(jdbc/create-table-ddl "test" [[:msg :text]]))                                                                                                               
(def ins! (partial jdbc/insert! db-spec "test"))                                                                                                                
(http/get "http://locahost" {} (fn [_] (ins! {:msg "repl"})))                                                                                                   

(defn -main []                                                                                                                                                  
  (println (System/getProperty  "user.dir"))                                                                                                                    
  (http/get "http://locahost" {} (fn [_] (ins! {:msg "exec"}))))                                                                                                

谢谢

脚本不从命令行工作的问题是,http-kit异步回调是由守护程序线程处理的,唯一的非daemon线程是运行脚本的主线程。

当您的-main函数在将HTTP请求提交给HTTP-KIT以进行异步处理后结束时,主线程终止并导致JVM关闭,然后守护程序线程处理ASYNC回调会有机会跑步。

>

您可以通过在-main函数的末尾添加睡眠表达来检查一下,以查看您的回调已执行:

(defn -main []                                                                                                                                                  
  (println (System/getProperty  "user.dir"))                                                                                                                    
  (http/get "http://locahost" {} (fn [_] (ins! {:msg "exec"})))
  (Thread/sleep 60000))

确保-main函数将等待处理结果的最佳方法是保持http/get呼叫返回的承诺。承诺最终将包含您的回调功能产生的结果:

(let [result-promise (http/get "https://www.google.com" {} (fn [_] "Result"))]
  @result-promise)

@result-promise(deref result-promise)的读取器宏/快捷方式。

当您想无限期地阻止deref时,完整表单可能会更好 - 只需使用超时MS和超时值参数:

(deref result-promise 5000 "Didn't get response in 5 seconds. Giving up")

最新更新