pub trait Message<T: Send + 'static>: Actor {
type Reply: Send + 'static;
// Required method
fn handle(
&mut self,
msg: T,
actor_ref: &ActorRef<Self>,
) -> impl Future<Output = Self::Reply> + Send;
// Provided method
fn on_tell_result(_result: &Self::Reply, _actor_ref: &ActorRef<Self>) { ... }
}Expand description
Required Associated Types§
Required Methods§
Sourcefn handle(
&mut self,
msg: T,
actor_ref: &ActorRef<Self>,
) -> impl Future<Output = Self::Reply> + Send
fn handle( &mut self, msg: T, actor_ref: &ActorRef<Self>, ) -> impl Future<Output = Self::Reply> + Send
Handles the incoming message and produces a reply.
The actor_ref parameter is a reference to the actor’s own ActorRef.
This is an asynchronous method where the actor’s business logic for
processing the message T resides.
This method is called by the actor system when a message is received via
tell, ask,
or their variants.
Provided Methods§
Sourcefn on_tell_result(_result: &Self::Reply, _actor_ref: &ActorRef<Self>)
fn on_tell_result(_result: &Self::Reply, _actor_ref: &ActorRef<Self>)
Called after a tell() message handler completes.
This hook allows inspecting the handler’s return value for fire-and-forget messages.
For ask() calls, this method is NOT invoked — the caller receives the result directly.
§Design decisions
This hook is designed as a synchronous, stateless logging hook:
- No
&self: The actor’s mutable state is not accessible. This prevents side effects and keeps the hook purely observational. - Not
async: Asynchronous operations (e.g., sending messages to other actors) are intentionally excluded to avoid hidden control flow in fire-and-forget paths. - These constraints may be relaxed in future versions if use cases arise.
The default implementation does nothing. When using the #[handler] macro with a
Result<T, E> return type (where E: Display), an override is automatically
generated that logs errors via tracing::error!.
§Display bound enforcement
The generated tracing::error!("...: {}", e) implicitly requires E: Display.
Since E is embedded inside Self::Reply = Result<T, E>, a where E: Display
clause cannot be added directly on a trait method override. In the
#[handler(result)] + type alias case, the proc macro cannot know the concrete
E type at all, making an explicit bound fundamentally impossible.
Therefore, implicit enforcement via the {} format specifier is adopted.
If E does not implement Display, the compiler emits
`MyError` doesn't implement `std::fmt::Display`
which is clear enough for the user to diagnose immediately.
§Automatic generation
The #[handler] macro generates an override when:
- The return type is syntactically
Result<T, E>(auto-detected) - The attribute
#[handler(result)]is explicitly specified
Use #[handler(no_log)] to suppress automatic generation.
§Manual override
For manual Message trait implementations, override this method directly:
fn on_tell_result(result: &Self::Reply, actor_ref: &ActorRef<Self>) {
if let Err(ref e) = result {
tracing::error!(actor = %actor_ref.identity(), "error: {}", e);
}
}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.