Module: Takagi::Hooks

Defined in:
lib/takagi/hooks.rb

Overview

Lightweight hook dispatcher used by the plugin system to observe internal events.

Hooks are intentionally simple: subscribe with a callable, emit with a hash payload. Errors in subscribers are caught and logged to avoid cascading failures.

Class Method Summary collapse

Class Method Details

.emit(event, payload = {}) ⇒ Object

Emit an event with a payload hash to all subscribers.

Parameters:

  • event (Symbol)
  • payload (Hash) (defaults to: {})


49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/takagi/hooks.rb', line 49

def emit(event, payload = {})
  if event_bus_ready?
    Takagi::EventBus.publish(hook_address(event), payload, freeze_body: false, scope: Takagi::EventBus::Scope::LOCAL)
  else
    handlers = @mutex.synchronize { @subscribers[event].dup }
    return if handlers.empty?

    handlers.each do |handler|
      handler.call(payload)
    rescue StandardError => e
      begin
        Takagi.logger.warn("Hook #{event} handler error: #{e.message}")
      rescue StandardError
        # Logger may not be initialized yet; swallow errors silently.
      end
    end
  end
end

.event_bus_ready?Boolean

Returns:

  • (Boolean)


72
73
74
75
76
77
78
79
# File 'lib/takagi/hooks.rb', line 72

def event_bus_ready?
  return false unless defined?(Takagi::EventBus)

  executor = Takagi::EventBus.instance_variable_get(:@executor) rescue nil
  return false if executor && executor.respond_to?(:running?) && !executor.running?

  true
end

.hook_address(event) ⇒ Object



68
69
70
# File 'lib/takagi/hooks.rb', line 68

def hook_address(event)
  "hooks.#{event}"
end

.subscribe(event, handler = nil) {|Hash| ... } ⇒ #call

Register a handler for a given event symbol.

Parameters:

  • event (Symbol)

    event name

  • handler (#call) (defaults to: nil)

    callable that receives payload hash

Yields:

  • (Hash)

    payload if block given instead of handler

Returns:

  • (#call)

    the handler reference (useful for unsubscribe)

Raises:

  • (ArgumentError)


19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/takagi/hooks.rb', line 19

def subscribe(event, handler = nil, &block)
  callback = handler || block
  raise ArgumentError, 'handler or block required' unless callback

  if event_bus_ready?
    Takagi::EventBus.consumer(hook_address(event), local_only: true) do |message|
      callback.call(message.body)
    end
  else
    @mutex.synchronize { @subscribers[event] << callback }
    callback
  end
end

.unsubscribe(event, handler) ⇒ Object

Remove a previously registered handler.

Parameters:

  • event (Symbol)
  • handler (#call)


37
38
39
40
41
42
43
# File 'lib/takagi/hooks.rb', line 37

def unsubscribe(event, handler)
  if event_bus_ready?
    Takagi::EventBus.unregister(handler)
  else
    @mutex.synchronize { @subscribers[event].delete(handler) }
  end
end