Я ищу обходной путь построения сервера потоковой передачи. Конкретная проблема, с которой я борюсь, - это как отправить значения от одного поставщика (веб-камеры) неопределенному количеству потоков (подключенных клиентов). Очевидно, что когда клиент подключается, его не интересует полный видеофайл с веб-камеры, в основном ему нужно отправить заголовок, а затем все пакеты, поступающие с веб-камеры в этот момент.
В прямой Java, я думаю, это будет легко. Когда клиент подключается, добавляйте соединение в массив, когда он отключается, удаляйте соединение из массива, и всякий раз, когда приходит новый пакет с веб-камеры, отправляйте его каждой записи в массиве. Заблокируйте массив так, чтобы мы либо добавляли / удаляли записи, либо проходили через него для отправки пакетов. Конечно, мы могли бы построить то же самое в ближайшем будущем, но это звучит действительно злобно.
В многопоточной архитектуре передачи сообщений это звучит одинаково просто.
Единственное решение, которое я мог придумать в ближайшем будущем, - это ленивая последовательность обещаний. Действительно, это работает, но мне было интересно, есть ли другой способ, который приводит к более чистому коду и большему количеству clojure-zen:)
Просто для иллюстрации: упрощенная задача с обещаниями и атомами:
Одна функция провайдера, генерирующая данные, одна нить, которая читает эти данные. Позже создаются некоторые другие потоки, которые хотели бы получить данные из этого первого потока, но не могут добраться до них.
(defn provider []
(lazy-seq
(do
(Thread/sleep 100)
(cons (rand) (provider)))))
(def printer (agent nil))
(defn log [& line]
(send-off printer (fn [x] (apply println line))))
(def promises (atom (repeatedly promise)))
(defn client-connected-thread [x input]
(log "Client connection " x " is connected with the provider and just received" @(first input))
(recur x (rest input)))
(.start (Thread. (fn []
(loop [stream (provider)]
(when-let [item (first stream)]
(log "I received " item", will share now")
(deliver (first @promises) item)
(swap! promises rest))
(recur (rest stream))))))
(Thread/sleep 300)
(.start (Thread. #(client-connected-thread 1 @promises)))
(Thread/sleep 100)
(.start (Thread. #(client-connected-thread 2 @promises)))
(Thread/sleep 50)
(.start (Thread. #(client-connected-thread 3 @promises)))
Итак, в основном вопрос: это правильный способ решения этой проблемы?
Кроме того, мы говорим о сервере потокового мультимедиа, поэтому функция провайдера будет предоставлять десятки тысяч элементов в секунду, и может быть подключено 10 клиентов. Система обещания предназначена для такого интенсивного использования?