Release v15.33.0
Summary
Adds pagination support to read models with skip/take semantics and introduces observable instance watching backed by Arc's change stream capabilities. Materialized read model operations (pagination and observation) are separated into a dedicated IMaterializedReadModels interface exposed via the Materialized property on IReadModels, with shared Release logic for PII decryption via injectable interface pattern. Both skip and take parameters are optional with sensible defaults (skip: 0, take: 50).
Added
InstanceCountToSkipandInstanceCountconcepts for type-safe pagination parameters with implicit conversion operatorsIMaterializedReadModelsinterface with optionalskipandtakeparameters onGetInstances<TReadModel>()andObserveInstances<TReadModel>()methods (defaults: skip=0, take=50)IMaterializedReadModelsgRPC service contract with correspondingObserveInstancesRequestandObserveInstancesResponsetypesIReadModels.Materializedproperty returningIMaterializedReadModelsfor accessing materialized read model operationsIReadModelsComplianceinterface for PII decryption operations on read model instancesReadModelsComplianceimplementation ofIReadModelsComplianceto centralize PII decryption logicIEventComplianceinterface for PII decryption operations on event contentEventComplianceimplementation ofIEventComplianceto centralize PII decryption logicISink.ObserveInstances(ReadModelContainerName? occurrence, int skip, int take)for sink-level observation- Client and Kernel implementations of
MaterializedReadModelsservice with automatic Release() calls on all returned instances - Comprehensive documentation for materialized read models pagination and observation at
Documentation/read-models/materialized-pagination.md - Specs for optional parameter behavior on
GetInstancesandObserveInstances
Changed
- Moved paginated
GetInstancesand observableWatchInstancesmethods fromIReadModelstoIMaterializedReadModels skipandtakeparameters are now optional with defaults (skip: 0, take: 50) onIMaterializedReadModelsinterface methods- MongoDB Sink now supports observable instances via Arc's
.Observe()with change stream monitoring - SQL Sink now supports observable instances via Arc's EF
.Observe()with proper DbContext scope lifetime management - InMemorySink and NullSink updated with observation support for testing scenarios
- Both
ReadModelsandMaterializedReadModelsservices now use injectedIReadModelsCompliancefor PII decryption - Converted
ReadModelsCompliancefrom static helper to injectable service following theIEventCompliancepattern - Renamed
IEventComplianceHelper→IEventComplianceandEventComplianceHelper→EventCompliancefor consistency with read models compliance naming
Fixed
Removed
Security
Deprecated
Client layer: Converts skip/take to page-based pagination for underlying gRPC API. ObserveInstances uses polling (Observable.Interval) - consider replacing with SignalR/gRPC streaming for production workloads.
Sink layer: All implementations leverage Arc's .Observe() extensions. SQL Sink uses custom ObservableInstancesDisposable to ensure DbContext scope lives for subscription duration.
Usage:
// Paginated retrieval with explicit skip/take - implicit conversion from int
var instances = await readModels.Materialized.GetInstances<MyModel>(
skip: 10,
take: 20);
// Using defaults (skip: 0, take: 50)
var instances = await readModels.Materialized.GetInstances<MyModel>();
// Observable watch with explicit skip/take
var subscription = readModels.Materialized.ObserveInstances<MyModel>(
skip: 0,
take: 50)
.Subscribe(instances => { /* handle changes */ });
// Observable watch with defaults
var subscription = readModels.Materialized.ObserveInstances<MyModel>()
.Subscribe(instances => { /* handle changes */ });