我結束了滾動我自己的小型圖書館,我叫simple-queue。你可以閱讀關於GitHub的完整文檔,但這裏是完整的源代碼。 我不會保持這個答案更新,所以如果你想使用這個庫,請從GitHub獲取源代碼。
(ns com.github.bdesham.simple-queue)
(defn new-queue
"Creates a new queue. Each trigger from the timer will cause the function f
to be invoked with the next item from the queue. The queue begins processing
immediately, which in practice means that the first item to be added to the
queue is processed immediately."
[f & opts]
(let [options (into {:delaytime 1}
(select-keys (apply hash-map opts) [:delaytime])),
delaytime (:delaytime options),
queue {:queue (java.util.concurrent.LinkedBlockingDeque.)},
task (proxy [java.util.TimerTask] []
(run []
(let [item (.takeFirst (:queue queue)),
value (:value item),
prom (:promise item)]
(if prom
(deliver prom (f value))
(f value))))),
timer (java.util.Timer.)]
(.schedule timer task 0 (int (* 1000 delaytime)))
(assoc queue :timer timer)))
(defn cancel
"Permanently stops execution of the queue. If a task is already executing
then it proceeds unharmed."
[queue]
(.cancel (:timer queue)))
(defn process
"Adds an item to the queue, blocking until it has been processed. Returns
(f item)."
[queue item]
(let [prom (promise)]
(.offerLast (:queue queue)
{:value item,
:promise prom})
@prom))
(defn add
"Adds an item to the queue and returns immediately. The value of (f item) is
discarded, so presumably f has side effects if you're using this."
[queue item]
(.offerLast (:queue queue)
{:value item,
:promise nil}))
使用這個隊列,返回值的示例:
(def url-queue (q/new-queue slurp :delaytime 30))
(def github (q/process url-queue "https://github.com"))
(def google (q/process url-queue "http://www.google.com"))
q/process
到的調用將阻塞,所以會有兩個def
語句之間有30秒的延遲。
純粹使用此隊列的副作用的例子:
(defn cache-url
[{url :url, filename :filename}]
(spit (java.io.File. filename)
(slurp url)))
(def url-queue (q/new-queue cache-url :delaytime 30))
(q/add url-queue {:url "https://github.com",
:filename "github.html"}) ; returns immediately
(q/add url-queue {:url "https://google.com",
:filename "google.html"}) ; returns immediately
現在呼籲立即q/add
回報。
爲什麼你想連續輪詢,但只發送每60秒?每60秒輪詢一次會完成同樣的事情嗎? – mamboking
@maboking幾乎,是的。該方法唯一的缺點是將第一個項目添加到隊列中:如果程序需要5秒鐘才能確定第一個請求URL將會是什麼,然後它將在那裏坐下55秒直到隊列被檢查。無論如何,該計劃將會非常長時間運行,但我想這不是太多問題。 – bdesham
您是否在避免任務調度程序?例如,這個,https://github.com/zcaudate/cronj(還有一個其他庫在該回購的自述文件中) – georgek