aether-persistence
WAL-backed durable state with PostgreSQL, Redis, and NATS backends
The aether-persistence crate provides durable state management for Aether worlds, including a write-ahead log, ephemeral checkpointing, snapshot policies, and trait-based abstractions for PostgreSQL, Redis, and NATS backends.
Overview
World state must survive server restarts and handle failover gracefully. This crate provides a policy-driven persistence layer:
- Write-ahead log (WAL) that ensures durability by recording state mutations before applying them.
- Snapshot system with configurable intervals for ephemeral and durable checkpoints.
- Critical state tracking for high-priority mutations that require immediate durability.
- PostgreSQL backend for durable relational storage.
- Redis backend for fast ephemeral caching.
- NATS JetStream for event bus with durable subscriptions.
- Connection pooling with environment-variable-driven configuration.
- Database migrations framework for schema evolution.
Key Types
PersistenceRuntime
The top-level runtime that coordinates WAL writes, snapshots, and backend interactions.
use aether_persistence::{PersistenceRuntime, PersistenceRuntimeConfig};
let config = PersistenceRuntimeConfig {
wal_flush_interval_ms: 100,
snapshot_interval_seconds: 300,
backend: "postgres".into(),
};
let runtime = PersistenceRuntime::new(config);
WalWriteCoordinator
Manages write-ahead log entries, ensuring mutations are recorded before being applied.
use aether_persistence::{WalWriteCoordinator, WalEntry, WalDurability, WalAppendResult};
let mut wal = WalWriteCoordinator::new();
let result: WalAppendResult = wal.append(WalEntry {
sequence: next_seq,
data: mutation_bytes,
durability: WalDurability::Fsync,
})?;
SnapshotRecorder
Captures periodic snapshots of world state for fast recovery.
use aether_persistence::{SnapshotRecorder, SnapshotPolicy, SnapshotKind, Snapshot};
let recorder = SnapshotRecorder::new(SnapshotPolicy {
interval_seconds: 300,
kind: SnapshotKind::Full,
max_retained: 5,
});
let snapshot: Snapshot = recorder.capture(&world_state)?;
WorldPersistenceProfile
Configures the persistence behavior for a specific world.
use aether_persistence::{WorldPersistenceProfile, WorldPersistenceClass};
let profile = WorldPersistenceProfile {
class: WorldPersistenceClass::Durable,
wal_enabled: true,
snapshot_interval_seconds: 300,
};
DatabaseClient
PostgreSQL client for durable state operations.
use aether_persistence::{DatabaseClient, ConnectionConfig};
let config = ConnectionConfig::from_env()?;
let client = DatabaseClient::new(config).await?;
CacheClient
Redis client for ephemeral state caching.
use aether_persistence::{CacheClient, ConnectionConfig};
let config = ConnectionConfig::from_env()?;
let cache = CacheClient::new(config).await?;
EventBus
NATS JetStream event bus for durable event distribution.
use aether_persistence::{EventBus, EventMessage, EventSubscription};
let bus = EventBus::new(nats_config).await?;
bus.publish("world.events", EventMessage {
topic: "entity.spawned".into(),
payload: event_bytes,
}).await?;
Migration
Database migration framework for schema evolution.
use aether_persistence::Migration;
let migration = Migration {
version: 3,
name: "add_world_metadata".into(),
up_sql: "ALTER TABLE worlds ADD COLUMN metadata JSONB;".into(),
down_sql: "ALTER TABLE worlds DROP COLUMN metadata;".into(),
};
Usage Examples
World Recovery
use aether_persistence::{
WorldRecovery, WalWriteCoordinator, SnapshotRecorder, Snapshot,
};
// On server restart, replay from latest snapshot + WAL entries
let snapshot = SnapshotRecorder::load_latest()?;
let wal_entries = WalWriteCoordinator::replay_after(snapshot.sequence)?;
let recovered_state = WorldRecovery::restore(snapshot, wal_entries)?;
Critical State Write
use aether_persistence::{
SyncStateMutation, CriticalStateKey, CriticalStatePriority,
};
let mutation = SyncStateMutation {
key: CriticalStateKey::new("player_inventory", player_id),
priority: CriticalStatePriority::High,
data: inventory_bytes,
};