angzarr_client.router.builder

Unified Router builder.

Registration-only surface in R3. Mode inference + kind validation arrive in R4 / R5; dispatch logic arrives in R6+. See TIER5_PLAN.md for the full round sequence.

Exceptions

BuildError

Raised when the builder cannot produce a valid runtime router.

Classes

Router

Fluent builder that collects handler factories for the unified router.

Module Contents

exception angzarr_client.router.builder.BuildError(message: str, *, code: str = '', details: collections.abc.Mapping[str, Any] | None = None)

Bases: Exception

Raised when the builder cannot produce a valid runtime router.

Audit #72: carries the structural error shape from audit #59 — SCREAMING_SNAKE code (programmatic dispatch / cucumber assertions), static message (cross-language equality), and details for runtime context (router name, conflicting kinds, duplicate (domain, type_url), handler class, field name, etc.). Mirrors Rust router::handler::BuildError which carries an ErrorDetail per variant.

Construction sites pass constants from angzarr_client.error_codes: codes.DUPLICATE_COMMAND_HANDLER etc. for the code, messages.DUPLICATE_COMMAND_HANDLER etc. for the static message, detail keys from keys for the details map.

Initialize self. See help(type(self)) for accurate signature.

message
code = ''
details: dict[str, str]
class angzarr_client.router.builder.Router(name: str)

Fluent builder that collects handler factories for the unified router.

Usage:

Router("agg-service")
    .with_handler(Player, lambda: Player(db_pool))
    .with_handler(Hand, lambda: Hand(rng))
    .build()

.build() returns a typed runtime router (CommandHandlerRouter, SagaRouter, ProcessManagerRouter, or ProjectorRouter). Mixed handler kinds are rejected at build time (R4).

Handlers are registered as (cls, factory) pairs so the router can invoke factory() per dispatch call to obtain a fresh (or pooled) instance. This keeps handler state isolated per request and makes the router safe to share across threads.

name
with_handler(cls: type, factory: Callable[[], Any]) Router

Register a handler class together with a zero-arg factory.

cls must carry one of the five kind decorators (@command_handler, @saga, @process_manager, @projector, @upcaster). Registering an undecorated class raises BuildError.

factory is any Callable[[], Any]: a lambda, a bound method on a DI container, a functools.partial, a pool-checkout closure, or a callable returning a shared singleton. The router never inspects the factory body; it only calls it and uses whatever it returns.

Factories are invoked inside dispatch(), so their latency is on the request path. For handlers whose construction is expensive — opens a DB connection, reads a config file, performs I/O, does non-trivial computation, holds resources that must be released — prefer a pool checkout or close over a pre-built instance rather than constructing fresh on every call.

build() Any

Produce a typed runtime router.

Empty → BuildError. Mixed kinds → BuildError. Homogeneous → CommandHandlerRouter / SagaRouter / ProcessManagerRouter / ProjectorRouter per the shared kind.