From messages to workflows.
Process RabbitMQ messages with DI, typed handlers, and a managed application lifecycle.
Dependencies, brought together.
Define your services. Let the container handle creation, sharing and cleanup.
Dependency injection 02From startup to shutdown.
A shared application lifecycle for messages, queues and managed resources.
Application lifecycleLily Consumer routes RabbitMQ messages to Rust handlers and manages the application's lifecycle. You define message contracts and business rules; Lily constructs services, opens each delivery scope, dispatches messages, and reconciles the resources it owns within a shutdown budget.
A shared foundation: DI and lifecycle#
Consumer shares the DI foundation used by HTTP API and WebSocket. Services registered with Injectable can be Singleton, Scoped, or Transient. A Consumer scope belongs to one admitted delivery, rather than a connection. Redelivering the same message creates a new scope.
Consumer::run() does more than start a loop: configuration, handler discovery, pipeline construction, queue registration, runtime supervision, and controlled shutdown share one application owner. Your application still designs ownership for independently spawned tasks and external resources.
The path of a message#
Publisher → RabbitMQ → contract selection → delivery scope
→ middleware → guards → typed extraction → handler
→ reverse middleware exit → scope cleanup → settlementHandlers are selected by (queue, version, content). For example, the orders.created, 1, json contract selects a Json<OrderCreated> handler. Invalid envelopes and unsupported contracts may be rejected before a scope or application middleware is entered.
Handlers return Result<(), QueueHandlerError>. Success, retryable failure, and permanent failure feed the framework's settlement decision. Handlers do not receive direct ACK/NACK authority, which prevents several components from settling the same delivery.
What can you build?#
| Capability | Starting point |
|---|---|
| Typed message handling and versioned handlers | Message contracts |
| Shared services and delivery scopes | Dependency injection |
| Shared behavior and application policy | Middleware and guards |
| Retries, dead letters, and capacity | Retries and backpressure |
| Databases, inbox, and outbox | Data integrations and transactional inbox |
| Health, shutdown, and documentation | Managed Consumer, tracing, AsyncAPI |
Installation and learning order#
lilyrs = { version = "0.1.0", features = ["consumer"] }The public entry point is the lilyrs facade. The consumer feature exposes the application API through lilyrs::consumer and queue contracts through lilyrs::queue. DI derives and registration infrastructure need no separate installation. This path uses RabbitMQ; there is no general transport switch for choosing another broker.
Start with your first Consumer, then send a message with the separate publisher. Continue through lifecycle, DI, and configuration. This gives advanced transaction and operational settings a working application to build on.
Sources for this page v0.1.0
This guide is based on the reviewed framework commit.