Railway-oriented combinators for agent operations.
Extends hive-dsl.result with additional primitives needed by the agent loop, swarm infrastructure, and CRDT-backed shared state:
tap — side-effecting inspection (identity for Result value) recover — Err -> Result via a recovery fn retry-on — repeat a Result-producing thunk on matching Err fan-out — run coll of 0-arg Result-thunks in parallel fan-in — combine coll<Result<a>> into Result<vector<a>> with-budget — atomically deduct cost from a budget atom before op with-persona — bind persona for the duration of op; enrich Err with-crdt — bind crdt for the duration of op (stub — full behavior in T7 once replikativ wrappers land)
Design notes:
{:ok v} or {:error k ...}).with-budget consumes budget whether the thunk returns Ok or Err —
compute was performed, account for it. Callers wanting refund-on-Err
should wrap with recover + an explicit refund.*persona* and *crdt* are thread-local dynamic vars; they do NOT
leak across future/thread boundaries unless caller uses bound-fn.Railway-oriented combinators for agent operations.
Extends hive-dsl.result with additional primitives needed by the agent
loop, swarm infrastructure, and CRDT-backed shared state:
tap — side-effecting inspection (identity for Result value)
recover — Err -> Result via a recovery fn
retry-on — repeat a Result-producing thunk on matching Err
fan-out — run coll of 0-arg Result-thunks in parallel
fan-in — combine coll<Result<a>> into Result<vector<a>>
with-budget — atomically deduct cost from a budget atom before op
with-persona — bind *persona* for the duration of op; enrich Err
with-crdt — bind *crdt* for the duration of op (stub — full
behavior in T7 once replikativ wrappers land)
Design notes:
- Every combinator returns a Result (`{:ok v}` or `{:error k ...}`).
- No exceptions cross combinator boundaries; thunks that throw are
left to the caller's own rescue/guard policy from hive-dsl.result.
- `with-budget` consumes budget whether the thunk returns Ok or Err —
compute was performed, account for it. Callers wanting refund-on-Err
should wrap with `recover` + an explicit refund.
- `*persona*` and `*crdt*` are thread-local dynamic vars; they do NOT
leak across future/thread boundaries unless caller uses `bound-fn`.Currently-bound CRDT ref. Nil outside a with-crdt scope.
T7 will define the ref shape; today it's opaque.
Currently-bound CRDT ref. Nil outside a `with-crdt` scope. T7 will define the ref shape; today it's opaque.
Currently-bound persona map. Nil outside a with-persona scope.
Currently-bound persona map. Nil outside a `with-persona` scope.
(fan-in results)Combine a collection of Results into a single Result. All Ok -> Ok of a vector of unwrapped values, order preserved. Any Err -> Err with :err/first, :err/partials, :err/oks.
Combine a collection of Results into a single Result. All Ok -> Ok of a vector of unwrapped values, order preserved. Any Err -> Err with :err/first, :err/partials, :err/oks.
(fan-out thunks)Run a collection of 0-arg Result-thunks in parallel via futures. Returns the combined Result (semantics of fan-in over the thunk results). Any exception thrown by a thunk becomes an Err via hive-dsl.result/try-effect.
Run a collection of 0-arg Result-thunks in parallel via futures. Returns the combined Result (semantics of fan-in over the thunk results). Any exception thrown by a thunk becomes an Err via hive-dsl.result/try-effect.
(recover result f)If result is Err, call (f err-map) to produce a recovery Result. f's return MUST itself be a Result; if it isn't, it's wrapped in ok. Ok results pass through unchanged.
If result is Err, call (f err-map) to produce a recovery Result. f's return MUST itself be a Result; if it isn't, it's wrapped in ok. Ok results pass through unchanged.
(retry-on thunk
{:keys [max pred backoff-ms]
:or {max 3 pred (constantly true) backoff-ms (constantly 0)}})Call (thunk) — a 0-arg fn returning a Result. If the Result is Err and
(pred err) is truthy, wait (backoff-ms attempt) and retry. Stops after
:max total attempts, returning the last Result.
Options: :max — max attempts (>= 1). Default 3. :pred — (fn [err-result] bool). Default (constantly true). :backoff-ms — (fn [attempt] ms). attempt starts at 1. Default (constantly 0).
Call (thunk) — a 0-arg fn returning a Result. If the Result is Err and (pred err) is truthy, wait (backoff-ms attempt) and retry. Stops after `:max` total attempts, returning the last Result. Options: :max — max attempts (>= 1). Default 3. :pred — (fn [err-result] bool). Default (constantly true). :backoff-ms — (fn [attempt] ms). attempt starts at 1. Default (constantly 0).
(tap result f)Call f on the Ok value for side effect; return the Result unchanged. Err results pass through without invoking f. f's return value is ignored.
Call f on the Ok value for side effect; return the Result unchanged. Err results pass through without invoking f. f's return value is ignored.
(with-budget budget-atom cost op)Atomically deduct cost from budget-atom, then run (op) — a 0-arg thunk returning a Result. If remaining < cost, returns Err :budget-exhausted (op is NOT invoked and NO deduction occurs).
budget-atom must be a plain Clojure atom holding a non-negative integer. Deduction is monotonic and safe under concurrent callers (swap-vals!).
Design: budget is consumed whether op succeeds or fails. Compute was
performed; account for it. Callers wanting refund-on-Err can compose
with recover that performs an explicit (swap! budget-atom + cost).
Atomically deduct cost from budget-atom, then run (op) — a 0-arg thunk returning a Result. If remaining < cost, returns Err :budget-exhausted (op is NOT invoked and NO deduction occurs). budget-atom must be a plain Clojure atom holding a non-negative integer. Deduction is monotonic and safe under concurrent callers (swap-vals!). Design: budget is consumed whether op succeeds or fails. Compute was performed; account for it. Callers wanting refund-on-Err can compose with `recover` that performs an explicit `(swap! budget-atom + cost)`.
(with-crdt crdt-ref op)Bind crdt to the given CRDT ref while running (op) — a 0-arg thunk returning a Result. T2 stub: simply threads the binding through. T7 will add merge hooks + reconciliation callbacks.
Bind *crdt* to the given CRDT ref while running (op) — a 0-arg thunk returning a Result. T2 stub: simply threads the binding through. T7 will add merge hooks + reconciliation callbacks.
(with-persona persona op)Bind persona to the given persona map while running (op) — a 0-arg
thunk returning a Result. If op returns Err, merge :persona/id (from
persona) into the error map so downstream observers see attribution.
persona is expected to be a map with at least :persona/id.
Bind *persona* to the given persona map while running (op) — a 0-arg thunk returning a Result. If op returns Err, merge `:persona/id` (from persona) into the error map so downstream observers see attribution. persona is expected to be a map with at least `:persona/id`.
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 |