ReactorHandlers
in package
Declarative reactor handler binding — CONTRACT.md §22.14.
ReactorServer takes one callable from an event to one answer, which
is the right shape for the wire and the wrong shape for the code. A reactor
registered for three events opens with a match ($event->event), and that
match carries two defects.
The first is cheap: a misspelled event name is a valid string, matches no arm,
and is discovered as an event that never fires. The second is not. It is the
default arm, which is almost always written ReactorAnswer::allow(). That
answers on behalf of code that never ran — the defect §22.10 rule 2 forbids
the runtime from committing, relocated into user code where the rule does
not reach it. An operator who set fail_closed on a registration has it
defeated by a default arm in a file they never read.
This class is the declarative form, in the spirit of §11's RequireAccess: mark the methods, collect them, hand the result to ReactorServer.
final class ClaimsReactor
{
#[OnReactorEvent(ReactorEvents::TOKEN_PRE_ISSUE)]
public function enrich(ReactorEvent $event): ReactorAnswer { ... }
#[OnReactorEvent(ReactorEvents::LOGIN_POST_AUTH)]
public function screen(ReactorEvent $event): ReactorAnswer { ... }
}
$handlers = ReactorHandlers::of(new ClaimsReactor());
$server = new ReactorServer($config, $transport, $handlers->handler());
It is pure sugar (§22.14 rule 1): what self::handler() returns is exactly the callable ReactorServer already accepts. It opens nothing, verifies nothing, signs nothing, and does not filter a patch (§22.10 rule 3).
Table of Contents
Methods
- bind() : self
- Bind $handler to $event without an attribute.
- events() : array<int, string>
- The bound event names, in binding order.
- handler() : callable(ReactorEvent): ReactorAnswer
- Compose the bindings into the callable {@see ReactorServer} accepts.
- of() : self
- Collect every `#[OnReactorEvent]`-marked public method on $sources.
Methods
bind()
Bind $handler to $event without an attribute.
public
bind(string $event, callable(ReactorEvent): ReactorAnswer $handler) : self
The imperative half of the same thing, for handlers that are closures rather than methods. Governed by every §22.14 rule identically.
Parameters
- $event : string
- $handler : callable(ReactorEvent): ReactorAnswer
Tags
Return values
selfevents()
The bound event names, in binding order.
public
events() : array<int, string>
Pass them to ReactorEvents::defaultFailurePolicy() to see what an unreachable reactor costs — the strictest default among them (§22.8) — derived from the code that handles the events rather than from a restatement of the registration.
Return values
array<int, string>handler()
Compose the bindings into the callable {@see ReactorServer} accepts.
public
handler() : callable(ReactorEvent): ReactorAnswer
Tags
Return values
callable(ReactorEvent): ReactorAnswerof()
Collect every `#[OnReactorEvent]`-marked public method on $sources.
public
static of(object ...$sources) : self
Methods are bound to their instance, so a class-based reactor keeps its state and its constructor-injected collaborators.
Parameters
- $sources : object
-
Objects whose public methods carry the attribute.