Expand description
§Murmer — A distributed actor framework for Rust
Murmer provides typed, location-transparent actors that communicate through
message passing. Whether an actor lives in the same process or on a remote
node across the network, you interact with it through the same Endpoint<A> API.
§Murmer in 1 minute
[dependencies]
murmer = "0.1"
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }ⓘ
use murmer::prelude::*;
// ① Define your actor — state lives separately
#[derive(Debug)]
struct Counter;
struct CounterState { count: i64 }
impl Actor for Counter {
type State = CounterState;
}
// ② Handlers become the actor's API
#[handlers]
impl Counter {
#[handler]
fn increment(
&mut self,
_ctx: &ActorContext<Self>,
state: &mut CounterState,
amount: i64,
) -> i64 {
state.count += amount;
state.count
}
#[handler]
fn get_count(
&mut self,
_ctx: &ActorContext<Self>,
state: &mut CounterState,
) -> i64 {
state.count
}
}
#[tokio::main]
async fn main() {
// ③ Create a local actor system
let system = System::local();
// ④ Start an actor — returns a typed Endpoint<Counter>
let counter = system.start("counter/main", Counter, CounterState { count: 0 });
// ⑤ Send messages via auto-generated extension methods
let result = counter.increment(5).await.unwrap();
println!("Count: {result}"); // → Count: 5
// ⑥ Look up actors by label — works for local and remote
let found = system.lookup::<Counter>("counter/main").unwrap();
let count = found.get_count().await.unwrap();
println!("Looked up: {count}"); // → Looked up: 5
}§What it gives you
- Send messages without caring where the actor lives.
counter.increment(5)works identically whether the actor is local or on a remote node —Endpoint<A>abstracts the difference away. - Test distributed systems from a single process.
System::localruns everything in-memory. Swap toSystem::clustered_autowhen ready for real networking — your actor code stays identical. - Define actors with minimal boilerplate. The
#[handlers]macro auto-generates message structs, dispatch tables, serialization, and ergonomic extension methods. - Get networking and encryption handled for you. QUIC transport with automatic TLS, SWIM-based cluster membership, and mDNS discovery — all configured, not hand-rolled.
- Supervise actors like OTP. Restart policies with configurable limits and exponential backoff keep your system running through failures.
§Core concepts
| Concept | Type | Purpose |
|---|---|---|
| Actor | Actor | Stateful message processor. State lives in an associated State type. |
| Message | Message | Defines a request and its response type. |
| RemoteMessage | RemoteMessage | A message that can cross the wire (serializable + TYPE_ID). |
| Endpoint | Endpoint<A> | Opaque send handle. Abstracts local vs remote — callers never know which. |
| Receptionist | Receptionist | Type-erased actor registry. Start, lookup, and subscribe to actors. |
| Router | Router<A> | Distributes messages across a pool of endpoints (round-robin, broadcast). |
| Listing | Listing<A> | Async stream of endpoints matching a ReceptionKey. |
§Location transparency
The key design principle: Endpoint<A> hides whether the actor is local or remote.
- Local actors use the envelope pattern — zero serialization cost, direct in-memory dispatch through a type-erased trait object.
- Remote actors serialize messages with bincode, send them over QUIC streams, and deserialize responses on return.
The caller’s code is identical in both cases:
ⓘ
let result = endpoint.send(Increment { amount: 5 }).await?;§Actor discovery
The Receptionist is the central registry for actor discovery:
- Labels identify actors with path-like strings (
"cache/user","worker/0"). - Typed lookup via
receptionist.lookup::<MyActor>("label")returnsOption<Endpoint<A>>. - Reception keys group actors by type for subscription-based discovery.
- Listings provide async streams of endpoints as actors register and deregister.
§Supervision
Actors are managed by supervisors that handle lifecycle and crash recovery:
RestartPolicy::Temporary— never restart (default)RestartPolicy::Transient— restart only on panicRestartPolicy::Permanent— always restart
Restart limits and exponential backoff are configured via RestartConfig.
§Clustering
The cluster module provides multi-node actor systems over QUIC:
- SWIM protocol membership via
focafor failure detection - mDNS discovery for zero-configuration LAN clustering
- OpLog replication with version vectors for consistent registry views
- Per-actor QUIC streams — one multiplexed connection per node pair
§Going from local to clustered
Only the system construction changes — all actor code stays identical:
ⓘ
// Local
let system = System::local();
// Clustered
let config = ClusterConfig::builder()
.name("my-node")
.listen("0.0.0.0:7100".parse()?)
.cookie("my-cluster-secret")
.build()?;
let system = System::clustered_auto(config).await?;§Learn more
- The Murmer Book — full guide with examples, diagrams, and deep-dives into every component
cluster— multi-node clustering and networkingreceptionist— actor discovery and subscriptionslifecycle— supervision, restart policies, and actor factoriesrouter— round-robin and broadcast routing across actor pools
Re-exports§
pub use actor::Actor;pub use actor::ActorContext;pub use actor::ActorRef;pub use actor::AsyncHandler;pub use actor::DispatchError;pub use actor::Handler;pub use actor::Message;pub use actor::MigratableActor;pub use actor::RemoteDispatch;pub use actor::RemoteMessage;pub use actor::ScheduleHandle;pub use client::ClientOptions;pub use client::MurmerClient;pub use endpoint::Endpoint;pub use lifecycle::ActorFactory;pub use lifecycle::ActorTerminated;pub use lifecycle::BackoffConfig;pub use lifecycle::RestartConfig;pub use lifecycle::RestartPolicy;pub use lifecycle::TerminateHook;pub use lifecycle::TerminationReason;pub use listing::Listing;pub use listing::ListingEvent;pub use listing::ReceptionKey;pub use listing::WatchedListing;pub use node::run_node_receiver;pub use oplog::Op;pub use oplog::OpType;pub use oplog::VersionVector;pub use ready::ReadyHandle;pub use receptionist::ActorEvent;pub use receptionist::Receptionist;pub use receptionist::ReceptionistConfig;pub use receptionist::Visibility;pub use router::PoolRouter;pub use router::Router;pub use router::RoutingStrategy;pub use runtime::Runtime;pub use runtime::SpawnHandle;pub use runtime::TokioRuntime;pub use system::System;pub use wire::DispatchRequest;pub use wire::RemoteInvocation;pub use wire::RemoteResponse;pub use wire::ReplySender;pub use wire::ResponseRegistry;pub use wire::SendError;
Modules§
- __
reexport - Re-export dependencies so generated code can reference them without the user needing them in their Cargo.toml.
- actor
- Core actor traits and types.
- client
- Edge client for connecting to a murmer cluster.
- cluster
- endpoint
- Endpoint — the user-facing send handle that abstracts local vs remote actors.
- lifecycle
- Lifecycle and restart types for actor supervision.
- listing
- Reception keys and listings for subscription-based actor discovery.
- node
- Node receiver — routes incoming remote invocations to local actors.
- oplog
- OpLog — operation log for distributed receptionist replication.
- prelude
- Convenience prelude — import everything you need for typical actor definitions.
- ready
- ReadyHandle — deferred actor startup.
- receptionist
- Receptionist — type-erased actor registry with typed lookup.
- router
- Router — distribute messages across a pool of actor endpoints.
- runtime
- Runtime seam — the single swappable abstraction murmer’s concurrency routes through.
- supervisor
- Supervisor — runs an actor, processing both local and remote messages.
- system
- System — unified entry point for local and clustered actor systems.
- wire
- Wire types for remote message dispatch.
Structs§
- Type
Registry Entry - An entry for auto-registration of an actor type in the cluster’s
cluster::sync::TypeRegistry.
Statics§
- ACTOR_
TYPE_ ENTRIES - Distributed slice populated by
#[handlers]macro expansions across all crates.
Attribute Macros§
- handlers
- Re-export proc macros from
murmer-macros(enabled by themacrosfeature, on by default).
Derive Macros§
- Message
- Re-export proc macros from
murmer-macros(enabled by themacrosfeature, on by default).