Requests¶
A request is a frozen dataclass that describes an intent. Commands change state, queries read state — both are dispatched through the mediator to exactly one handler.
Defining Requests¶
waku provides two ways to define a request:
Request base class¶
Request[TResponse] adds an auto-generated request_id (UUID):
Tip
Use Request[None] when a command does not return a value.
IRequest protocol¶
IRequest[TResponse] is a marker protocol with no required attributes. Use it when you need
custom identification strategies or no ID at all:
Response base class¶
Response is an optional frozen dataclass base for response objects. It has no required fields —
it exists for consistency and type clarity:
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 MediatorExtension in the module's extensions list:
Dispatching¶
Inject ISender and call send. Prefer ISender over IMediator when you only need to
dispatch requests — this enforces the principle of least privilege:
send returns the response type declared by the request's generic parameter. If the request
declares Request[None], send 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
- Mediator (CQRS) — setup, interfaces, and complete example