eventide-application
中文版本: README.zh.md
Application layer of the eventide
DDD/CQRS toolkit. It orchestrates use cases and translates external
requests (HTTP / CLI / job runner) into domain commands and queries
without leaking infrastructure concerns.
What is in here
| Type / module | Role |
|---|---|
CommandHandler<C> |
Handles a single command type with side effects (writes). |
QueryHandler<Q, R> |
Handles a single query type and returns a typed result R. |
CommandBus |
Type-erased dispatch. Routes a command to its registered handler by TypeId. |
QueryBus |
Same idea for queries, with a typed return value. |
InMemoryCommandBus / InMemoryQueryBus |
Concurrent reference implementations backed by dashmap::DashMap. |
AppContext |
Cross-cutting context: EventContext (correlation / causation / actor) + idempotency_key. |
AppError |
Domain / Validation / Authorization / Infra / HandlerNotFound / AggregateNotFound / TypeMismatch. |
Add it
[]
= "0.1"
= "0.1"
= { = "1", = ["full"] }
Or via the umbrella crate:
[]
= "0.1"
Command example
use async_trait;
use CommandBus;
use CommandHandler;
use AppContext;
use InMemoryCommandBus;
use Arc;
;
async
Query example
use async_trait;
use AppContext;
use QueryBus;
use QueryHandler;
use InMemoryQueryBus;
use Serialize;
use Arc;
;
async
Concurrency notes
- Bus registries use
dashmap::DashMap. Handlers are wrapped inArcand cloned out before dispatch, so locks never span anawait. AppError::HandlerNotFound(name)reports the missing handler withstd::any::type_name::<T>(), keeping the message short and stable.AppError::TypeMismatchis a defensive error used when the registry is unexpectedly mutated to hold the wrong handler type.
Run tests / examples
Layered architecture
eventide-application → eventide-domain ← eventide-macros
Application code depends only on the domain layer. Concrete repositories, event stores, and message buses live in your own infrastructure crate and are wired into handlers through dependency injection.
License
Licensed under either of Apache-2.0 or MIT at your option.