可以自动重启失败的Clojure代理吗?

时间:2017-06-19 18:32:00

标签: clojure

我正在尝试了解是否可以自动重启失败的代理。从我的代码示例中看不出来:

(def a (agent 0))

(defn h [a e]
  (restart-agent a 0))

(set-error-handler! a h)

(send a inc) 
;; 1

(send a #(/ % 0)) 
;; error handler h will be triggered

(send a inc) 
;; ArithmeticException Divide by zero (agent didn't restart)

我错过了什么吗?

2 个答案:

答案 0 :(得分:0)

似乎是一个未记录的要求,restart-agent在与错误处理程序不同的线程中调用:

(dotest
  (future (println "running in a thread..."))
  (let [agt (agent 0)

        ; This doesn't work
        h01 (fn [a e]
              (println :10 "agent error found:" )
              (println :11 "restarting agent...")
              (restart-agent a 100)
              (Thread/sleep 100)
              (println :12 "agent restarted, state=" @a))

        ; This works. Need to call restart-agent in a separate thread
        h02 (fn [a e]
              (println :20 "agent error found:" )
              (future
                (println :21 "restarting agent...")
                (restart-agent a 200)
                (println :22 "agent restarted, state=" @a))) ;=> 200
  ]
    (set-error-handler! agt h02)
    (send agt inc)
    (Thread/sleep 100) (spy :01 @agt)  ;=> 1
    (Thread/sleep 100) (send agt #(/ % 0))
    (Thread/sleep 100) (spy :02 @agt)  ;=> 200
    (Thread/sleep 100) (send agt inc)
    (Thread/sleep 100) (spy :03 @agt)  ;=> 201
))

结果:

running in a thread...
:01 => 1
:20 agent error found:
:21 restarting agent...
:22 agent restarted, state= 200
:02 => 200
:03 => 201

答案 1 :(得分:0)

问题是,在你调用restart-agent时,不需要重启。您可以通过将处理程序更改为此来显示:

(defn h [a e]
  (try (restart-agent a 0)
    (catch Exception e (println e))))

抛出异常,说“代理不需要重启”。只有在处理程序运行后才执行:fail(或:continue)。

不知道你在追求什么,也许会介绍心脏起搏器?

(def a (agent 0))
(def a-pacemaker (agent nil))

(defn h [a e]
  (send a-pacemaker (fn [_] (restart-agent a 0))))

(set-error-handler! a h)