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 a log-consistency provider
Section titled “Register a log-consistency provider”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:
- AddStateStorageBasedLogConsistencyProvider
- AddLogStorageBasedLogConsistencyProvider
- AddCustomStorageBasedLogConsistencyProvider
Each also has an AsDefault form. If a default log-consistency provider and default grain storage provider are registered, provider attributes can be omitted.
Select providers on a grain
Section titled “Select providers on a grain”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();}Multi-cluster responsibility
Section titled “Multi-cluster responsibility”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.
