Requests¶
A request is a frozen dataclass that describes an intent. Commands change state, queries read state — both are dispatched through the message bus to exactly one handler.
Defining Requests¶
waku provides two ways to define a request:
IRequest[TResponse] is a marker protocol with no required attributes. Implement it as a
frozen dataclass:
Tip
IRequest without a type argument defaults to IRequest[None] — use it for void commands.
Response types are plain frozen dataclasses -- no base class is needed:
Request Handlers¶
Each request type maps to exactly one handler. waku provides two styles:
RequestHandler (ABC)¶
RequestHandler[TRequest, TResponse] is an abstract base class — use it for explicit inheritance
and type checking:
IRequestHandler (Protocol)¶
IRequestHandler[TRequest, TResponse] is a protocol — any class with a matching handle method
is compatible (structural subtyping):
Registration¶
Bind a request to its handler via MessagingExtension in the module's extensions list:
Dispatching¶
Inject ISender and call invoke. Prefer ISender over IMessageBus when you only need to
dispatch requests — this enforces the principle of least privilege:
invoke returns the response type declared by the request's generic parameter. If the request
declares Request[None], invoke returns None.
How are handler dependencies resolved?
Constructor parameters like user_repo: UserRepository are resolved automatically by
waku's dependency injection system. Register the
implementation in your module's providers list.
Further reading¶
- Events — event definitions, handlers, and publishers
- Pipeline Behaviors — cross-cutting middleware for request handling
- Message Bus (CQRS) — setup, interfaces, and complete example