5 releases
Uses new Rust 2024
| 0.1.5 | Jan 4, 2026 |
|---|---|
| 0.1.4 | Dec 1, 2025 |
| 0.1.3 | Nov 25, 2025 |
| 0.1.1 | Nov 9, 2025 |
| 0.1.0 | Nov 9, 2025 |
#5 in #req
Used in 4 crates
(3 directly)
97KB
1.5K
SLoC
actr-framework
Actor-RTC core programming interface layer - defines the contract for user-framework interaction.
Architectural Positioning
actr-framework is the SDK interface layer of the actr system, positioned in the middle tier:
User Application (Workload implementation)
↓ depends on
actr-framework (this crate) ← Stable API contract (trait definitions only)
↓ depends on
actr-protocol ← Data type definitions
↑ implements
actr-runtime ← Runtime implementation (implements Context trait)
Core Responsibilities
- Define user programming interface:
Workload,MessageDispatchertraits - Define execution context interface:
Contexttrait (implemented by runtime) - Type-safe RPC:
Context::call()andContext::tell()methods - Lifecycle management:
on_start,on_stophooks
Design Principles
1. Interface-only, Zero Implementation
// ✅ Framework defines
pub trait Context {
async fn call<R: RpcRequest>(...) -> ActorResult<R::Response>;
}
// ✅ Runtime implements
impl Context for RuntimeContext { ... }
Framework contains no implementation code, all logic is in runtime.
2. Dependency Inversion Principle
- Framework defines traits, Runtime implements traits
- User code only depends on framework, not runtime
- Context trait can be mocked for unit testing
3. Zero-Cost Abstraction
- Use generics instead of trait objects (
<C: Context>not&dyn Context) - Compile-time monomorphization, static dispatch
- Compiler can fully inline the entire call chain
- Zero virtual function call overhead
Core Type System
4-Trait Architecture
actr builds a type-safe message handling system with 4 traits:
┌─────────────────────────────────────────────────────────┐
│ 1. RpcRequest trait (actr-protocol) │
│ - Associates Request and Response types │
│ - Provides route_key() static method │
└─────────────────────────────────────────────────────────┘
↓ used by
┌─────────────────────────────────────────────────────────┐
│ 2. Concrete Handler trait (code generated) │
│ - e.g., EchoServiceHandler<C: Context> │
│ - async fn echo<C: Context>(&self, req, ctx: &C) │
└─────────────────────────────────────────────────────────┘
↓ wrapped by
┌─────────────────────────────────────────────────────────┐
│ 3. MessageDispatcher trait (this crate) │
│ - Static routing: route_key → handler method │
│ - Zero-sized type (ZST), zero runtime overhead │
└─────────────────────────────────────────────────────────┘
↓ associated with
┌─────────────────────────────────────────────────────────┐
│ 4. Workload trait (this crate) │
│ - Associates Dispatcher type │
│ - Provides on_start(), on_stop() hooks │
└─────────────────────────────────────────────────────────┘
Usage Example
use actr_framework::{Context, Workload};
// Code-generated Handler trait
#[async_trait]
pub trait EchoServiceHandler: Send + Sync + 'static {
async fn echo<C: Context>(
&self,
req: EchoRequest,
ctx: &C,
) -> ActorResult<EchoResponse>;
}
// User implements business logic
impl EchoServiceHandler for MyService {
async fn echo<C: Context>(
&self,
req: EchoRequest,
ctx: &C,
) -> ActorResult<EchoResponse> {
// Access context data
tracing::info!("trace_id: {}", ctx.trace_id());
// Type-safe RPC call
let response = ctx.call(&target, another_request).await?;
Ok(EchoResponse {
reply: format!("Echo: {}", req.message),
})
}
}
Dependencies
~12–32MB
~395K SLoC