Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何最好地关闭clojure core.async进程管道_Clojure_Core.async - Fatal编程技术网

如何最好地关闭clojure core.async进程管道

如何最好地关闭clojure core.async进程管道,clojure,core.async,Clojure,Core.async,我有一个clojure处理应用程序,它是一个通道管道。每个处理步骤都以异步方式进行计算(即使用http工具包或其他方式发出http请求),并将其结果放在输出通道上。这样,下一步可以从该通道读取数据并进行计算 我的主要功能如下所示 (defn -main [args] (-> file/tmp-dir (schedule/scheduler) (search/searcher) (process/resultprocessor) (buy/buyer) (report/

我有一个clojure处理应用程序,它是一个通道管道。每个处理步骤都以异步方式进行计算(即使用http工具包或其他方式发出http请求),并将其结果放在输出通道上。这样,下一步可以从该通道读取数据并进行计算

我的主要功能如下所示

(defn -main [args]
 (-> file/tmp-dir
  (schedule/scheduler)
  (search/searcher)
  (process/resultprocessor)
  (buy/buyer)
  (report/reporter)))
目前,调度器步骤驱动管道(它没有输入通道),并为链提供工作负载

当我在REPL中运行此命令时:

(-main "some args")
由于调度器的无限性,它基本上永远运行。更改此体系结构的最佳方法是什么,以便我可以从REPL关闭整个系统?关闭每个通道是否意味着系统终止


一些广播频道会有帮助吗?

你可以让你的调度器
alts/
高度在终止通道和管道的输入通道上:

(def kill-channel (async/chan))

(defn scheduler [input output-ch kill-ch]
  (loop []
    (let [[v p] (async/alts!! [kill-ch [out-ch (preprocess input)]]
                  :priority true)]
      (if-not (= p kill-ch)
        (recur))))
kill channel
上输入一个值将终止循环

从技术上讲,您也可以使用
output ch
来控制流程(put to closed channels return
false
),但我通常会发现显式终止通道更干净,至少对于顶级管道是如此


为了使事情同时变得更加优雅和方便使用(无论是在REPL还是在生产中),您可以使用,启动调度程序循环(在一个单独的线程上)和
assoc
在组件的
start
方法中将kill通道连接到组件上,然后
关闭组件的
停止
方法中的终止通道(从而终止循环)。

我建议使用类似的方法来处理系统设置。它确保您可以在REPL中轻松启动和停止系统。使用该库,您可以将其设置为每个处理步骤都是一个组件,每个组件都可以在其
start
stop
协议中处理通道的设置和拆卸。此外,您可能还可以为每个要实现的组件创建一个
IStream
协议,并使每个组件依赖于实现该协议的组件。它为您带来了一些非常简单的模块化

您将得到一个如下所示的系统:

(component/system-map
 :scheduler (schedule/new-scheduler file/tmp-dir)
 :searcher  (component/using (search/searcher)
                             {:in :scheduler})
 :processor (component/using (process/resultprocessor)
                             {:in :searcher})
 :buyer     (component/using (buy/buyer)
                             {:in :processor})
 :report    (component/using (report/reporter)
                             {:in :buyer}))
这种方法的一个优点是,如果组件也依赖于通道,则可以轻松添加组件。例如,如果每个组件使用内部
mult
上的
tap
创建其输出通道,则可以仅通过将处理器作为依赖项的日志组件为处理器添加记录器

 :processor (component/using (process/resultprocessor)
                             {:in :searcher})
 :processor-logger (component/using (log/logger)
                                    {:in processor})

我建议你也看一下他是如何工作的。

你应该考虑使用,这取决于建模你的“流水线”元素,因为这样你可以把你的逻辑单体建模为“类”,意思是你可以控制结构和破坏(开始/停止)。它们中的每一个都有逻辑。

这也不幸地杀死了REPL。我将尝试组件方法