angzarr_client.router.decorators

Class-level decorators that stash metadata on handler classes.

Five kinds of components:

@command_handler(domain=…, state=…) @saga(name=…, source=…, target=…) @process_manager(name=…, pm_domain=…, sources=[…], targets=[…], state=…) @projector(name=…, domains=[…]) @upcaster(name=…, domain=…)

Each decorator:
  • sets cls.__angzarr_kind__ to the kind string

  • sets cls.__angzarr_meta__ to a dict of the decorator kwargs

  • raises TypeError if the class was already decorated with a different kind

Required kwargs are keyword-only with no defaults so Python raises TypeError on missing arguments — the same shape the tests rely on.

Attributes

T

F

Functions

command_handler(→ Callable[[T], T])

Mark a class as a command handler (aggregate) for domain.

saga(→ Callable[[T], T])

Mark a class as a saga translating events from source to commands

process_manager(→ Callable[[T], T])

Mark a class as a process manager.

projector(→ Callable[[T], T])

Mark a class as a projector consuming events from domains.

upcaster(→ Callable[[T], T])

Mark a class as an upcaster transforming events in domain.

handles(→ Callable[[F], F])

Register a method as a dispatch target for message_type.

handles_fact(→ Callable[[F], F])

Register a method as a fact-event handler for event_type.

applies(→ Callable[[F], F])

Register a method as a state applier for event_type.

rejected(→ Callable[[F], F])

Register a method as a compensation handler for command rejections.

state_factory(→ F)

Mark a method as the state factory for this instance.

upcasts(→ Callable[[F], F])

Register a method as a transformation from from_type to to_type.

Module Contents

angzarr_client.router.decorators.T
angzarr_client.router.decorators.command_handler(*, domain: str, state: type, supports_replay: bool = False) Callable[[T], T]

Mark a class as a command handler (aggregate) for domain.

The state type is the aggregate’s state type; the class must either provide a @state_factory method or rely on state() as the default factory (enforced in a later round).

supports_replay (default False) opts the aggregate into the coordinator’s Replay RPC, used for MERGE_COMMUTATIVE conflict detection. When True, the framework auto-implements replay using the @applies methods to rebuild state from a snapshot + events; the state type must be a proto Message (carry a DESCRIPTOR). When False the gRPC adapter returns UNIMPLEMENTED for Replay requests — the coordinator degrades to MERGE_STRICT semantics. Audit #45.

Fact handling is opt-in via the @handles_fact(EventType) method decorator. Aggregates with no @handles_fact methods get UNIMPLEMENTED from the gRPC adapter for HandleFact; the coordinator falls back to pass-through-persist (per the proto’s Optional contract).

angzarr_client.router.decorators.saga(*, name: str, source: str, target: str, sync: bool = False) Callable[[T], T]

Mark a class as a saga translating events from source to commands for target.

Audit #74: sync declares whether commands emitted to target ever use sync mode (SIMPLE / CASCADE / DECISION / ISOLATED). Default False — target commands flow through the async bus and the readiness supervisor will not probe target’s coordinator. Flip to True when the saga blocks on the downstream response.

angzarr_client.router.decorators.process_manager(*, name: str, pm_domain: str, sources: list[str], targets: list[str], state: type, sync_targets: list[str] | None = None) Callable[[T], T]

Mark a class as a process manager.

pm_domain is the PM’s own state-storage domain; sources lists incoming event domains; targets lists downstream command domains.

Audit #74: sync_targets declares the subset of targets the PM ever addresses with sync mode (SIMPLE / CASCADE / DECISION / ISOLATED) — those are the targets whose coordinator must be reachable for readiness. Default None (no sync targets) — every command goes through the async bus and the readiness supervisor will not probe any target’s coordinator.

Raises ValueError if sync_targets contains a domain that is not in targets.

angzarr_client.router.decorators.projector(*, name: str, domains: list[str]) Callable[[T], T]

Mark a class as a projector consuming events from domains.

angzarr_client.router.decorators.upcaster(*, name: str, domain: str) Callable[[T], T]

Mark a class as an upcaster transforming events in domain.

Methods decorated with @upcasts(FromType, ToType) declare individual version-to-version transformations. An upcaster with zero @upcasts methods is allowed (passthrough).

angzarr_client.router.decorators.F
angzarr_client.router.decorators.handles(message_type: type) Callable[[F], F]

Register a method as a dispatch target for message_type.

For command handlers this is the command type; for sagas / process managers / projectors it is the event type. Dispatch routes by proto full-name match.

angzarr_client.router.decorators.handles_fact(event_type: type) Callable[[F], F]

Register a method as a fact-event handler for event_type.

Audit #45. Triggered when the coordinator dispatches a fact (an external reality, e.g. a payment confirmation from a third party) via the HandleFact RPC. The method receives (event, state) after state has been rebuilt from prior events; it returns the events to persist (or None for pure side-effects).

Aggregates with at least one @handles_fact method opt into the HandleFact RPC. Aggregates with none get UNIMPLEMENTED from the framework’s gRPC adapter — the coordinator then falls back to pass-through-persist per the proto’s Optional contract.

Distinct from @handles (which dispatches commands and returns events), @handles_fact is fact-specific: facts cannot be rejected, and the method’s return shape is just events-to-persist.

angzarr_client.router.decorators.applies(event_type: type) Callable[[F], F]

Register a method as a state applier for event_type.

Appliers are invoked during state rebuild, walking the prior event book and mutating the instance’s state in place.

angzarr_client.router.decorators.rejected(source_domain: str, command: str) Callable[[F], F]

Register a method as a compensation handler for command rejections.

Triggered when a command originating from this component is rejected by the target aggregate. source_domain and command identify the rejected command’s proto full-name suffix split into domain/command parts.

angzarr_client.router.decorators.state_factory(fn: F) F

Mark a method as the state factory for this instance.

Overrides the default factory (calling StateType()). Useful when state construction requires parameters or custom defaults.

angzarr_client.router.decorators.upcasts(from_type: type, to_type: type) Callable[[F], F]

Register a method as a transformation from from_type to to_type.

The method must accept the old event and return the new one. Dispatch matches by exact proto type-URL on the incoming event; events without a registered transform pass through unchanged.