Возможно, вы могли бы использовать функцию seque
? Цитирование (doc seque)
:
clojure.core/seque
([s] [n-or-q s])
Creates a queued seq on another (presumably lazy) seq s. The queued
seq will produce a concrete seq in the background, and can get up to
n items ahead of the consumer. n-or-q can be an integer n buffer
size, or an instance of java.util.concurrent BlockingQueue. Note
that reading from a seque can block if the reader gets ahead of the
producer.
Я имею в виду ленивую последовательность получения элементов очереди по сети; Вы обернули бы это в seque
, поместили бы это в Ссылку, и рабочие Агенты потребляли предметы из этого seque
. seque
возвращает что-то, что выглядит как обычный seq с точки зрения вашего кода, а магия очереди происходит прозрачным образом. Обратите внимание, что если последовательность, которую вы помещаете внутрь, является чанковой, то она все равно будет принудительно чанковой за один раз. Также обратите внимание, что первоначальный вызов самого seque
, кажется, блокируется до тех пор, пока не будет получен исходный элемент или два (или чанк, в зависимости от случая; я думаю, что это больше связано с тем, как работают ленивые последовательности, чем с самим seque
). хотя).
Набросок кода ( действительно схематичный, совсем не тестировался):
(defn get-queue-items-seq []
(lazy-seq
(cons (get-queue-item)
(get-queue-items-seq))))
(def task-source (ref (seque (get-queue-items-seq))))
(defn do-stuff []
(let [worker (agent nil)]
(if-let [result
(dosync
(when-let [task (first @task-source)]
(send worker (fn [_] (do-stuff-with task)))))]
(do (await worker)
;; maybe do something with worker's state
(do-stuff))))) ;; continue working
(defn do-lots-of-stuff []
(let [fs (doall (repeatedly 20 #(future (do-stuff))))]
fs)))
На самом деле вы, вероятно, захотите более сложного производителя элемента очереди seq, чтобы вы могли попросить его прекратить производство новых элементов (необходимость, если все это должно быть в состоянии изящно завершиться; фьючерсы умрут когда источник задачи иссякнет, используйте future-done?
, чтобы увидеть, сделали ли они это уже). И это только то, что я вижу на первый взгляд ... Я уверен, что здесь есть еще кое-что для полировки. Я думаю, что общий подход будет работать, хотя.