Skip to main content

Context

Trait Context 

Source
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 = Result<<R as RpcRequest>::Response, ActrError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, R: 'async_trait + RpcRequest, Self: 'async_trait; fn tell<'life0, 'life1, 'async_trait, R>( &'life0 self, target: &'life1 Dest, message: R, ) -> Pin<Box<dyn Future<Output = Result<(), ActrError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, R: 'async_trait + RpcRequest, Self: 'async_trait; fn register_stream<'life0, 'async_trait, F>( &'life0 self, stream_id: String, callback: F, ) -> Pin<Box<dyn Future<Output = Result<(), ActrError>> + Send + 'async_trait>> where 'life0: 'async_trait, F: Fn(DataStream, ActrId) -> Pin<Box<dyn Future<Output = Result<(), ActrError>> + Send>> + Send + Sync + 'static + 'async_trait, Self: 'async_trait; fn unregister_stream<'life0, 'life1, 'async_trait>( &'life0 self, stream_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<(), ActrError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: '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 = Result<(), ActrError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn discover_route_candidate<'life0, 'life1, 'async_trait>( &'life0 self, target_type: &'life1 ActrType, ) -> Pin<Box<dyn Future<Output = Result<ActrId, ActrError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: '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 = Result<Bytes, ActrError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait; fn register_media_track<'life0, 'async_trait, F>( &'life0 self, track_id: String, callback: F, ) -> Pin<Box<dyn Future<Output = Result<(), ActrError>> + Send + 'async_trait>> where 'life0: 'async_trait, F: Fn(MediaSample, ActrId) -> Pin<Box<dyn Future<Output = Result<(), ActrError>> + Send>> + Send + Sync + 'static + 'async_trait, Self: 'async_trait; fn unregister_media_track<'life0, 'life1, 'async_trait>( &'life0 self, track_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<(), ActrError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: '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 = Result<(), ActrError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: '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 = Result<(), ActrError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait, Self: '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 = Result<(), ActrError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: '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§

Source

fn self_id(&self) -> &ActrId

Get the current Actor’s ID

Source

fn caller_id(&self) -> Option<&ActrId>

Get the caller’s Actor ID

  • Some(caller_id): Called by another Actor
  • None: System internal call (e.g., lifecycle hooks)
Source

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.

Source

fn call<'life0, 'life1, 'async_trait, R>( &'life0 self, target: &'life1 Dest, request: R, ) -> Pin<Box<dyn Future<Output = Result<<R as RpcRequest>::Response, ActrError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, R: 'async_trait + RpcRequest, Self: '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 failure
  • ProtocolError::Actr(DecodeFailure): Response decode failure
  • ProtocolError::Actr(UnknownRoute): Route does not exist
  • Errors returned by remote Actor’s business logic
§Parameters
  • target: Target destination (Dest::Shell for local, Dest::Actor(id) for remote)
  • request: Request message implementing RpcRequest trait
§Returns

Returns response message of type R::Response

Source

fn tell<'life0, 'life1, 'async_trait, R>( &'life0 self, target: &'life1 Dest, message: R, ) -> Pin<Box<dyn Future<Output = Result<(), ActrError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, R: 'async_trait + RpcRequest, Self: '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::Shell for local, Dest::Actor(id) for remote)
  • message: Message implementing RpcRequest trait
Source

fn register_stream<'life0, 'async_trait, F>( &'life0 self, stream_id: String, callback: F, ) -> Pin<Box<dyn Future<Output = Result<(), ActrError>> + Send + 'async_trait>>
where 'life0: 'async_trait, F: Fn(DataStream, ActrId) -> Pin<Box<dyn Future<Output = Result<(), ActrError>> + Send>> + Send + Sync + 'static + 'async_trait, Self: '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?;
Source

fn unregister_stream<'life0, 'life1, 'async_trait>( &'life0 self, stream_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<(), ActrError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Unregister a DataStream callback

§Parameters
  • stream_id: Stream identifier to unregister
Source

fn send_data_stream<'life0, 'life1, 'async_trait>( &'life0 self, target: &'life1 Dest, chunk: DataStream, payload_type: PayloadType, ) -> Pin<Box<dyn Future<Output = Result<(), ActrError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: '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 destination
  • chunk: DataStream to send
  • payload_type: Lane selection (StreamReliable or StreamLatencyFirst)
Source

fn discover_route_candidate<'life0, 'life1, 'async_trait>( &'life0 self, target_type: &'life1 ActrType, ) -> Pin<Box<dyn Future<Output = Result<ActrId, ActrError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: '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.

Source

fn call_raw<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, target: &'life1 ActrId, route_key: &'life2 str, payload: Bytes, ) -> Pin<Box<dyn Future<Output = Result<Bytes, ActrError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: '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 ID
  • route_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?;
Source

fn register_media_track<'life0, 'async_trait, F>( &'life0 self, track_id: String, callback: F, ) -> Pin<Box<dyn Future<Output = Result<(), ActrError>> + Send + 'async_trait>>
where 'life0: 'async_trait, F: Fn(MediaSample, ActrId) -> Pin<Box<dyn Future<Output = Result<(), ActrError>> + Send>> + Send + Sync + 'static + 'async_trait, Self: '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)
Source

fn unregister_media_track<'life0, 'life1, 'async_trait>( &'life0 self, track_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<(), ActrError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Unregister a media track callback

§Parameters
  • track_id: Media track identifier to unregister
Source

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 = Result<(), ActrError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: '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 destination
  • track_id: Track identifier
  • sample: 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?;
Source

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 = Result<(), ActrError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait, Self: '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 destination
  • track_id: Media track identifier
  • codec: Codec name (e.g., “VP8”, “H264”, “OPUS”)
  • media_type: Media type (“video” or “audio”)
Source

fn remove_media_track<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, target: &'life1 Dest, track_id: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), ActrError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: '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§

Source

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".

Implementors§