pub struct ActrRef<W: Workload> { /* private fields */ }Expand description
ActrRef - Lightweight reference to a running Actor
This is the primary handle returned by ActrNode::start().
§Code Generation Pattern
actr-cli code generator will generate type-safe RPC methods for ActrRef.
§Proto Definition
service EchoService {
rpc Echo(EchoRequest) returns (EchoResponse);
rpc Ping(PingRequest) returns (PingResponse);
}§Generated Code (in generated/echo_service_actr_ref.rs)
use actr_runtime::ActrRef;
use super::echo_service_actor::{EchoServiceWorkload, EchoServiceHandler};
use super::echo::{EchoRequest, EchoResponse, PingRequest, PingResponse};
impl<T: EchoServiceHandler> ActrRef<EchoServiceWorkload<T>> {
/// Call Echo RPC method
pub async fn echo(&self, request: EchoRequest) -> ActorResult<EchoResponse> {
self.call(request).await
}
/// Call Ping RPC method
pub async fn ping(&self, request: PingRequest) -> ActorResult<PingResponse> {
self.call(request).await
}
}§Usage in Shell
use generated::echo_service_actr_ref::*; // Import ActrRef extensions
let actr = node.start().await?;
// Type-safe RPC calls (generated methods)
let response = actr.echo(EchoRequest {
message: "Hello".to_string(),
}).await?;
// Or use generic call() method
let response: EchoResponse = actr.call(EchoRequest { ... }).await?;§Design Rationale
Why bind RPC methods to ActrRef?
- Type Safety: Compiler checks request/response types
- Auto-completion: IDE shows available RPC methods
- No target needed: ActrRef already knows its target Actor
- Symmetric to Context: Similar to Context extension pattern
Comparison with Context pattern:
| Aspect | Context (in Workload) | ActrRef (in Shell) |
|---|---|---|
| Caller | Workload | Shell |
| Target | Any Actor (needs target param) | This Workload (fixed) |
| Method | ctx.call(target, req) | actr.echo(req) |
| Generation | Extension trait | Concrete impl |
Implementations§
Source§impl<W: Workload> ActrRef<W>
impl<W: Workload> ActrRef<W>
Sourcepub async fn discover_route_candidates(
&self,
target_type: &ActrType,
candidate_count: u32,
) -> ActorResult<Vec<ActrId>>
pub async fn discover_route_candidates( &self, target_type: &ActrType, candidate_count: u32, ) -> ActorResult<Vec<ActrId>>
Discover remote actors of the specified type via signaling server.
This method implements the full runtime compatibility negotiation workflow:
- Fast Path: Check
compat.lock.tomlfor cached negotiation results - Ideal Path: Read fingerprint from
Actr.lock.tomland request exact match - Negotiation: If no exact match, server performs compatibility analysis
- Result: Returns candidates with compatibility info, updates caches
The fingerprint is automatically obtained from the Actr.lock.toml file
loaded during ActrSystem::attach().
§Arguments
target_type: The ActrType of the target service to discovercandidate_count: Maximum number of candidates to return
§Returns
A list of compatible ActrId candidates.
Sourcepub async fn call<R>(&self, request: R) -> ActorResult<R::Response>where
R: RpcRequest,
pub async fn call<R>(&self, request: R) -> ActorResult<R::Response>where
R: RpcRequest,
Call Actor method (Shell → Workload RPC)
This is a generic method used by code-generated RPC methods. Most users should use the generated methods instead.
§Example
// Generic call
let response: EchoResponse = actr.call(EchoRequest {
message: "Hello".to_string(),
}).await?;
// Generated method (preferred)
let response = actr.echo(EchoRequest {
message: "Hello".to_string(),
}).await?;Sourcepub async fn call_raw(
&self,
route_key: String,
request_bytes: Bytes,
timeout_ms: i64,
payload_type: PayloadType,
) -> ActorResult<Bytes>
pub async fn call_raw( &self, route_key: String, request_bytes: Bytes, timeout_ms: i64, payload_type: PayloadType, ) -> ActorResult<Bytes>
Call Actor method using route_key and request bytes (for language bindings)
This is a non-generic version of call() that accepts route_key and raw bytes,
making it suitable for language bindings (e.g., Python) that don’t have access
to Rust’s generic RpcRequest trait.
§Parameters
route_key: Route key string (e.g., “package.Service.Method”)request_bytes: Request protobuf bytestimeout_ms: Timeout in millisecondspayload_type: Payload transmission type
§Returns
Response protobuf bytes
Sourcepub async fn tell_raw(
&self,
route_key: String,
message_bytes: Bytes,
payload_type: PayloadType,
) -> ActorResult<()>
pub async fn tell_raw( &self, route_key: String, message_bytes: Bytes, payload_type: PayloadType, ) -> ActorResult<()>
Send one-way message using route_key and message bytes (for language bindings)
This is a non-generic version of tell() that accepts route_key and raw bytes,
making it suitable for language bindings (e.g., Python) that don’t have access
to Rust’s generic RpcRequest trait.
§Parameters
route_key: Route key string (e.g., “package.Service.Method”)message_bytes: Message protobuf bytespayload_type: Payload transmission type
§Returns
Unit (fire-and-forget, no response)
Sourcepub async fn tell<R>(&self, message: R) -> ActorResult<()>where
R: RpcRequest + ProstMessage,
pub async fn tell<R>(&self, message: R) -> ActorResult<()>where
R: RpcRequest + ProstMessage,
Send one-way message to Actor (Shell → Workload, fire-and-forget)
Unlike call(), this method does not wait for a response.
Use this for notifications or commands that don’t need acknowledgment.
§Example
// Send notification without waiting for response
actr.tell(LogEvent {
level: "INFO".to_string(),
message: "User logged in".to_string(),
}).await?;
// Generated method (if codegen supports tell)
actr.log_event(LogEvent { ... }).await?;§Performance
- Latency: ~10μs (in-process, zero serialization)
- No blocking: Returns immediately after sending
- No response: Caller won’t know if message was processed
Sourcepub fn shutdown(&self)
pub fn shutdown(&self)
Trigger Actor shutdown
This signals the Actor to stop, but does not wait for completion.
Use wait_for_shutdown() to wait for cleanup to finish.
Sourcepub async fn wait_for_shutdown(&self)
pub async fn wait_for_shutdown(&self)
Wait for Actor to fully shutdown
This waits for the shutdown signal to be triggered.
All background tasks will be aborted when the last ActrRef is dropped.
Sourcepub fn is_shutting_down(&self) -> bool
pub fn is_shutting_down(&self) -> bool
Check if Actor is shutting down
Sourcepub async fn wait_for_ctrl_c_and_shutdown(self) -> ActorResult<()>
pub async fn wait_for_ctrl_c_and_shutdown(self) -> ActorResult<()>
Trait Implementations§
Auto Trait Implementations§
impl<W> Freeze for ActrRef<W>
impl<W> !RefUnwindSafe for ActrRef<W>
impl<W> Send for ActrRef<W>
impl<W> Sync for ActrRef<W>
impl<W> Unpin for ActrRef<W>
impl<W> !UnwindSafe for ActrRef<W>
Blanket Implementations§
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more