Skip to main content

nexus-persistence-dbal

Doctrine DBAL adapter for Nexus persistence -- SQL-backed stores using parameterized queries. Supports any database supported by DBAL (SQLite, PostgreSQL, MySQL, etc.).

Composer: nexus-actors/persistence-dbal

Namespace: Monadial\Nexus\Persistence\Dbal\

View class diagram

Dependencies: doctrine/dbal ^4.0

Classes

ClassDescription
DbalEventStoreEventStore implementation using DBAL. Constructor: Connection, MessageSerializer (default: PhpNativeSerializer). Throws ConcurrentModificationException on duplicate sequence numbers.
DbalSnapshotStoreSnapshotStore implementation using DBAL. Constructor: Connection, MessageSerializer (default: PhpNativeSerializer).
DbalDurableStateStoreDurableStateStore implementation using DBAL. Constructor: Connection, MessageSerializer (default: PhpNativeSerializer). Uses optimistic locking via WHERE version = ? on updates.
DbalPessimisticLockProviderPessimisticLockProvider implementation using SELECT ... FOR UPDATE. Constructor: Connection. Uses a dedicated nexus_persistence_lock table for row-level locks.
PersistenceSchemaManagerCreates and drops database tables. Constructor: Connection. Methods: createSchema(), dropSchema(). Lives in Schema\ sub-namespace.

Table schema

The PersistenceSchemaManager creates the following tables:

nexus_event_journal

ColumnTypeNotes
persistence_idVARCHAR(255)Primary key (composite)
sequence_nrBIGINTPrimary key (composite)
event_typeVARCHAR(255)
event_dataTEXT
metadataTEXTNullable
timestampDATETIMEImmutable

Index: idx_event_journal_pid on persistence_id.

nexus_snapshot_store

ColumnTypeNotes
persistence_idVARCHAR(255)Primary key (composite)
sequence_nrBIGINTPrimary key (composite)
state_typeVARCHAR(255)
state_dataTEXT
timestampDATETIMEImmutable

nexus_durable_state

ColumnTypeNotes
persistence_idVARCHAR(255)Primary key
versionBIGINTOptimistic lock version
state_typeVARCHAR(255)
state_dataTEXT
timestampDATETIMEImmutable

nexus_persistence_lock

ColumnTypeNotes
persistence_idVARCHAR(255)Primary key

Used by DbalPessimisticLockProvider to acquire exclusive row-level locks via SELECT ... FOR UPDATE.

Usage

use Doctrine\DBAL\DriverManager;
use Monadial\Nexus\Persistence\Dbal\DbalEventStore;
use Monadial\Nexus\Persistence\Dbal\DbalSnapshotStore;
use Monadial\Nexus\Persistence\Dbal\DbalDurableStateStore;
use Monadial\Nexus\Persistence\Dbal\Schema\PersistenceSchemaManager;

$connection = DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => 'nexus.db']);

// Create tables (idempotent -- skips existing tables)
(new PersistenceSchemaManager($connection))->createSchema();

$eventStore = new DbalEventStore($connection);
$snapshotStore = new DbalSnapshotStore($connection);
$durableStateStore = new DbalDurableStateStore($connection);

// With a custom serializer
use Monadial\Nexus\Serialization\MessageSerializer;

$eventStore = new DbalEventStore($connection, $customSerializer);
$durableStateStore = new DbalDurableStateStore($connection, $customSerializer);

// Pessimistic locking
use Monadial\Nexus\Persistence\Dbal\DbalPessimisticLockProvider;
use Monadial\Nexus\Persistence\Locking\LockingStrategy;

$lockProvider = new DbalPessimisticLockProvider($connection);

$behavior = EventSourcedBehavior::create($persistenceId, $emptyState, $commandHandler, $eventHandler)
->withEventStore($eventStore)
->withLockingStrategy(LockingStrategy::pessimistic($lockProvider))
->toBehavior();