@startuml Actor Creation and Spawning
title Actor Creation and Spawning
actor User
participant "UserActor Struct" as UserActor
participant "spawn()" as spawn_func
participant "ActorRef<T>" as ActorRef_type
participant "mpsc::channel (mailbox)" as MailboxChannel
participant "mpsc::channel (terminate)" as TerminateChannel
participant "tokio::spawn" as tokio_spawn
participant "run_actor_lifecycle()" as run_lifecycle
participant "Actor::on_start(Args)" as on_start_method
participant "Actor::on_run()" as on_run_method
User -> UserActor: Defines struct & impl Actor (with Args)
User -> UserActor: Uses #[message_handlers] macro for message handling
User -> spawn_func: Calls spawn(actor_args)
activate spawn_func
spawn_func -> spawn_func: Generates unique actor ID (atomic)
spawn_func -> MailboxChannel: Creates (mailbox_tx, mailbox_rx)
spawn_func -> TerminateChannel: Creates (terminate_tx, terminate_rx) with buffer=1
spawn_func -> ActorRef_type: Creates ActorRef<T> (with id, mailbox_tx, terminate_tx)
spawn_func -> tokio_spawn: Spawns run_actor_lifecycle(args, actor_ref, mailbox_rx, terminate_rx)
activate tokio_spawn
spawn_func --> User: Returns (ActorRef<T>, JoinHandle<ActorResult<T>>)
deactivate spawn_func
tokio_spawn -> run_lifecycle: Executes in dedicated async task
activate run_lifecycle
run_lifecycle -> on_start_method: Calls T::on_start(args, &actor_ref).await
activate on_start_method
on_start_method --> run_lifecycle: Returns Result<ActorInstance, Error>
deactivate on_start_method
alt on_start Success
run_lifecycle -> run_lifecycle: Creates ActorWeak from ActorRef (drops strong ref)
run_lifecycle -> run_lifecycle: Enters main tokio::select! loop
note right of run_lifecycle
Main loop handles (biased priority):
1. Termination signals (highest)
2. Mailbox messages
3. on_run() idle handler (when queue empty)
end note
run_lifecycle -> on_run_method: Calls actor.on_run(&actor_weak).await (when idle)
activate on_run_method
on_run_method --> run_lifecycle: Returns Result<bool, Error>
deactivate on_run_method
note right of run_lifecycle
Ok(true): continue calling on_run when idle
Ok(false): disable idle processing
Err: terminate with ActorResult::Failed
end note
run_lifecycle --> tokio_spawn: Eventually completes with ActorResult::Completed
else on_start Failure
run_lifecycle --> tokio_spawn: Returns ActorResult::Failed { phase: OnStart, .. }
end
deactivate run_lifecycle
tokio_spawn --> User: JoinHandle resolves with ActorResult when task finishes
deactivate tokio_spawn
@enduml