Skip to content

Event sourcing configuration

Reference Microsoft.Orleans.EventSourcing from the grain implementation project. Grain interface projects don’t need that package unless they expose Event Sourcing types in their contracts.

Register one or more providers on the silo:

builder.UseOrleans(siloBuilder =>
{
siloBuilder
.AddAzureBlobGrainStorage("eventStore", options =>
{
var connectionString =
builder.Configuration.GetConnectionString("eventStore")
?? throw new InvalidOperationException(
"The eventStore connection string isn't configured.");
options.BlobServiceClient =
new BlobServiceClient(connectionString);
})
.AddStateStorageBasedLogConsistencyProvider("snapshots")
.AddLogStorageBasedLogConsistencyProvider("shortLogs");
});

Available registration methods are:

Each also has an AsDefault form. If a default log-consistency provider and default grain storage provider are registered, provider attributes can be omitted.

State storage and log storage use a standard grain storage provider:

[LogConsistencyProvider(ProviderName = "snapshots")]
[StorageProvider(ProviderName = "eventStore")]
public sealed class AccountGrain
: JournaledGrain<AccountState, AccountEvent>, IAccountGrain
{
}

The provider names must exactly match registrations on every silo capable of activating the grain.

Custom storage doesn’t use IGrainStorage. The grain implements ICustomStorageInterface<T, U> and owns the storage operations:

[LogConsistencyProvider(ProviderName = "custom")]
public sealed class AccountGrain
: JournaledGrain<AccountState, AccountEvent>,
IAccountGrain,
ICustomStorageInterface<AccountState, AccountEvent>
{
public Task<KeyValuePair<int, AccountState>> ReadStateFromStorage() =>
throw new NotImplementedException();
public Task<bool> ApplyUpdatesToStorage(
IReadOnlyList<AccountEvent> updates,
int expectedVersion) =>
throw new NotImplementedException();
public Task ClearStoredState() =>
throw new NotImplementedException();
}

Custom storage owns the write-topology rules needed by a multi-cluster deployment. The primaryCluster registration argument is retained by the provider but doesn’t restrict submissions, configure Orleans multi-cluster networking, replicate storage, or provide failover. Enforce any single-writer or regional-write rule in the application and storage implementation.