Guarded execution — bounded futures/pool tasks with cleanup hooks.
Extends hive-weave.safe and hive-weave.pool with two missing
pieces for production runs:
:on-cancel — a 0-arg cleanup thunk invoked when the task is
killed by timeout. Runs on a separate cleanup pool so a hung
task body can't block its own cleanup. Capped by
:cleanup-timeout-ms. Used to release resources the task held
(datahike connections, LSP probes, scan-state atoms, file locks).
:alert! — an injectable 1-arg fn invoked with a structured event
map on timeout or exception. Keeps hive-weave decoupled from
hive-events — callers wire their own emitter (telemetry, hivemind
shout, dashboard, ...). When omitted, no alert side-effect runs.
Failure mode: fail loud — every guarded call returns a hive-dsl Result. Callers must explicitly opt out via their own try/catch if they want exceptions to surface raw.
Quick reference: (require '[hive-weave.guarded :as wg])
(wg/guarded-future-call {:timeout-ms 60000 :name "carto-scan-hive-knowledge" :on-cancel (fn [] (reset-scan-state! :hive-knowledge)) :alert! (fn [ev] (events/emit! [:weave/task-killed ev]))} (fn [] (run-scan-async! [:hive-knowledge])))
(wg/guarded-await! my-pool (fn [] (long-running-write)) {:timeout-ms 30000 :name "datahike-write" :on-cancel (fn [] (reopen-conn!)) :alert! telemetry-emit})
Guarded execution — bounded futures/pool tasks with cleanup hooks.
Extends `hive-weave.safe` and `hive-weave.pool` with two missing
pieces for production runs:
- `:on-cancel` — a 0-arg cleanup thunk invoked when the task is
killed by timeout. Runs on a *separate* cleanup pool so a hung
task body can't block its own cleanup. Capped by
`:cleanup-timeout-ms`. Used to release resources the task held
(datahike connections, LSP probes, scan-state atoms, file locks).
- `:alert!` — an injectable 1-arg fn invoked with a structured event
map on timeout *or* exception. Keeps `hive-weave` decoupled from
`hive-events` — callers wire their own emitter (telemetry, hivemind
shout, dashboard, ...). When omitted, no alert side-effect runs.
Failure mode: fail loud — every guarded call returns a hive-dsl
Result. Callers must explicitly opt out via their own try/catch if
they want exceptions to surface raw.
Quick reference:
(require '[hive-weave.guarded :as wg])
(wg/guarded-future-call
{:timeout-ms 60000
:name "carto-scan-hive-knowledge"
:on-cancel (fn [] (reset-scan-state! :hive-knowledge))
:alert! (fn [ev] (events/emit! [:weave/task-killed ev]))}
(fn [] (run-scan-async! [:hive-knowledge])))
(wg/guarded-await!
my-pool
(fn [] (long-running-write))
{:timeout-ms 30000
:name "datahike-write"
:on-cancel (fn [] (reopen-conn!))
:alert! telemetry-emit})(guarded-await! exec
f
{:keys [timeout-ms name on-cancel cleanup-timeout-ms alert!]
:or {name "guarded" cleanup-timeout-ms 5000}})Pool-bound counterpart to guarded-future-call. Submits f to
pool (a java.util.concurrent.ThreadPoolExecutor from
hive-weave.pool/make-pool) and blocks up to :timeout-ms. Same
timeout / cancel / alert / cleanup contract as
guarded-future-call, plus pool-stats embedded in the alert event
so callers can see saturation when timeouts cluster.
Options: see guarded-future-call. Additionally:
:pool — required (the ThreadPoolExecutor).
Pool-bound counterpart to `guarded-future-call`. Submits `f` to `pool` (a `java.util.concurrent.ThreadPoolExecutor` from `hive-weave.pool/make-pool`) and blocks up to `:timeout-ms`. Same timeout / cancel / alert / cleanup contract as `guarded-future-call`, plus pool-stats embedded in the alert event so callers can see saturation when timeouts cluster. Options: see `guarded-future-call`. Additionally: :pool — required (the ThreadPoolExecutor).
(guarded-future opts & body)Macro form of guarded-future-call. Body is wrapped as the thunk.
(guarded-future {:timeout-ms 60000 :name "scan" :on-cancel #(reset-state!) :alert! emit-event} (run-scan! ...))
Macro form of guarded-future-call. Body is wrapped as the thunk.
(guarded-future {:timeout-ms 60000 :name "scan"
:on-cancel #(reset-state!)
:alert! emit-event}
(run-scan! ...))(guarded-future-call {:keys [timeout-ms name on-cancel cleanup-timeout-ms
alert!]
:or {name "guarded" cleanup-timeout-ms 5000}}
f)Run f in a future under :timeout-ms. On timeout: future-cancel
(interrupt), submit :on-cancel to the cleanup pool, fire :alert!,
return (r/err :weave/timeout {...}). On exception: fire :alert!,
return (r/err :weave/exception {...}). Otherwise (r/ok value).
Options: :timeout-ms — required, pos-int. :name — diagnostic label (default "guarded"). :on-cancel — 0-arg cleanup thunk; only fires on timeout. :cleanup-timeout-ms — wall-time cap on :on-cancel (default 5000). :alert! — (event-map) -> any. Event keys: :event :weave/task-killed | :weave/task-failed :name :timeout-ms :elapsed-ms :reason :cleanup-result (only on timeout) :exception (only on :weave/task-failed)
Run `f` in a future under `:timeout-ms`. On timeout: future-cancel
(interrupt), submit `:on-cancel` to the cleanup pool, fire `:alert!`,
return `(r/err :weave/timeout {...})`. On exception: fire `:alert!`,
return `(r/err :weave/exception {...})`. Otherwise `(r/ok value)`.
Options:
:timeout-ms — required, pos-int.
:name — diagnostic label (default "guarded").
:on-cancel — 0-arg cleanup thunk; only fires on timeout.
:cleanup-timeout-ms — wall-time cap on :on-cancel (default 5000).
:alert! — (event-map) -> any. Event keys:
:event :weave/task-killed | :weave/task-failed
:name :timeout-ms :elapsed-ms :reason
:cleanup-result (only on timeout)
:exception (only on :weave/task-failed)(with-guarded-await pool opts & body)Macro form of guarded-await!. Submits body to pool with cleanup + alert hooks.
(with-guarded-await my-pool {:timeout-ms 60000 :name "datahike-tx" :on-cancel #(reopen-conn!) :alert! emit-event} (transact! ...))
Macro form of guarded-await!. Submits body to pool with cleanup +
alert hooks.
(with-guarded-await my-pool
{:timeout-ms 60000
:name "datahike-tx"
:on-cancel #(reopen-conn!)
:alert! emit-event}
(transact! ...))cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |