pub trait ActorEntity:
Clone
+ Send
+ Sync
+ 'static {
type Id: Eq + Hash + Clone + Send + Sync + Display + Debug + From<u32>;
type Create: Send + Sync + Debug;
type Update: Send + Sync + Debug;
type Action: Send + Sync + Debug;
type ActionResult: Send + Sync + Debug;
type Context: Send + Sync;
type Error: Error + Send + Sync + 'static;
// Required methods
fn from_create_params(
id: Self::Id,
params: Self::Create,
) -> Result<Self, Self::Error>;
fn on_update<'life0, 'life1, 'async_trait>(
&'life0 mut self,
update: Self::Update,
_ctx: &'life1 Self::Context,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn handle_action<'life0, 'life1, 'async_trait>(
&'life0 mut self,
action: Self::Action,
_ctx: &'life1 Self::Context,
) -> Pin<Box<dyn Future<Output = Result<Self::ActionResult, Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
// Provided methods
fn on_create<'life0, 'life1, 'async_trait>(
&'life0 mut self,
_ctx: &'life1 Self::Context,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn on_delete<'life0, 'life1, 'async_trait>(
&'life0 self,
_ctx: &'life1 Self::Context,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
}Expand description
Trait that any resource entity must implement to be managed by ResourceActor.
§Architecture Note
By defining a contract (ActorEntity) that all our resource types (User, Product, Order)
must satisfy, we can write the ResourceActor logic once and reuse it everywhere.
§Async & Context
This trait is #[async_trait] to allow asynchronous operations in hooks (e.g., calling other actors).
It also defines a Context type, which is injected into every hook. This allows “Late Binding”
of dependencies (passing clients to run() instead of new()).
Required Associated Types§
Sourcetype Id: Eq + Hash + Clone + Send + Sync + Display + Debug + From<u32>
type Id: Eq + Hash + Clone + Send + Sync + Display + Debug + From<u32>
The unique identifier for this entity (e.g., String, Uuid, u64). Must be convertible from u32 for automatic ID generation.
Sourcetype Create: Send + Sync + Debug
type Create: Send + Sync + Debug
The data required to create a new instance (DTO - Data Transfer Object).
Sourcetype Action: Send + Sync + Debug
type Action: Send + Sync + Debug
Enum representing resource-specific operations (e.g., ReserveStock).
Sourcetype ActionResult: Send + Sync + Debug
type ActionResult: Send + Sync + Debug
The result type returned by custom actions.
Sourcetype Context: Send + Sync
type Context: Send + Sync
The runtime context (dependencies) injected into the actor.
Use () if no dependencies are needed.
Sourcetype Error: Error + Send + Sync + 'static
type Error: Error + Send + Sync + 'static
The error type for this entity. Must implement std::error::Error for proper error propagation.
§Design Note: Error Granularity
The framework enforces a Per-Actor Error Type (one enum for the whole actor) rather than Per-Message Error Types (a specific error for each action).
Why?
- Simplicity: Reduces boilerplate. You don’t need to define 10 different error enums for 10 actions.
- Ergonomics: Clients deal with a single
UserErrortype, making pattern matching easier.
Trade-off:
This means UserError must be the union of all possible errors. If ActionA can only fail with ErrorX,
but ActionB can fail with ErrorY, the return type for both is Result<..., UserError>, which technically
allows ErrorY to be returned from ActionA. In practice, this theoretical loss of precision is worth
the massive reduction in code complexity.
Required Methods§
Sourcefn from_create_params(
id: Self::Id,
params: Self::Create,
) -> Result<Self, Self::Error>
fn from_create_params( id: Self::Id, params: Self::Create, ) -> Result<Self, Self::Error>
Construct the full Entity from the ID and Payload.
This is called synchronously before on_create.
Sourcefn on_update<'life0, 'life1, 'async_trait>(
&'life0 mut self,
update: Self::Update,
_ctx: &'life1 Self::Context,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn on_update<'life0, 'life1, 'async_trait>(
&'life0 mut self,
update: Self::Update,
_ctx: &'life1 Self::Context,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Called when an update request is received.
Sourcefn handle_action<'life0, 'life1, 'async_trait>(
&'life0 mut self,
action: Self::Action,
_ctx: &'life1 Self::Context,
) -> Pin<Box<dyn Future<Output = Result<Self::ActionResult, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn handle_action<'life0, 'life1, 'async_trait>(
&'life0 mut self,
action: Self::Action,
_ctx: &'life1 Self::Context,
) -> Pin<Box<dyn Future<Output = Result<Self::ActionResult, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Handle a custom resource-specific action.
Provided Methods§
Sourcefn on_create<'life0, 'life1, 'async_trait>(
&'life0 mut self,
_ctx: &'life1 Self::Context,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn on_create<'life0, 'life1, 'async_trait>(
&'life0 mut self,
_ctx: &'life1 Self::Context,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Called immediately after the entity is created and initialized. Use this hook to perform validation or side effects (e.g., checking other actors).
Sourcefn on_delete<'life0, 'life1, 'async_trait>(
&'life0 self,
_ctx: &'life1 Self::Context,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn on_delete<'life0, 'life1, 'async_trait>(
&'life0 self,
_ctx: &'life1 Self::Context,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Called immediately before the entity is removed from the system.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.