如何从Clojure期货中的错误获取堆栈跟踪?

Expez

我有一些非常独立的任务,这些都是我使用期货衍生出来的。这些任务通过core.async / chan将某些事件传达回主应用程序,或者只是与数据库对话。

这些期货中的一些现在正在默默地失败。我的日志或std {out,err}中没有堆栈跟踪。我试过将期货所调用的fns中的代码与

(try (do-stuff)
  (catch Exception e
    (log/error e))

只是为了将一些输出输出到我的日志中,但是-令人惊讶的是-无效。

我唯一的选择是循环启动另一个线程吗?

(let [m (Thread/getAllStackTraces)]
    (doseq [e (.entrySet m)]
      (log/error (.toString (.getKey e)))
      (doseq [s (.getValue e)]
        (log/error " " (.toString s)))))

这是否表明我根本不应该使用期货?即使没有必要向这些代理发送任何消息,我也应该使用代理吗?

康拉德·加鲁斯

该行为与Java非常相似Future在将来的块中,可能会引发并捕获异常,并且其行为与您期望的一样。如果未捕获到异常,则无法将其Future重新抛出到调用线程中。它只会以ExecutionException您真正获得其价值的形式进行这对应于Clojure中的deref。

让我们创建一个抛出一些东西的函数:

(defn die [] (throw (RuntimeException.)))

如果我将来将它包装起来,它会很好地工作:

user=> (def x (future (die)))
#'user/x
; Note: No exception here
user=> @x
RuntimeException   user/die (NO_SOURCE_FILE:1)
; Bam! Exception thrown on deref, think of it as
; ExecutionException when getting failed future's value in Java

因此,您可以在deref上捕获此异常:

user=> (def x (future (die)))
#'user/x
(try @x (catch Exception e (println "Caught ya")))
Caught ya
nil

或者,您可以在将来将其捕获:

user=> (def x 
  #_=>   (future 
  #_=>     (try (die)
  #_=>       (catch Exception e
  #_=>         (print "Caught ya!")
  #_=>         "Something"))))
#'user/x
Caught ya
user=> @x
"Something"

请注意,在这种情况下,在后台线程上发生错误时,在取消引用之前,它将如何立即打印“ Caught ya”。然后在deref上返回将来catch块返回的值。

再次强调的是,它的工作原理与Java期货几乎相同。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章