This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Before declaring any code change complete, you MUST run the following and resolve ALL errors and warnings:
# Format all code (fix in place)
cargo fmt --all
# Run clippy with strict settings — ALL warnings must be resolved
cargo clippy --all -- -D clippy::all -D warningsDo NOT skip these steps. Do NOT declare a task done if either command produces errors or warnings. Fix any issues and re-run until clean.
Ractor is a pure-Rust actor framework inspired by Erlang's gen_server, providing lightweight actors with single-threaded message processing, supervision trees, and optional distributed clustering capabilities.
This is a Cargo workspace with multiple crates:
- ractor: Core actor framework library
- ractor_cluster: Distributed cluster support (experimental)
- ractor_cluster_derive: Procedural macros for cluster message serialization
- ractor_cluster_integration_tests: Integration tests for clustering
- ractor_example_entry_proc: Example entry point procedures
- ractor_playground: Playground/experimentation crate
- xtask: Build/development automation tasks
# Run all tests
cargo test
# Run tests for a specific package
cargo test --package ractor
cargo test --package ractor_cluster
# Run tests with specific feature flags
cargo test --package ractor --features cluster
cargo test --package ractor --features async-std,message_span_propogation --no-default-features
cargo test --package ractor --features monitors
cargo test --package ractor --features blanket_serde
# Run a specific test
cargo test --package ractor --test <test_name>
cargo test --package ractor <test_name>To reproduce a CI failure locally, find the matching row and run cargo test --package <package> <flags>:
| CI Job Name | Package | Flags |
|---|---|---|
| Run the default tests | ractor | (none) |
| Test ractor with async-trait | ractor | -F async-trait |
| Test ractor without span propogation | ractor | --no-default-features -F tokio_runtime |
Test ractor with the cluster feature |
ractor | -F cluster |
Test ractor with the blanket_serde feature |
ractor | -F blanket_serde |
| Test ractor with async-std runtime | ractor | --no-default-features -F async-std,message_span_propogation |
| Test ractor with async-std runtime but no span propagation | ractor | --no-default-features -F async-std |
| Test ractor with async-std runtime and async-trait | ractor | --no-default-features -F async-std,async-trait |
| Test ractor_cluster with native async traits | ractor_cluster | (none) |
| Test ractor_cluster with async_trait | ractor_cluster | -F async-trait |
| Test ractor with the monitor API | ractor | -F monitors |
| Test ractor with output-port-v2 feature | ractor | -F output-port-v2 |
| Test ractor without output-port-v2 feature (explicit) | ractor | --no-default-features -F tokio_runtime,message_span_propogation |
CI also runs: clippy, rustfmt --check, cargo doc --lib -r, and cargo bench --no-run.
# Run benchmarks
cargo bench -p ractor
# Compile benchmarks without running
cargo bench --no-run# Run clippy
cargo clippy --all -- -D clippy::all -D warnings
# Run rustfmt
cargo fmt --all
# Check formatting without modifying
cargo fmt --all -- --check# Build documentation
cargo doc --lib
# Build documentation in release mode
cargo doc --lib -rRactor implements the actor model with these key components:
-
Actor: The trait defining actor behavior (
Actortrait forSendactors,ThreadLocalActorfor!Sendactors)pre_start: Initialize actor state (fallible, errors returned to spawner)post_start: Post-initialization hookhandle: Process incoming messageshandle_supervisor_evt: Handle supervision events from childrenpost_stop: Cleanup on shutdown
-
ActorCell: Reference-counted primitive representing an actor's communication channels
- Contains message ports (signal, stop, supervision, message)
- Manages actor lifecycle status (Unstarted, Starting, Running, Upgrading, Draining, Stopping, Stopped)
-
ActorRef: Strongly-typed wrapper over ActorCell for type-safe communication
- Primary interface for sending messages to actors
- Derefs to ActorCell for access to lower-level operations
Without cluster feature: blanket impl<T: Any + Send + Sized + 'static> Message for T — any Send + 'static type works as a message with zero boilerplate.
With cluster feature: the blanket impl is replaced by one requiring BytesConvertable. For enum message types, use derive macros:
#[derive(RactorMessage)]— local-only actors (marks as non-serializable)#[derive(RactorClusterMessage)]— remote-capable actors (generates serialization). Mark RPC variants with#[rpc].
RactorClusterMessage supports:
- Both tuple-style (
Variant(A, B)) and struct-style (Variant { a: A, b: B }) fields RpcReplyPort<T>at any position in#[rpc]variants (detected by type scan, not position)- Exactly one
RpcReplyPort<T>per#[rpc]variant (compile error on 0 or 2+) - Using
RpcReplyPortwithout#[rpc]produces a helpful compile error
The wire format is purely positional — field names and port position don't affect serialization. Internal codegen variables are __-prefixed to avoid collisions with user field names.
See ractor/src/message.rs for trait definition and ractor_cluster_derive/ for the proc macros.
Messages are processed in strict priority order (see docs/runtime-semantics.md):
- Signals (highest): Immediate termination (e.g.,
Signal::Kill) - Stop: Graceful shutdown request
- SupervisionEvent: Child actor lifecycle notifications
- Messages (lowest): User-defined work messages
self: Read-only reference containing configuration/constants (ideally empty)State: Mutable state managed by the actor, initialized inpre_start
- Actors form supervision trees through linking
- Parent actors receive
SupervisionEventmessages on child lifecycle changes - Panics in message handlers are caught and reported to supervisors (unless
panic = "abort") - Panics in
pre_startreturn errors to the spawner without starting the actor
DerivedActorRef<TFrom> (ractor/src/actor/derived_actor.rs) wraps an ActorCell to accept a subset of an actor's message type via From conversion. This provides interface isolation — callers only see the subset type, not the full message enum. Obtain one via actor_ref.get_derived::<SubsetType>(). Requires impl From<SubsetType> for FullMsg and impl TryFrom<FullMsg> for SubsetType.
ractor::pg (ractor/src/pg.rs) provides Erlang-style named process groups — global, scope-aware collections of actors.
pg::join(group, actors)/pg::leave(group, actors)— add/remove actors (actors auto-leave on shutdown)pg::get_members(group)/pg::get_local_members(group)— retrieve group memberspg::which_groups()/pg::which_scopes()— enumerate registered namespg::monitor(group, actor)/pg::demonitor(group, actor_id)— subscribe toSupervisionEvent::ProcessGroupChanged- Scoped variants:
join_scoped,get_scoped_members,monitor_scope,demonitor_scope
ractor::registry (ractor/src/registry.rs) provides actor lookup by name.
- Actors with a
Some(name)passed toActor::spawnare auto-registered and auto-unregistered on drop registry::where_is(name) -> Option<ActorCell>— look up by nameregistry::registered() -> Vec<ActorName>— list all registered names- With
clusterfeature:pid_registrysub-module addswhere_is_pidandPidLifecycleEvent
The factory module provides worker pools for parallel job processing:
- Worker: Trait for defining job processing logic
- Factory: Manages a pool of workers with configurable routing
- Routing modes: KeyPersistent, StickyQueuer, Queuer, RoundRobin, Custom
- Queueing: DefaultQueue, PriorityQueue
- Factory handles worker lifecycle, automatically restarting failed workers
The thread_local module supports !Send types:
- Must use Tokio runtime with
rtfeature (relies ontokio::task::LocalSet) - Use
ThreadLocalActortrait instead ofActor - Spawn with
ractor::spawn_local()andThreadLocalActorSpawner - State does not need to be
SendorSync
cluster: Exposes functionality forractor_cluster(network-distributed actors)async-std: Use async-std runtime instead of tokio (tokio sync primitives still used)monitors: Erlang-style monitoring API (alternative to direct linking)message_span_propogation: Propagate tracing spans through actor messagestokio_runtime: Tokio runtime support (default)blanket_serde: Serde serialization supportoutput-port-v2: Experimental output port v2async-trait: Use async-trait crate instead of native async traits
Default features: tokio_runtime, message_span_propogation
- NodeServer: Manages node connections and incoming sessions
- NodeSession: Handles TCP connections, authentication, message routing, and remote actor lifecycle
- RemoteActor: Untyped actor handling serialized messages from remote nodes
- See
ractor_cluster/src/node/for implementation andractor_cluster_derive/for message serialization macros
- MSRV: Rust 1.64
- Native async fn in traits requires Rust >= 1.75 (otherwise use
async-traitfeature) - Thread-local actors REQUIRE tokio runtime with
rtfeature - WASM support available (target
wasm32-unknown-unknown)
- Unit tests:
#[cfg(test)] mod testswithin each module - Integration tests:
ractor_cluster_integration_tests/crate - Some tests require
serial_testcrate for sequential execution
ractor/src/common_test.rs provides helpers used throughout the test suite:
periodic_check(closure, timeout)— polls aFn() -> boolevery 50ms until true or timeout (then asserts)periodic_async_check(closure, timeout)— same but forasync Fn() -> Future<Output = bool>
Critical files for understanding the architecture:
ractor/src/actor.rs: Core Actor trait and spawn logicractor/src/actor/actor_cell.rs: ActorCell and ActorPortSet (message multiplexing)ractor/src/actor/actor_ref.rs: Strongly-typed ActorRef wrapperractor/src/actor/derived_actor.rs: DerivedActorRef for interface isolationractor/src/message.rs: Message trait definition and blanket implsractor/src/concurrency.rs: Runtime-abstracted channel/timer primitives (tokio vs async-std)ractor/src/pg.rs: Process groups (named actor groups)ractor/src/registry.rs: Named actor registryractor/src/factory.rs: Worker pool patternractor/src/thread_local.rs: Thread-local actor supportractor/src/common_test.rs: Test utilities (periodic_check,periodic_async_check)ractor_cluster/src/node/: NodeServer and NodeSession implementationsractor_cluster_derive/src/ir.rs: Intermediate representation (ParsedEnum, ParsedVariant, FieldStyle, VariantKind)ractor_cluster_derive/src/parse.rs: Parsing and validation of derive inputractor_cluster_derive/src/codegen.rs: Code generation forimpl Messagedocs/runtime-semantics.md: Detailed runtime guarantees and edge cases