Class: CMDx::Callbacks
- Inherits:
-
Object
- Object
- CMDx::Callbacks
- Defined in:
- lib/cmdx/callbacks.rb
Overview
Registry of lifecycle callbacks invoked by Runtime. Callbacks can be method names (Symbols dispatched via ‘task.send`), blocks/Procs (`instance_exec`’d on the task), or arbitrary ‘#call` objects.
Each registration may carry ‘:if` / `:unless` gates (Symbol, Proc, or any `#call`-able). Gates are evaluated against the task before the callback is invoked; non-passing gates skip the callback silently.
Constant Summary collapse
- EVENTS =
Callback event names Runtime dispatches.
Set[ :before_validation, :before_execution, :around_execution, :after_execution, :on_complete, :on_interrupted, :on_success, :on_skipped, :on_failed, :on_ok, :on_ko ].freeze
Instance Attribute Summary collapse
-
#registry ⇒ Object
readonly
Returns the value of attribute registry.
Instance Method Summary collapse
-
#around(event, task, &body) { ... } ⇒ void
Wraps ‘block` with every callback registered for `event` as a nested chain (outer-first by declaration order).
-
#count ⇒ Integer
Total callbacks across all events.
-
#deregister(event, callable = nil) ⇒ Callbacks
Drops callbacks registered for ‘event`.
- #empty? ⇒ Boolean
-
#initialize ⇒ Callbacks
constructor
A new instance of Callbacks.
- #initialize_copy(source) ⇒ void
-
#process(event, task) ⇒ void
Fires each callback registered for ‘event` against `task`.
-
#register(event, callable = nil, **options, &block) { ... } ⇒ Callbacks
Adds a callback for ‘event`.
-
#size ⇒ Integer
Number of distinct events with callbacks.
Constructor Details
#initialize ⇒ Callbacks
Returns a new instance of Callbacks.
30 31 32 |
# File 'lib/cmdx/callbacks.rb', line 30 def initialize @registry = {} end |
Instance Attribute Details
#registry ⇒ Object (readonly)
Returns the value of attribute registry.
28 29 30 |
# File 'lib/cmdx/callbacks.rb', line 28 def registry @registry end |
Instance Method Details
#around(event, task, &body) { ... } ⇒ void
This method returns an undefined value.
Wraps ‘block` with every callback registered for `event` as a nested chain (outer-first by declaration order). Each callback receives a continuation it must invoke exactly once: Symbol callbacks get it as their block (use `yield`); Procs/blocks are `instance_exec`’d on the task with ‘(task, continuation)`; arbitrary callables receive `(task, continuation)`. Gates skip individual links silently while still running the body.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/cmdx/callbacks.rb', line 137 def around(event, task, &body) callbacks = registry[event] return yield if callbacks.nil? || callbacks.empty? callbacks.reverse_each.reduce(body) do |succ, (callable, )| lambda do next succ.call unless Util.satisfied?([:if], [:unless], task) called = false cont = lambda do called = true succ.call end invoke(callable, task, cont, &cont) called || raise(CallbackError, "#{event} callback did not invoke its continuation") end end.call end |
#count ⇒ Integer
Returns total callbacks across all events.
101 102 103 |
# File 'lib/cmdx/callbacks.rb', line 101 def count registry.each_value.sum(&:size) end |
#deregister(event, callable = nil) ⇒ Callbacks
Drops callbacks registered for ‘event`. With no `callable`, removes every callback for `event`. With a `callable`, removes only the entries whose callback matches `callable` by `==` (works for Symbol method names, classes/modules, and any callable held by reference). When the last entry for `event` is removed, the key itself is dropped.
77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/cmdx/callbacks.rb', line 77 def deregister(event, callable = nil) raise ArgumentError, "unknown event #{event.inspect}, must be one of #{EVENTS.join(', ')}" unless EVENTS.include?(event) if callable.nil? registry.delete(event) elsif (entries = registry[event]) entries.reject! { |cb, _opts| cb == callable } registry.delete(event) if entries.empty? end self end |
#empty? ⇒ Boolean
91 92 93 |
# File 'lib/cmdx/callbacks.rb', line 91 def empty? registry.empty? end |
#initialize_copy(source) ⇒ void
This method returns an undefined value.
36 37 38 |
# File 'lib/cmdx/callbacks.rb', line 36 def initialize_copy(source) @registry = source.registry.transform_values(&:dup) end |
#process(event, task) ⇒ void
This method returns an undefined value.
Fires each callback registered for ‘event` against `task`. Skips any callback whose `:if`/`:unless` gates fail.
112 113 114 115 116 117 118 119 120 121 |
# File 'lib/cmdx/callbacks.rb', line 112 def process(event, task) callbacks = registry[event] return if callbacks.nil? || callbacks.empty? callbacks.each do |callable, | next unless Util.satisfied?([:if], [:unless], task) invoke(callable, task) end end |
#register(event, callable = nil, **options, &block) { ... } ⇒ Callbacks
Adds a callback for ‘event`.
52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/cmdx/callbacks.rb', line 52 def register(event, callable = nil, **, &block) callback = callable || block if callable && block raise ArgumentError, "provide either a callable or a block, not both" elsif !callback.is_a?(Symbol) && !callback.respond_to?(:call) raise ArgumentError, "callback must be a Symbol or respond to #call" elsif !EVENTS.include?(event) raise ArgumentError, "unknown event #{event.inspect}, must be one of #{EVENTS.join(', ')}" end (registry[event] ||= []) << [callback, .freeze] self end |
#size ⇒ Integer
Returns number of distinct events with callbacks.
96 97 98 |
# File 'lib/cmdx/callbacks.rb', line 96 def size registry.size end |