Router Generation
View SourceAshCommanded automatically generates Commanded Routers for dispatching commands to the appropriate handlers and aggregates based on your domain structure.
Domain-specific Routers
For each Ash.Domain containing resources with the AshCommanded.Commanded.Dsl extension, a domain-specific router is generated:
defmodule ECommerce.Store.Router do
use Commanded.Commands.Router
# For each resource in the domain
identify ECommerce.ProductAggregate, by: :id
dispatch [ECommerce.Commands.CreateProduct, ECommerce.Commands.UpdateProduct], to: ECommerce.ProductAggregate
identify ECommerce.CustomerAggregate, by: :id
dispatch [ECommerce.Commands.RegisterCustomer, ECommerce.Commands.UpdateStatus], to: ECommerce.CustomerAggregate
end
These domain routers handle command routing within a specific domain context.
Main Application Router
AshCommanded also generates a main application router at AshCommanded.Router
. The behavior of this router depends on the domain structure:
Single Domain Setup
For applications with a single domain, the main router directly routes commands to aggregates:
defmodule AshCommanded.Router do
use Commanded.Commands.Router
# Direct command routing for all resources
identify ECommerce.ProductAggregate, by: :id
dispatch [ECommerce.Commands.CreateProduct, ECommerce.Commands.UpdateProduct], to: ECommerce.ProductAggregate
identify ECommerce.CustomerAggregate, by: :id
dispatch [ECommerce.Commands.RegisterCustomer, ECommerce.Commands.UpdateStatus], to: ECommerce.CustomerAggregate
end
Multiple Domain Setup
For applications with multiple domains, the main router forwards commands to the appropriate domain router:
defmodule AshCommanded.Router do
use Commanded.Commands.Router
# Forward to domain routers
forward ECommerce.Store.Router
forward ECommerce.Marketing.Router
forward ECommerce.Shipping.Router
end
Command Dispatching
With these routers in place, you can dispatch commands using the dispatch/1 or dispatch/2 functions:
# Basic command dispatch
command = %ECommerce.Commands.CreateProduct{id: "123", name: "Premium Widget", price: 29.99}
AshCommanded.Router.dispatch(command)
# With options
command = %ECommerce.Commands.CreateProduct{id: "123", name: "Premium Widget", price: 29.99}
AshCommanded.Router.dispatch(command, correlation_id: UUID.uuid4(), metadata: %{user_id: "user-123"})
The command will be routed to the appropriate aggregate and handler based on the command type and the resource's identity.
Identity Resolution
By default, the router uses the resource's primary identity key or the specified identity_field
in the command definition.
commanded do
commands do
command :create_product do
fields([:id, :name, :price])
identity_field(:id) # Explicitly specify the identity field
end
end
end
If no identity field is specified, the router will try to use:
- The first field from the resource's primary identity
- The
:id
field as a fallback