Cruster
A Rust framework for building distributed, stateful entity systems with durable workflows.
Cruster provides a distributed actor/entity model with consistent-hashing-based shard assignment, persistent messaging, singleton management, durable workflows, and cron scheduling.
Project Status: This project is under active development and not yet ready for production use. The API may change without notice. It is currently being developed alongside an internal project. Feedback and contributions are welcome, but please be aware of the experimental nature of this library.
Features
- Entity System - Define stateful actors with automatic persistence and lifecycle management
- Durable Workflows - Long-running operations that survive crashes and restarts
- Activity Journaling - State mutations with transactional guarantees and replay safety
- Entity Traits - Composable behaviors that can be mixed into multiple entities
- Singletons - Cluster-wide unique instances with automatic failover
- Scheduled Tasks - Cron-based scheduling with distributed coordination
- gRPC Transport - Built-in inter-node communication with streaming support
- Storage - PostgreSQL for persistence, etcd for cluster formation & health monitoring
Installation
Prerequisites
Cruster requires the Protocol Buffers compiler (protoc) to be installed for building gRPC support:
# Debian/Ubuntu
# macOS
# Windows (with Chocolatey)
Cargo
Add to your Cargo.toml:
[]
= "0.1"
= "0.1"
Quick Start
Defining an Entity
use *;
use ;
// Define the entity's state
// Define the entity
;
Using the Entity
use TestCluster;
async
Core Concepts
Method Types
| Annotation | Purpose | Self Type | Journaled | Callable From |
|---|---|---|---|---|
#[rpc] |
Read-only operations | &self |
No | External clients |
#[activity] |
State mutations and side effects | &mut self |
Yes | Workflows, other activities |
#[workflow] |
Orchestrate activities | &self |
Yes | External clients |
#[method] |
Read-only helpers | &self |
No | Internal only |
Visibility Modifiers
#[public]- Callable from generated client (default for#[rpc]and#[workflow])#[protected]- Callable within the entity and by composed traits#[private]- Callable only within the defining scope (default for#[activity])
State Persistence
All entity state is automatically persisted. When an entity is evicted from memory (due to idle timeout) and later reactivated, its state is restored from storage.
// State is always persisted
Durable Workflows
Workflows orchestrate multiple activities and survive crashes. On restart, workflows replay from their journal, skipping already-completed activities.
Idempotency Keys
Activities and workflows are deduplicated by their idempotency key. The default key is hash(method_name, serialized_params).
Custom keys can be specified:
async
Entity Traits
Traits provide reusable behaviors that can be composed into entities:
// Define a trait
// Compose into an entity
Singletons
Singletons are cluster-wide unique instances. Only one instance runs at a time, with automatic failover if the hosting node fails.
use singleton;
// Register a singleton using the builder API
singleton
.register
.await?;
// Or use the direct function
use register_singleton;
register_singleton.await?;
Deferreds (Async Coordination)
Deferreds allow workflows to wait for signals from other parts of the system:
Timers and Sleep
Durable sleep that survives restarts:
async
Cluster Configuration
Single Node (Development)
use SingleRunner;
let runner = new.await?;
runner.register.await?;
runner.start.await?;
Multi-Node (Production)
use ShardingConfig;
use ShardingImpl;
let config = ShardingConfig ;
let sharding = new.await?;
sharding.register_entity.await?;
sharding.start.await?;
Configuration Options
| Option | Default | Description |
|---|---|---|
shards_per_group |
2048 | Number of shards per shard group |
entity_max_idle_time |
60s | Entity eviction timeout |
entity_mailbox_capacity |
100 | Per-entity message queue size |
storage_poll_interval |
500ms | Message storage polling frequency |
storage_message_max_retries |
10 | Max delivery attempts before dead-letter |
Storage
PostgreSQL
Used for:
- Entity state persistence
- Message storage (at-least-once delivery)
- Workflow journals
- Timer and deferred value storage
Required tables are created via migrations in migrations/.
etcd
Used for:
- Runner registration and discovery
- Shard lock acquisition
- Health monitoring
- Leader election
Testing
TestCluster
An in-memory cluster for unit tests:
use TestCluster;
async
Examples
cluster-tests
E2E test suite demonstrating all features. Requires PostgreSQL and etcd:
# Start infrastructure (Postgres and etcd)
# Run the test runner
POSTGRES_URL=postgres://postgres:postgres@localhost/cluster \
ETCD_ENDPOINTS=localhost:2379 \
RUNNER_ADDRESS=localhost:9000 \
# In another terminal, run the bash tests:
chess-cluster
Distributed chess server demonstrating:
- Player sessions (in-memory state)
- Game state persistence (workflows)
- Matchmaking service (stateless entity)
- Leaderboard singleton
- Move timeouts (scheduled messages)
- Auditable trait composition
Note: The HTTP API layer (M3) is not yet implemented. Currently only the entity layer is complete and can be tested via TestCluster:
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Client │
└───────────────────────────┬─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Sharding Layer │
│ - Consistent hashing for shard assignment │
│ - Request routing to correct runner │
│ - Storage polling for persisted messages │
└───────────────────────────┬─────────────────────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Runner 1 │ │ Runner 2 │ │ Runner 3 │
│ Shards 0-42 │ │ Shards 43-85 │ │ Shards 86-127│
└───────┬───────┘ └───────┬───────┘ └───────┬───────┘
│ │ │
└──────────────────┴──────────────────┘
│
┌──────────────┴──────────────┐
▼ ▼
┌───────────────┐ ┌───────────────┐
│ PostgreSQL │ │ etcd │
│ - State │ │ - Runners │
│ - Messages │ │ - Shard locks│
│ - Journals │ │ - Health │
└───────────────┘ └───────────────┘
API Reference
See specs/architecture.md for detailed API documentation.
License
MIT