This file provides guidance to WARP (warp.dev) when working with code in this repository.
joerl is an Erlang-inspired actor model library for Rust, named in tribute to Joe Armstrong, the creator of Erlang. It implements the actor model with supervision trees, links, monitors, and bounded mailboxes using Rust's async/await built on tokio.
Erlang-style generic server with call (synchronous) and cast (asynchronous) operations.
Finite state machines defined with Mermaid diagrams, compiled to Rust code with validation.
- EPMD server and client for node discovery
- Location-transparent messaging between nodes
- Unified ActorSystem API (same for local and distributed)
- TCP transport with automatic reconnection
- Message serialization with global registry
Full Erlang/OTP-style panic recovery:
- Panics caught automatically
- Links and monitors notified
- Supervisors restart panicked actors
- Guaranteed cleanup (no leaks)
System health checks with configurable thresholds for:
- Active actor count
- Message processing rates
- Supervisor restart rates
Metrics and observability with Prometheus/OpenTelemetry support.
cargo build # Build the library
cargo build --release # Build optimized release versioncargo test # Run all tests (unit + integration + doc tests)
cargo test test_name # Run specific test by name
cargo test -- --nocapture # Run tests with output visible
cargo test --doc # Run only doc tests
cargo test --test integration_test # Run integration tests onlycargo fmt # Format code (required before commits)
cargo clippy --all-targets --all-features -- -D warnings # Run linter (CI enforces this)cargo install cargo-tarpaulin # Install coverage tool (once)
cargo tarpaulin --out Html # Generate HTML coverage report
cargo tarpaulin --verbose --all-features --workspace --timeout 120 --out Xml # CI-style coveragecargo run --example counter # Run counter example
cargo run --example ping_pong # Run ping-pong examplecargo bench # Run benchmarks (uses Criterion)The library follows a modular design organized around core actor system concepts:
-
actor: Defines theActortrait andActorContext. All actors implement theActortrait withhandle_message()as the main entry point. The context provides access to the actor's Pid, mailbox operations, and lifecycle control (trap_exit, stop). -
system: TheActorSystemis the runtime that manages all actors. It maintains aDashMapregistry mappingPidtoActorEntry(containing mailbox sender, links, monitors). Spawning returns anActorRefwhich is used to send messages and interact with actors. -
pid: Process identifiers using UUID v7 for unique, time-ordered actor IDs. Now includes node support for distributed systems. -
mailbox: Bounded MPSC channels (using tokio) that provide backpressure. Messages are wrapped inEnvelopewhich can contain either user messages or system signals. -
message: DefinesMessage(type-erasedBox<dyn Any>),Signalenum (Exit, Down, Stop, Kill), andExitReasonfor actor termination. -
gen_server: Implements Erlang's gen_server behavior with call/cast semantics for structured request-reply patterns. -
gen_statem: Implements Erlang's gen_statem with Mermaid DSL for defining finite state machines with compile-time validation. -
supervisor: Implements Erlang/OTP supervision trees. Supervisors monitor children and restart them according to strategies (OneForOne,OneForAll,RestForOne). Includes restart intensity limits to prevent infinite loops. -
distributed: Distributed actor system with location transparency. Wraps ActorSystem with EPMD integration, node discovery, and TCP transport. -
epmd: Erlang Port Mapper Daemon implementation for node discovery and registration (client and server). -
serialization: Trait-based message serialization system with global registry for remote messaging. -
health: System health monitoring with configurable checks for actor counts, message rates, and resource usage. -
telemetry: Optional metrics and observability support (requires "telemetry" feature). -
error: Error types and Result alias usingthiserror.
- Spawn: Actor registered in system, given Pid and mailbox, tokio task spawned
- Started:
Actor::started()hook called for initialization - Message Loop: Actor processes messages/signals from mailbox sequentially
- Stopped:
Actor::stopped()hook called, links/monitors notified, cleanup performed
-
Message Passing: All communication via type-erased messages (
Box<dyn Any + Send>). Actors downcast to expected types. -
Links vs Monitors: Links are bidirectional (both actors fail together), monitors are unidirectional (observer receives DOWN signal). Actors can trap exits to handle failures gracefully.
-
Supervision: Supervisors use factory functions (
Box<dyn FnMut() -> Box<dyn Actor>>) to recreate children. They track restart times to enforce intensity limits.
This library intentionally mirrors Erlang/OTP concepts and terminology. When implementing features or fixing bugs:
- Use Erlang terminology in APIs and documentation (e.g.,
Pid,trap_exit,monitor) - Follow Erlang semantics (e.g., normal exit doesn't trigger restarts, links are bidirectional)
- Reference Erlang/OTP documentation for expected behavior
- See README.md "Erlang Terminology Mapping" table for exact equivalents
- All new features require tests (unit and/or integration)
- Target >80% code coverage
- Test edge cases, error conditions, and concurrent scenarios
- Use descriptive test names explaining what is being tested
- All actor operations are async using tokio
- Use
#[async_trait]for theActortrait - Be careful with blocking operations—use
tokio::task::spawn_blockingif needed - Actors process messages sequentially but the system is concurrent
- Use
ActorErrorandResult<T>types consistently - Send operations can fail if actor dead or mailbox full
- Link/monitor operations can fail if actors don't exist
- Document all public APIs with rustdoc comments (
///) - Include examples in documentation when helpful
- Reference Erlang equivalents in doc comments
- Keep README.md synchronized with API changes
GitHub Actions runs on push/PR to main:
- test: All tests including doc tests
- fmt: Checks code formatting with
cargo fmt --check - clippy: Lints with warnings as errors
- coverage: Generates coverage report using tarpaulin, uploads to Codecov
All checks must pass before merging.
Follow conventional commits format:
feat:- New featuresfix:- Bug fixesdocs:- Documentation changestest:- Test additions/changesrefactor:- Code refactoringperf:- Performance improvementschore:- Maintenance tasks
Example: feat: add support for named actors in registry