MySQL configuration
Transaction behavior
MySqlEventStorage::storeEvents() runs the complete call in one transaction.
It can write events for multiple aggregates and enroll outbox entries in the
same transaction. If the PDO connection is already inside a transaction, the
adapter joins it and leaves the final commit or rollback to the transaction
owner.
The optional batchSize controls how many event inserts are grouped into each
internal chunk; it does not weaken the transaction boundary of the public
storeEvents() call:
$storage = new MySqlEventStorage($pdo, batchSize: 500);
Use InnoDB for the shipped tables. MyISAM does not provide the transaction semantics required by the Core storage contract.
Event table and ordering
The events table has an auto-increment id for global order and a unique
(aggregate_id, version) key for stream concurrency. Aggregate reads order by
version; global reads and cursor-based pages order by id.
The payload and metadata columns use MySQL JSON. The default entry factory stores the event payload as JSON text in the persistence record before the adapter binds it to the JSON column.
Snapshots and process managers
MySqlSnapshotStorage keeps one current row per aggregate in snapshots.
MySqlSnapshotHistoryStorage stores one row per aggregate/version in
snapshot_history. Process-manager state is stored in
process_manager_states, with an index on timeout for due-timeout polling.
Transactional outbox
Pass a MySqlOutboxStorage to MySqlEventStorage when events should be
delivered through an outbox:
use DomainFlow\EventSourcing\Facade\EventSourcingFacade;
use DomainFlow\EventSourcing\Outbox\OutboxRelay;
use DomainFlow\EventSourcingMySQL\Outbox\MySqlOutboxStorage;
use DomainFlow\EventSourcingMySQL\Storage\MySqlEventStorage;
$outbox = new MySqlOutboxStorage($pdo);
$storage = new MySqlEventStorage($pdo, outbox: $outbox);
// Do not also pass an inline dispatcher to this facade.
$facade = new EventSourcingFacade($storage);
$relay = new OutboxRelay($outbox, $dispatcher);
The outbox row is inserted in the event transaction. outbox contains pending
entries and outbox_dead contains entries abandoned after too many attempts.
Use the Core OutboxRelay for delivery; delivery is at least once.
Custom database fields
An event can expose getDatabaseFields(): array to add adapter fields beside
the standard event columns. MySQL validates the field names before placing them
in the generated INSERT; names must be valid SQL identifiers beginning with a
letter or underscore. The corresponding columns must already exist in the
events table.