Skip to main content

Module hooks

Module hooks 

Source
Expand description

Observability for the resolver pipeline (chartml 5.0 phase 3c).

Consumers implement ResolverHooks and pass it to ChartML::set_hooks; the resolver fires events at every pipeline decision point so consumers can wire progress bars, cache-hit telemetry, custom error recovery, etc. without reading private resolver state.

Mirrors the JS PLUGIN_HOOKS.md semantics with a Rust-idiomatic trait-based API.

§Important constraints (read before implementing)

  • Hooks must be panic-free. std::panic::catch_unwind does not work across .await points and is not available on WASM at all. We do not try to catch hook panics — if a hook panics on native the spawned task crashes; on WASM the whole module typically aborts. Hooks should always catch their own errors internally.
  • Hooks must never acquire any lock the resolver holds. Re-entering the resolver from within a hook is explicitly unsupported. The fire-and-forget spawn in spawn_hook mitigates this in practice because the hook runs on a separate task after the resolver’s locks are released, but a hook that takes its own lock that the resolver later wants will still deadlock.
  • Hook events are fire-and-forget on the runtime — the resolver does NOT await hook delivery. There is no ordering guarantee between events: events for the same source may arrive in any order, and events across sources interleave freely. Each spawn_hook call submits an independent task with no happens-before relationship to subsequent emits, so consumers that need a stable order must impose it themselves (e.g. by sequence-stamping events on the way out of the hook).
  • Hook errors are never propagated. The trait methods return () so there’s no Result to swallow; if tokio::spawn / spawn_local itself fails, the failure is logged via tracing::warn and not surfaced.

Structs§

CacheHitEvent
Cache-hit notification.
CacheMissEvent
Cache-miss notification.
ErrorEvent
Error notification — fires when a provider call (or transform, when emitted from ChartML::transform) returns an error. The error is stringified at the emission site so consumers don’t need to know the concrete error type.
NullHooks
Zero-cost default impl. Used by the resolver when no hook has been registered. Public so consumers writing tests can opt into “explicitly no hooks” without inventing a noop type.
ProgressEvent
Generic progress notification — fires at the start of each pipeline phase and again on completion. loaded / total are populated when a provider surfaces them; otherwise both are None.

Enums§

CacheTier
Cache tier the entry was served from on a CacheHitEvent.
MissReason
Why a CacheMissEvent fired.
Phase
Pipeline phase a ProgressEvent or ErrorEvent originated from.

Traits§

ResolverHooks
Observability trait. Consumers implement only the methods they care about; every default is a no-op so partial impls are zero-cost.

Type Aliases§

HooksRef
Shared handle to a registered hook impl. Arc on native (so spawned hook tasks can hold a clone without lifetime juggling), Rc on WASM (single-threaded; matches the resolver’s SharedRef story).