Module: RubyReactor::Dsl::AsyncMacros
- Included in:
- Reactor::ClassMethods
- Defined in:
- lib/ruby_reactor/dsl/async_macros.rb
Overview
The three ways a reactor sends work out of the calling process, kept together because they are one design decision seen from three distances:
background — the rest of THIS reactor moves to a worker
(`all: true` — EVERYTHING, incl. input validation)
async_step — ONE step's work becomes its own job
async_reactor — a whole nested reactor runs independently
Mixed into Dsl::Reactor::ClassMethods.
Instance Method Summary collapse
-
#async? ⇒ Boolean
True only for the whole-reactor hand-off (
background all: true) — the entire run, including input validation, happens in a worker. -
#async_reactor(name, child_reactor_class, &block) ⇒ Object
Dispatch a whole nested reactor to run INDEPENDENTLY — linked to this one by execution id for traceability, but excluded from its compensation graph.
-
#async_step(name, impl = nil, &block) ⇒ Object
A step whose work is dispatched to its own independent worker job while this reactor keeps executing every other ready step.
-
#background(after: nil, before: nil, all: false) ⇒ Object
The single, unambiguous cut point between what runs in the calling process and what is handed to a worker.
-
#background_handoff ⇒ Object
The normalized
{ mode:, step: }pair — one reader, never a one-sidedbackground_after, so no consumer can be accidentally implemented forafter:only.
Instance Method Details
#async? ⇒ Boolean
True only for the whole-reactor hand-off (background all: true) —
the entire run, including input validation, happens in a worker.
47 48 49 |
# File 'lib/ruby_reactor/dsl/async_macros.rb', line 47 def async? background_handoff&.fetch(:mode, nil) == :all end |
#async_reactor(name, child_reactor_class, &block) ⇒ Object
Dispatch a whole nested reactor to run INDEPENDENTLY — linked
to this one by execution id for traceability, but excluded from its
compensation graph. Fire-and-forget unless a later step reads
result(:name), which blocks until the child is terminal and hands
over the child's real Success/Failure to inspect.
Contrast with compose, which runs the child inline, synchronously,
and fully wired into the parent's rollback path.
151 152 153 154 155 156 |
# File 'lib/ruby_reactor/dsl/async_macros.rb', line 151 def async_reactor(name, child_reactor_class, &block) builder = RubyReactor::Dsl::AsyncReactorBuilder.new(name, child_reactor_class, self) builder.instance_eval(&block) if block_given? steps[name] = builder.build end |
#async_step(name, impl = nil, &block) ⇒ Object
A step whose work is dispatched to its own independent worker
job while this reactor keeps executing every other ready step. Same
call shape and same block DSL as step — argument, run,
compensate, undo, retries, validators all behave identically;
only WHERE the body runs changes.
Any step reading result(:name) blocks (bounded) until the unit
finishes. A failure with no reader does NOT compensate this reactor —
compensation is opt-in, via a reader that inspects the result and
returns Failure itself.
136 137 138 139 140 141 |
# File 'lib/ruby_reactor/dsl/async_macros.rb', line 136 def async_step(name, impl = nil, &block) builder = RubyReactor::Dsl::StepBuilder.new(name, impl, self) builder.instance_eval(&block) if block_given? steps[name] = builder.build(async_dispatch: :step) end |
#background(after: nil, before: nil, all: false) ⇒ Object
The single, unambiguous cut point between what runs in
the calling process and what is handed to a worker. Replaces the
per-step async flag, where only the first flagged step ever took
effect and the rest were silently ignored, and the whole-reactor
async true flag, which named the same idea with a different word.
background after: :second # :second is the LAST step to run here
background before: :third # :third is the FIRST step in the worker
background all: true # the ENTIRE reactor runs in the worker,
# including input validation
after:/before: name one cut point from opposite sides — identical
in a linear chain, different in a DAG, where each pins the step it
names. all: names no step: there is nothing left to pin, everything
moves. Triggering is keyed to REACHING the named step (or, for all:,
to the run starting at all), not to where this declaration sits in
the class body.
32 33 34 35 36 |
# File 'lib/ruby_reactor/dsl/async_macros.rb', line 32 def background(after: nil, before: nil, all: false) point = validate_background_declaration!(after, before, all) @background_handoff = point end |
#background_handoff ⇒ Object
The normalized { mode:, step: } pair — one reader, never a one-sided
background_after, so no consumer can be accidentally implemented for
after: only. step is nil when mode is :all.
41 42 43 |
# File 'lib/ruby_reactor/dsl/async_macros.rb', line 41 def background_handoff @background_handoff end |