我想弄清楚如何最好地创建一个异步组件,或以一种组件友好的方式适应异步代码。这是我能想到的最好的,而且......它感觉不太正确。如何改进此Clojure组件+异步示例?
要义:接话,uppercase
他们和他们reverse
最后print
他们。
问题1:我不能让system
停止在最后。我期望看到个人c-chan
停止的println
,但不。
问题2:我该如何正确注射贴剂。进入producer
/consumer
fns?我的意思是,它们不是组件,我认为它们应该是而不是是组件,因为它们没有明智的生命周期。
问题3:如何处理惯用命名为a>b
,并b>c
的async/pipeline
-creating副作用? pipeline
应该是一个组件吗?
(ns pipelines.core
(:require [clojure.core.async :as async
:refer [go >! <! chan pipeline-blocking close!]]
[com.stuartsierra.component :as component]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PIPELINES
(defn a>b [a> b>]
(pipeline-blocking 4
b>
(map clojure.string/upper-case)
a>))
(defn b>c [b> c>]
(pipeline-blocking 4
c>
(map (comp (partial apply str)
reverse))
b>))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PRODUCER/CONSUMER
(defn producer [a>]
(doseq [word ["apple" "banana" "carrot"]]
(go (>! a> word))))
(defn consumer [c>]
(go (while true
(println "Your Word Is: " (<! c>)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; SYSTEM
(defn pipeline-system [config-options]
(let [c-chan (reify component/Lifecycle
(start [this]
(println "starting chan: " this)
(chan 1))
(stop [this]
(println "stopping chan: " this)
(close! this)))]
(-> (component/system-map
:a> c-chan
:b> c-chan
:c> c-chan)
(component/using {}))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; RUN IT!
(def system (atom nil))
(let [_ (reset! system (component/start (pipeline-system {})))
_ (a>b (:a> @system) (:b> @system))
_ (b>c (:b> @system) (:c> @system))
_ (producer (:a> @system))
_ (consumer (:c> @system))
_ (component/stop @system)])
编辑:
我开始思考以下,但我不能肯定它是否正常关闭...
(extend-protocol component/Lifecycle
clojure.core.async.impl.channels.ManyToManyChannel
(start [this]
this)
(stop [this]
(close! this)))
Mount + Async的一个很好的例子,就像你说的那样,对于较小的用例可能是首选。在为* this *作品安排Component之前,我实际上花了很多时间在Component *和* Mount上,也就是因为我喜欢“框架”提供的内容。对我来说,这是一个已经“买进”Component的大型系统,我真的很喜欢为组件运行一个例子,尽管我会因为这是一个很好的Mount示例而听到这个声音! (加上,我喜欢这是'引导',我打算最终切换:) –
我的意思是更小的情况是什么都没用:只是Clojure。 Mount目前在很多大型应用程序中都非常成功地使用。事实上,一周前我刚刚听到一家公司将他们的20K LOC应用程序从Component转换为Mount,并且不能更快乐。我在答案中添加了一个示例组件示例。 – tolitius
我非常感谢你们在提倡和支持'Mount'!与我对斯图尔特塞拉利昂和weavejester(詹姆斯?)对组件的看法,我怀疑他们对这个玩具问题的处理看起来更通用一些,比如'channel'或'pipeline'组件(带有'boundary's?),而不是'WordEngine',以及补救你征收的一些(否则有效的)批评。尽管如此,我们确实有权衡取舍,并且你说服我让“更多”机会,所以非常感谢!我很感激tolitius! –