Skip to content

Getting state

Event sequence state provides information about how far a sequence has progressed. The most common state value is the tail sequence number, which represents the latest event appended to the sequence. Use the IEventSequence APIs, such as GetTailSequenceNumber and related state calls, to capture the current position.

Use sequence state for scenarios such as:

  • Tracking progress for consumers and observers
  • Capturing a point in time for read model time travel
  • Avoiding duplicate processing when resuming work

For point-in-time reads of read models, capture the sequence position from the event sequence state and use it alongside the read model APIs described in the read models guides.

Related reading:

using Cratis.Chronicle.Events;
using Cratis.Chronicle.EventSequences;
public class GettingStateCheckpointStore(IEventLog eventLog)
{
public async Task<EventSequenceNumber> CaptureTail()
{
// Persists the current tail so processing can resume later.
return await eventLog.GetTailSequenceNumber();
}
}

Kotlin and Java don’t currently expose a way to read the tail sequence number at all — their public event sequence APIs only support appending and checking for existence.

Capture the tail for a specific event source and event types

Section titled “Capture the tail for a specific event source and event types”
using Cratis.Chronicle.Events;
using Cratis.Chronicle.EventSequences;
[EventType]
public record GettingStateInventoryAdjusted(string Sku, int Delta);
[EventType]
public record GettingStateInventoryReserved(string Sku, int Quantity);
public class GettingStateInventoryCheckpoint(IEventLog eventLog)
{
public async Task<EventSequenceNumber> CaptureFor(EventSourceId inventoryId)
{
// Scopes the tail to a specific stream of inventory events.
var eventTypes = new[]
{
typeof(GettingStateInventoryAdjusted).GetEventType(),
typeof(GettingStateInventoryReserved).GetEventType()
};
return await eventLog.GetTailSequenceNumber(
eventSourceId: inventoryId,
filterEventTypes: eventTypes
);
}
}

This scoped form (filtering by event source and event types) is currently C#-only. Elixir and TypeScript can capture the overall tail (see above), but neither exposes a way to scope it to specific event types.

using Cratis.Chronicle.Events;
using Cratis.Chronicle.EventSequences;
public class GettingStateObserverProgress(IEventSequence eventSequence)
{
public async Task<EventSequenceNumber> GetRelevantTail(Type observerType)
{
// Uses the observer's event type filters to compute the relevant tail.
return await eventSequence.GetTailSequenceNumberForObserver(observerType);
}
}

Computing the relevant tail for a specific observer is currently a C#-only capability.