Skip to main content

Crate murmer

Crate murmer 

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

Read the book →  ·  GitHub


§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::local runs everything in-memory. Swap to System::clustered_auto when 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

ConceptTypePurpose
ActorActorStateful message processor. State lives in an associated State type.
MessageMessageDefines a request and its response type.
RemoteMessageRemoteMessageA message that can cross the wire (serializable + TYPE_ID).
EndpointEndpoint<A>Opaque send handle. Abstracts local vs remote — callers never know which.
ReceptionistReceptionistType-erased actor registry. Start, lookup, and subscribe to actors.
RouterRouter<A>Distributes messages across a pool of endpoints (round-robin, broadcast).
ListingListing<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") returns Option<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:

Restart limits and exponential backoff are configured via RestartConfig.

§Clustering

The cluster module provides multi-node actor systems over QUIC:

  • SWIM protocol membership via foca for 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 networking
  • receptionist — actor discovery and subscriptions
  • lifecycle — supervision, restart policies, and actor factories
  • router — 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§

TypeRegistryEntry
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 the macros feature, on by default).

Derive Macros§

Message
Re-export proc macros from murmer-macros (enabled by the macros feature, on by default).