Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Hook Protocol

Every hook returns a map. Missing keys keep the current value.

Invocation Pipeline

flowchart LR
    Before["before-fn"] --> Fn[":fn"]
    Fn --> After["after-fn"]
    Fn -->|"throws"| OnError["on-error-fn"]
    OnError -->|":result"| Fallback(["Fallback result"])
    OnError -->|":error"| Rethrow(["Re-throw"])
    OnError -->|":fn / :args"| Retry["Retry with new fn/args"]
    Before -->|":result"| ShortCircuit(["Short-circuit"])

wrap-extension wires this up automatically. Direct calls via invoke-symbol-wrapper are rarely needed.

:before-fn(fn [env f args] → map)

Called before the implementation fn. Can transform inputs or short-circuit.

Return keyEffect
:envOverride env for the call
:fnOverride the implementation fn
:argsOverride the args vector
:resultShort-circuit — skip :fn entirely, return this value

:after-fn(fn [env f args result] → map)

Called after the implementation fn returns. Can transform the result.

Return keyEffect
:resultOverride the result
:env, :fn, :argsOverride (rarely needed)

:on-error-fn(fn [err env f args] → map)

Called when :fn throws. The return map determines recovery:

Return keyEffect
:resultUse this as the fallback result
:errorThrow this error instead
:fn / :argsRetry — re-invoke with (possibly different) fn and args

If no :on-error-fn is defined, the original exception propagates.

Observability

All hook invocations are logged via taoensso.telemere/log!:

LevelEvent
:infoSymbol invocation start/end with elapsed ms
:debugIndividual hook start/end (before, after, fn return)
:warn:fn threw; :on-error-fn invoked

Log data includes :ext (namespace), :sym (symbol name), :phase, and :ms (elapsed milliseconds).