Clojure 如何执行超时重试的函数?
假设我使用以下代码来确保代码超时:Clojure 如何执行超时重试的函数?,clojure,timeout,future,Clojure,Timeout,Future,假设我使用以下代码来确保代码超时: (defmacro with-timeout [millis & body] `(let [future# (future ~@body)] (try (.get future# ~millis java.util.concurrent.TimeUnit/MILLISECONDS) (catch java.util.concurrent.TimeoutException x# (
(defmacro with-timeout [millis & body]
`(let [future# (future ~@body)]
(try
(.get future# ~millis java.util.concurrent.TimeUnit/MILLISECONDS)
(catch java.util.concurrent.TimeoutException x#
(do
(future-cancel future#)
nil)))))
现在,我想让它在5秒间隔后重试3次(如果超时)。我是在TimeoutException
上写的,还是用其他方式写的
我的问题是:如何执行超时重试的函数?这里有一个使用core.async的解决方案。它非常幼稚,因为它不处理错误处理。我也不确定它是否在超时时完全退出go调用
(ns async
(:require [clojure.core.async :as a]))
(defmacro with-timeout [millis & body]
`(loop [tries# 0]
(if (> tries# 3)
(throw (Exception. "Timed out. (3)"))
(let [result# (a/alt!!
(a/go ~@body) ([v# ch] v#)
(a/timeout ~millis) :async/timed-out)]
(if (= result# :async/timed-out)
(recur (inc tries#))
result#)))))
deref
有一个接受超时的变量。使用它,我们可以在不使用Java互操作的情况下实现带超时的
(defmacro with-timeout [millis & body]
`(loop [tries# 3]
(if (pos? tries#)
(let [future# (future ~@body)
result# (deref future# ~millis ::timeout)]
(if (= result# ::timeout)
(do (future-cancel future#)
(recur (dec tries#)))
result#)))))
(这不是100%的“卫生”,因为::timeout
sentinel值理论上可能与正文
表单返回的值冲突。)