Clojure:管理单个线程

Clojure:管理单个线程,clojure,Clojure,假设我有这样一个简单的函数: (defn process-files "Take file name and read data" [file] (let [data (slurp file) rows (rest (c/parse-csv data))] (doseq [row rows] (future (call-url (nth row 3 nil))) )) 它将ID传递到调用url,然后调用cgi脚本。cgi

假设我有这样一个简单的函数:

(defn process-files
  "Take file name and read data"
  [file]
   (let [data (slurp file)
        rows (rest (c/parse-csv data))]
        (doseq [row rows]
          (future (call-url (nth row 3 nil)))
    ))
它将ID传递到调用url,然后调用cgi脚本。cgi脚本根据文档ID将文档放入队列,然后等待处理完成。出于我的目的,cgi调用中等待流程完成的部分只对通过浏览器点击服务的人感兴趣

所以我想做的是启动,比如说,100个线程,等待cgi脚本的“将文档放入队列”阶段运行足够长的时间,然后关闭这些线程(而不是坐在那里等待完成),并继续下一批100行。冲洗并重复

(shutdown agents)看起来像system.exit,因为它会杀死整个程序,甚至杀死我的repl

(future cancel)在单个线程上工作,但我不确定如何使其取消一批线程

任何见解都将不胜感激。

我认为“等待cgi脚本的“将文档放入队列”阶段运行足够长的时间”不是一个好主意。你如何定义“足够长”?您可以尝试估计它需要多长时间,并关闭或超时到端点的HTTP请求,但是如果运行CGI脚本的服务器会稍微慢一点呢

在我看来,您应该在CGI服务中公开两个独立的端点:

  • 为用户将等待处理完成的UI界面公开的
  • 一个单独的,设计为“开火并忘记”,你可以在你的场景中使用
这样的设计将使您的处理更加可靠,也将使您的客户机应用程序更加简单(线程将根据需要阻塞和等待很长时间,因此您不需要任何变通方法来以非设计的方式使用现有端点)

如果您不能或不想修改CGI端点,我将使用HTTP客户端库的超时功能。例如,您可以使用的
:socket timeout
:timeout
参数在请求级别起作用。但是,我不确定它是否总是可靠工作,因为这些超时在网络级别工作,任何接收到的字节都将重置超时计数器

您还可以使用异步客户端,在该客户端中,您将阻塞并仅等待响应10秒,然后忽略响应:


http/post
将调用服务器并返回包含响应的未来对象。您可以使用阻止并等待响应,但时间不得超过提供的超时时间(以毫秒为单位)。如果在10秒内没有响应,
:将返回超时值(您可以忽略返回值)。

通常cgi的返回部分会等待文档转换为PDF并在浏览器中显示。如果退出等待部分,后端进程仍会将转换后的文档护送到“转换后的文档”文件管理器中供最终用户使用,因此我不关心在后端等待每个文档。我只想劫持推送功能并退出。这是一个遗留系统,我们正在从中迁移,因此我们避免了对现有代码进行任何不必要的修补。前端是可预测的,每个文档大约10秒。我正在等待20。我已经添加了一个可能的解决方案,使用异步http调用和超时。谢谢。我会考虑你提到的方法。
(let [response-future (http/post "http://example.com/cgi-bin/abc")]
  (deref response-future 10000 :time-out))