我有一个小程序,它应该一个一个地读取 SQL 查询/命令并针对数据库执行它们。
如果查询成功执行,则执行下一个查询。如果执行一个查询时出错,程序应该一起停止执行。
我有代码,只是即使出现异常,查询仍会继续执行。
(defn main
[]
(loop [queries (get-all-queries)
querycount 1]
(let [q (first queries)]
(println (format "currently processing query %s", querycount))
(cond (nil? q) (println "All Queries ran successfully.")
:else (do
(cond (= (:status (process-query q querycount)) "OK")
(recur (rest queries) (+querycount 1)))
:else (println "An error occured while running queries")))))))
(defn process-query
[query query-count]
(let [{query-body :query-body, is-query-running? :is-query-running?} query
my-agent (agent
{:error false, :query-count query-count}
:error-handler handler-fn)]
(send my-agent (fn[_]
(execute-query! db query-body)))))
(loop [is-query-running? (is-query-running?)
error? (:error @my-agent)]
(cond error? (do (println "Error")
{:status "ERROR" :error-msg (:error-msg @my-agent)})
(and (not is-query-running?) (not error?)) (do (println "Success")
{:status "OK"})
(:else (do
(Thread/sleep 2000)
(recur (is-query-running?) (:error @my-agent)))))))
(defn handler-fn
[agent exception]
(println (format "an exception occured : %s" exception))
(if (instance? java.sql.BatchUpdateException exception)
(println (.getNextException exception)))
(send agent (? [_] {:error true, :error-message exception}))
(throw exception))
我使用代理的原因是我有一些查询需要 4 小时才能运行。当这种情况发生时,数据库不会通知程序查询已经完成。相反,程序卡住了。所以,相反,我经常轮询以检查查询是否已经完成。
- 这是完成我想做的事情的最佳方式吗?
- 我应该使用任何其他并发原语吗?
- 我什至需要并发原语吗?
- 我已经想了很久了。