Documentation / Foundations

Stores and serialization

IStore is the base event-stream contract. It appends a collection of events at an expected stream version and reads all, a range, the last event, or one event. A store implementation determines durability, concurrency behavior, and its deployment requirements.

On this page

Store choices

Store Intended use
InMemoryStore Local examples and tests; state disappears with the process.
FileSystemStore Local filesystem experiments; review filesystem semantics before relying on it.
Troolio.SqlServer SQL Server adapters with explicit schema, transaction, and recovery setup.
Troolio.KurrentDB KurrentDB append and named-stream integration with separate route and recovery contracts.

The two bundled Core stores do not grant the selected atomic transaction capability. That route requires IAtomicEventTransactionStore and, when fenced, IRouteFencedAtomicEventTransactionStore with the required capability flags. Atomic commit explains the full contract.

Serializer options

Core includes JsonEventSerializer, MessagePackEventSerializer, and MessagePackLz4EventSerializer behind IEventSerializer. Choose one deliberately, test round trips of your domain event types, and retain backward readers for any stored format you have already written. Changing serializers without migration can make historical replay fail.

Orleans serialization attributes on message records serve actor transport. They do not by themselves define the bytes your chosen event store writes. The store's serializer and the application event schema must agree.

Operational contract

The store must enforce expected versions and return an append count consistent with what it committed. For the selected route, the store must atomically commit participant events, required projection handoffs, ancillary writes, and completion evidence. A IStore implementation alone does not promise that stronger property.

Example: Append and serialize events

The application supplies a store and serializer. Use the stream’s actual current version; 0 below is only appropriate for a new stream.

public static byte[] SerializeEvent(
    Troolio.Core.Serialization.IEventSerializer serializer, Metadata headers) =>
    serializer.Serialize(new Incremented(headers));
public static async Task<ulong> Append(IStore store, Metadata headers) =>
    await store.Append("CounterActor-42", 0,
        new IEvent[] { new Incremented(headers) });