mirror of
https://github.com/logseq/logseq.git
synced 2026-05-04 19:06:21 +00:00
enhance: c.m/backoff add :reset-flow option
We can use worker-flows/online-event-flow to trigger a retry immediately upon receiving an 'online' event, instead of waiting for the next retry delay.
This commit is contained in:
@@ -21,32 +21,55 @@
|
||||
(m/reductions {} init-value)
|
||||
(m/latest identity))))
|
||||
|
||||
(def delays (reductions * 1000 (repeat 2)))
|
||||
|
||||
(def ^:private retry-sentinel (js-obj))
|
||||
(defn backoff
|
||||
"Retry task when it throw exception `(get ex-data :missionary/retry)`"
|
||||
[delays-seq task]
|
||||
(m/sp
|
||||
(loop [[delay & rest-delays] (seq delays-seq)]
|
||||
(let [r (try
|
||||
(m/? task)
|
||||
(catch :default e
|
||||
(if (and (some-> e ex-data :missionary/retry)
|
||||
(pos-int? delay))
|
||||
(do (m/? (m/sleep delay))
|
||||
(println :missionary/retry "after" delay "ms (" (ex-message e) ")")
|
||||
retry-sentinel)
|
||||
(throw e))))]
|
||||
(if (identical? r retry-sentinel)
|
||||
(recur rest-delays)
|
||||
r)))))
|
||||
|
||||
(defn mix
|
||||
"Return a flow which is mixed by `flows`"
|
||||
[& flows]
|
||||
(m/ap (m/?> (m/?> (count flows) (m/seed flows)))))
|
||||
|
||||
(def never-flow (m/ap (m/? m/never)))
|
||||
|
||||
(def delays (reductions * 1000 (repeat 2)))
|
||||
|
||||
(def ^:private retry-sentinel (js-obj))
|
||||
(defn backoff
|
||||
"Retry task when it throw exception `(get ex-data :missionary/retry)`
|
||||
:delay-seq - retry delay-msecs
|
||||
:reset-flow - retry immediately when getting value from flow and reset delays to init state"
|
||||
[{:keys [delay-seq reset-flow]
|
||||
:or {delay-seq (take 4 delays)
|
||||
reset-flow never-flow}}
|
||||
task]
|
||||
(let [reset-flow* (mix reset-flow never-flow)]
|
||||
(m/sp
|
||||
(loop [[delay & rest-delays] (seq delay-seq)]
|
||||
(let [r (try
|
||||
(m/? task)
|
||||
(catch :default e
|
||||
(if (and (some-> e ex-data :missionary/retry)
|
||||
(pos-int? delay))
|
||||
(let [delay-or-reset
|
||||
(m/? (m/race (m/sleep delay :delay)
|
||||
(m/reduce (fn [_ r] (when r (reduced :reset))) nil
|
||||
(->> (continue-flow reset-flow*)
|
||||
(m/eduction (drop 1) (take 1))))))
|
||||
rest-delays*
|
||||
(case delay-or-reset
|
||||
:delay
|
||||
(do (println :missionary/retry "after" delay "ms (" (ex-message e) ")")
|
||||
rest-delays)
|
||||
:reset
|
||||
(do (println :missionary/retry "retry now (" (ex-message e) ")")
|
||||
delay-seq))]
|
||||
[retry-sentinel rest-delays*])
|
||||
(throw e))))]
|
||||
(if (and (vector? r)
|
||||
(first r) ;; if delete this `(first r)`,
|
||||
;; the code continues to the next line even if r=0...
|
||||
;; I suspect it's a bug in missionary.
|
||||
(identical? retry-sentinel (first r)))
|
||||
(recur (second r))
|
||||
r))))))
|
||||
|
||||
(defn clock
|
||||
"Return a flow that emits `value` every `interval-ms`."
|
||||
([interval-ms]
|
||||
|
||||
Reference in New Issue
Block a user