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
-
#key?(event) ⇒ Boolean
Whether a callback is registered under ‘name`.
-
#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.
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/cmdx/callbacks.rb', line 156 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, <<~MSG.chomp) #{event} callback did not invoke its continuation. See https://drexed.github.io/cmdx/callbacks/#around_execution-the-wrap-the-whole-thing-hook MSG end end.call end |
#count ⇒ Integer
Returns total callbacks across all events.
118 119 120 |
# File 'lib/cmdx/callbacks.rb', line 118 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.
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/cmdx/callbacks.rb', line 83 def deregister(event, callable = nil) unless EVENTS.include?(event) raise ArgumentError, <<~MSG.chomp unknown callback event #{event.inspect}, must be one of #{EVENTS.to_a.inspect}. See https://drexed.github.io/cmdx/callbacks/#what-callbacks-exist MSG end 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
108 109 110 |
# File 'lib/cmdx/callbacks.rb', line 108 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 |
#key?(event) ⇒ Boolean
Returns whether a callback is registered under ‘name`.
103 104 105 |
# File 'lib/cmdx/callbacks.rb', line 103 def key?(event) registry.key?(event) 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.
129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/cmdx/callbacks.rb', line 129 def process(event, task) return if empty? 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 66 67 68 69 70 71 |
# File 'lib/cmdx/callbacks.rb', line 52 def register(event, callable = nil, **, &block) callback = callable || block if callable && block raise ArgumentError, "callback: provide either a callable or a block, not both" elsif !callback.is_a?(Symbol) && !callback.respond_to?(:call) raise ArgumentError, <<~MSG.chomp callback must be a Symbol or respond to #call (got #{callback.class}). See https://drexed.github.io/cmdx/callbacks/#how-do-i-register-one MSG elsif !EVENTS.include?(event) raise ArgumentError, <<~MSG.chomp unknown callback event #{event.inspect}, must be one of #{EVENTS.to_a.inspect}. See https://drexed.github.io/cmdx/callbacks/#what-callbacks-exist MSG end (registry[event] ||= []) << [callback, .freeze] self end |
#size ⇒ Integer
Returns number of distinct events with callbacks.
113 114 115 |
# File 'lib/cmdx/callbacks.rb', line 113 def size registry.size end |