pub trait Context:
Clone
+ MaybeSendSync
+ 'static {
Show 16 methods
// Required methods
fn self_id(&self) -> &ActrId;
fn caller_id(&self) -> Option<&ActrId>;
fn request_id(&self) -> &str;
fn call<'life0, 'life1, 'async_trait, R>(
&'life0 self,
target: &'life1 Dest,
request: R,
) -> Pin<Box<dyn Future<Output = ActorResult<R::Response>> + Send + 'async_trait>>
where R: 'async_trait + RpcRequest,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn tell<'life0, 'life1, 'async_trait, R>(
&'life0 self,
target: &'life1 Dest,
message: R,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>
where R: 'async_trait + RpcRequest,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn register_stream<'life0, 'async_trait, F>(
&'life0 self,
stream_id: String,
callback: F,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>
where F: Fn(DataStream, ActrId) -> BoxFuture<'static, ActorResult<()>> + Send + Sync + 'static + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait;
fn unregister_stream<'life0, 'life1, 'async_trait>(
&'life0 self,
stream_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn send_data_stream<'life0, 'life1, 'async_trait>(
&'life0 self,
target: &'life1 Dest,
chunk: DataStream,
payload_type: PayloadType,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn discover_route_candidate<'life0, 'life1, 'async_trait>(
&'life0 self,
target_type: &'life1 ActrType,
) -> Pin<Box<dyn Future<Output = ActorResult<ActrId>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn call_raw<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
target: &'life1 ActrId,
route_key: &'life2 str,
payload: Bytes,
) -> Pin<Box<dyn Future<Output = ActorResult<Bytes>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn register_media_track<'life0, 'async_trait, F>(
&'life0 self,
track_id: String,
callback: F,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>
where F: Fn(MediaSample, ActrId) -> BoxFuture<'static, ActorResult<()>> + Send + Sync + 'static + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait;
fn unregister_media_track<'life0, 'life1, 'async_trait>(
&'life0 self,
track_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn send_media_sample<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
target: &'life1 Dest,
track_id: &'life2 str,
sample: MediaSample,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn add_media_track<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>(
&'life0 self,
target: &'life1 Dest,
track_id: &'life2 str,
codec: &'life3 str,
media_type: &'life4 str,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait;
fn remove_media_track<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
target: &'life1 Dest,
track_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
// Provided method
fn log(&self, level: LogLevel, msg: &str) { ... }
}Expand description
Actor execution context interface.
Defines the complete interface for an actor to interact with the runtime:
- Context data access (
self_id,request_id, …) - Communication primitives (
call,tell)
§Design principles
- Interface only: the framework provides no implementation; the runtime does.
- Generic parameter: user code accepts
<C: Context>rather than&dyn Context, so dispatch monomorphises and avoids vtables.
§cfg dispatch
The trait is ?Send on wasm32 (browser single-threaded, futures can
legitimately not be Send) and #[async_trait] (Send mode) on native
targets so tokio-multi-thread spawners downstream keep working. The
MaybeSendSync supertrait adds Send + Sync on native only — per
Option U γ-unified §3.1 the user-visible bound stays Clone + 'static
while Workload default method bodies (which need Send futures under
the native async_trait) compile without any extra constraint on the
generic C.
§Example
async fn my_handler<C: Context>(ctx: &C) {
let id = ctx.self_id();
let response = ctx.call(&target, request).await?;
}Required Methods§
Sourcefn caller_id(&self) -> Option<&ActrId>
fn caller_id(&self) -> Option<&ActrId>
Get the caller’s Actor ID
Some(caller_id): Called by another ActorNone: System internal call (e.g., lifecycle hooks)
Sourcefn request_id(&self) -> &str
fn request_id(&self) -> &str
Get the unique request ID
A new request_id is generated for each RPC call, used to match requests and responses.
Sourcefn call<'life0, 'life1, 'async_trait, R>(
&'life0 self,
target: &'life1 Dest,
request: R,
) -> Pin<Box<dyn Future<Output = ActorResult<R::Response>> + Send + 'async_trait>>where
R: 'async_trait + RpcRequest,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn call<'life0, 'life1, 'async_trait, R>(
&'life0 self,
target: &'life1 Dest,
request: R,
) -> Pin<Box<dyn Future<Output = ActorResult<R::Response>> + Send + 'async_trait>>where
R: 'async_trait + RpcRequest,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Send a type-safe RPC request and wait for response
This is the primary way to call other Actors, providing full type safety guarantees.
§Type Inference
Response type is automatically inferred from R::Response, no manual annotation needed:
let request = EchoRequest { message: "hello".to_string() };
let response: EchoResponse = ctx.call(&target, request).await?;
// ^^^^^^^^^^^^ Inferred from EchoRequest::Response§Error Handling
ProtocolError::TransportError: Network transport failureProtocolError::Actr(DecodeFailure): Response decode failureProtocolError::Actr(UnknownRoute): Route does not exist- Errors returned by remote Actor’s business logic
§Parameters
target: Target destination (Dest::Shellfor local,Dest::Actor(id)for remote)request: Request message implementingRpcRequesttrait
§Returns
Returns response message of type R::Response
Sourcefn tell<'life0, 'life1, 'async_trait, R>(
&'life0 self,
target: &'life1 Dest,
message: R,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
R: 'async_trait + RpcRequest,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn tell<'life0, 'life1, 'async_trait, R>(
&'life0 self,
target: &'life1 Dest,
message: R,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
R: 'async_trait + RpcRequest,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Send a type-safe one-way message (no response expected)
Used for sending notifications, events, etc. that do not require a response.
§Semantics
- Fire-and-forget: Does not wait for response after sending
- No delivery guarantee: Message may be lost if target is unreachable
- Low latency: Does not block waiting for response
§Parameters
target: Target destination (Dest::Shellfor local,Dest::Actor(id)for remote)message: Message implementingRpcRequesttrait
Sourcefn register_stream<'life0, 'async_trait, F>(
&'life0 self,
stream_id: String,
callback: F,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
F: Fn(DataStream, ActrId) -> BoxFuture<'static, ActorResult<()>> + Send + Sync + 'static + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
fn register_stream<'life0, 'async_trait, F>(
&'life0 self,
stream_id: String,
callback: F,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
F: Fn(DataStream, ActrId) -> BoxFuture<'static, ActorResult<()>> + Send + Sync + 'static + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
Register a DataStream callback for a specific stream
When a DataStream with matching stream_id arrives, the registered callback will be invoked. Callbacks are executed concurrently and do not block other streams.
§Parameters
stream_id: Stream identifier (must be globally unique)callback: Handler function that receives (DataStream, sender ActrId)
§Example
ctx.register_stream("log-stream", |chunk, sender| {
Box::pin(async move {
println!("Received chunk {} from {:?}", chunk.sequence, sender);
Ok(())
})
}).await?;Sourcefn unregister_stream<'life0, 'life1, 'async_trait>(
&'life0 self,
stream_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn unregister_stream<'life0, 'life1, 'async_trait>(
&'life0 self,
stream_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Sourcefn send_data_stream<'life0, 'life1, 'async_trait>(
&'life0 self,
target: &'life1 Dest,
chunk: DataStream,
payload_type: PayloadType,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn send_data_stream<'life0, 'life1, 'async_trait>(
&'life0 self,
target: &'life1 Dest,
chunk: DataStream,
payload_type: PayloadType,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Send a DataStream to a destination with explicit lane selection.
Use PayloadType::StreamReliable for ordered reliable delivery (default) or
PayloadType::StreamLatencyFirst for low-latency partial-reliable delivery.
§Parameters
target: Target destinationchunk: DataStream to sendpayload_type: Lane selection (StreamReliableorStreamLatencyFirst)
Sourcefn discover_route_candidate<'life0, 'life1, 'async_trait>(
&'life0 self,
target_type: &'life1 ActrType,
) -> Pin<Box<dyn Future<Output = ActorResult<ActrId>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn discover_route_candidate<'life0, 'life1, 'async_trait>(
&'life0 self,
target_type: &'life1 ActrType,
) -> Pin<Box<dyn Future<Output = ActorResult<ActrId>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Discover a remote Actor of the specified type via the signaling server.
Returns a route candidate or an error if none are available. Concrete selection strategy is decided by the Context implementation.
Sourcefn call_raw<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
target: &'life1 ActrId,
route_key: &'life2 str,
payload: Bytes,
) -> Pin<Box<dyn Future<Output = ActorResult<Bytes>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn call_raw<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
target: &'life1 ActrId,
route_key: &'life2 str,
payload: Bytes,
) -> Pin<Box<dyn Future<Output = ActorResult<Bytes>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Send a raw RPC request (untyped bytes) and wait for response
This is a lower-level method for dynamic dispatch scenarios where the request/response types are not known at compile time (e.g., FFI bindings).
§Parameters
target: Target Actor IDroute_key: Route key (e.g., “echo.EchoService/Echo”)payload: Raw request payload bytes
§Returns
Returns raw response payload bytes
§Example
// For FFI or dynamic dispatch scenarios
let response = ctx.call_raw(
&target_id,
"echo.EchoService/Echo",
request_bytes.into(),
).await?;Sourcefn register_media_track<'life0, 'async_trait, F>(
&'life0 self,
track_id: String,
callback: F,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
F: Fn(MediaSample, ActrId) -> BoxFuture<'static, ActorResult<()>> + Send + Sync + 'static + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
fn register_media_track<'life0, 'async_trait, F>(
&'life0 self,
track_id: String,
callback: F,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
F: Fn(MediaSample, ActrId) -> BoxFuture<'static, ActorResult<()>> + Send + Sync + 'static + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
Register a WebRTC native media track callback
When media samples arrive on the specified track, the registered callback will be invoked. Uses WebRTC native RTCTrackRemote, no protobuf serialization overhead.
§Parameters
track_id: Media track identifier (must match WebRTC track ID in SDP)callback: Handler function that receives native media samples
§Example
use actr_framework::MediaSample;
ctx.register_media_track("video-track-1", |sample, sender| {
Box::pin(async move {
// Decode and render video frame (native RTP payload)
println!("Received {} bytes at timestamp {}",
sample.data.len(), sample.timestamp);
decoder.decode(&sample.data).await?;
Ok(())
})
}).await?;§Architecture Note
MediaTrack uses WebRTC native RTP channels (RTCTrackRemote), NOT DataChannel. This provides:
- Zero protobuf serialization overhead
- Native RTP header information (timestamp, SSRC, etc.)
- Optimal latency (~1-2ms lower than DataChannel)
Sourcefn unregister_media_track<'life0, 'life1, 'async_trait>(
&'life0 self,
track_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn unregister_media_track<'life0, 'life1, 'async_trait>(
&'life0 self,
track_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Sourcefn send_media_sample<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
target: &'life1 Dest,
track_id: &'life2 str,
sample: MediaSample,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn send_media_sample<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
target: &'life1 Dest,
track_id: &'life2 str,
sample: MediaSample,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Send media samples via WebRTC native track
Sends raw media samples through WebRTC RTCRtpSender (native RTP). This is much more efficient than sending through DataChannel.
§Parameters
target: Target destinationtrack_id: Track identifiersample: Media sample to send
§Example
use actr_framework::{MediaSample, MediaType};
let sample = MediaSample {
data: encoded_frame.into(),
timestamp: rtp_timestamp,
codec: "H264".to_string(),
media_type: MediaType::Video,
};
ctx.send_media_sample(&target, "video-track-1", sample).await?;Sourcefn add_media_track<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>(
&'life0 self,
target: &'life1 Dest,
track_id: &'life2 str,
codec: &'life3 str,
media_type: &'life4 str,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
fn add_media_track<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>(
&'life0 self,
target: &'life1 Dest,
track_id: &'life2 str,
codec: &'life3 str,
media_type: &'life4 str,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
Add a media track to the WebRTC connection with the target
Creates a new RTP track on the PeerConnection and triggers SDP renegotiation.
Must be called before send_media_sample() for the given track.
§Parameters
target: Target destinationtrack_id: Media track identifiercodec: Codec name (e.g., “VP8”, “H264”, “OPUS”)media_type: Media type (“video” or “audio”)
Sourcefn remove_media_track<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
target: &'life1 Dest,
track_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn remove_media_track<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
target: &'life1 Dest,
track_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = ActorResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Remove a media track from the WebRTC connection with the target.
If the track exists, this removes the RTP sender from the PeerConnection and triggers SDP renegotiation so repeated start/stop cycles do not keep stale tracks alive on the connection.
Provided Methods§
Sourcefn log(&self, level: LogLevel, msg: &str)
fn log(&self, level: LogLevel, msg: &str)
Emit a log record from the workload side, routed through whichever observability pipeline the runtime installs.
The default implementation forwards to tracing using the configured
target = "actr_framework::workload". Runtimes that embed workloads
in environments without tracing (e.g. wasm32-unknown-unknown
running in a browser Service Worker) override this to surface records
through whatever host hook is available (console.log, host import, …).
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".