Module: Protege::Subscribers::HookDispatcher
- Extended by:
- HookDispatcher
- Included in:
- HookDispatcher
- Defined in:
- lib/protege/subscribers/hook_dispatcher.rb
Overview
The hooks-only event dispatcher — the runtime that activates hooks against the engine's event
stream. Installed once at boot by Protege::Engine (a peer of Subscribers::Tracing and
Subscribers::IntrospectionBroadcaster); it subscribes one dispatcher per Protege::Event.all
that, when an event fires, runs every registered hook's matching handlers.
Kept separate from the hook contract (+Protege::HookMixin+, the +on+/+stateful+ DSL a hook
declares with): this module only reads that contract off each hook class
(+hook_class.subscriptions+, hook_class.stateful?) — a one-way dependency, dispatcher → contract.
Hooks are pulled live from Hook.descendants (via #registered) when an event fires, so a Zeitwerk
reload just changes the descendant set; the dispatchers are stable and never need re-subscribing.
Handler blocks run via instance_exec on a hook instance — fresh per event for stateless hooks, or
a shared per-run instance (keyed by correlation_id) for stateful ones — inside a rescue that
logs and swallows, so one hook can never break inference or a sibling hook.
Constant Summary collapse
- TERMINAL_EVENTS =
Event classes that end a run; a stateful hook's per-run instance is evicted after these fire. Includes
InferenceFailedEventso a run that raises before completing never leaves a stale instance behind. [ InferenceCompletedEvent, InferenceFailedEvent, InferenceMaxTurnsReachedEvent ].freeze
Instance Method Summary collapse
-
#install! ⇒ void
Wire the event bus to hook dispatch — the subscriber's
install!contract. -
#reset! ⇒ void
Detach every dispatcher and drop all per-run state — the subscriber's
reset!contract, for boot re-wiring and tests.
Instance Method Details
#install! ⇒ void
This method returns an undefined value.
Wire the event bus to hook dispatch — the subscriber's install! contract. Called once at boot
by the engine; idempotent, so a repeat call is a no-op until #reset! runs. Installs one
dispatcher per Protege::Event.all that fans the event out to every registered hook's handlers.
48 49 50 51 52 53 54 55 56 |
# File 'lib/protege/subscribers/hook_dispatcher.rb', line 48 def install! @install_mutex.synchronize do return unless @handles.empty? @handles = Protege::Event.all.map do |event_class| event_class.subscribe { |event| dispatch(event_class, event) } end end end |
#reset! ⇒ void
This method returns an undefined value.
Detach every dispatcher and drop all per-run state — the subscriber's reset! contract, for boot
re-wiring and tests.
62 63 64 65 66 67 68 |
# File 'lib/protege/subscribers/hook_dispatcher.rb', line 62 def reset! @install_mutex.synchronize do @handles.each { |handle| ActiveSupport::Notifications.unsubscribe(handle) } @handles = [] @instances_mutex.synchronize { @instances.clear } end end |