Part of #5118 (compliance wave growth), epic #5110.
Live aggregation — folding a stream on read with no persisted document — runs entirely through shared surfaces: AggregateStreamAsync<T> and AggregateStreamToLastKnownAsync<T> on IQueryEventStore, both with Guid and string overloads and both with version/timestamp/fromVersion bounds.
The one seam fact worth recording up front: EventStoreComplianceFixture.SupportsLiveAggregationRegistration already exists (false in stores that build live aggregators automatically and reject explicit registration), and ComplianceStoreConfig.LiveAggregation<T>() is already wired. So the plumbing for this suite is in place.
What each store tests today
| Marten |
Polecat |
Aggregation/when_doing_live_aggregations.cs |
Projections/live_aggregation_tests.cs |
Aggregation/aggregate_stream_returns_null_if_the_aggregate_is_null_at_that_point_in_stream.cs |
Events/aggregate_stream_to_last_known_tests.cs |
Aggregation/live_aggregation_without_an_aggregate_identifier.cs |
Projections/aggregateto_linq_operator_tests.cs |
Aggregation/explicit_code_for_aggregation_logic.cs, Projections/using_explicit_code_for_live_aggregation.cs |
|
Aggregation/when_finding_the_last_good_aggregation.cs |
|
Scope
New LiveAggregationCompliance suite:
AggregateStreamAsync<T> over a full stream, a version-bounded slice, and a timestamp-bounded slice
- Null result when the stream does not exist, and when the fold legitimately produces null (a "deleted" aggregate)
AggregateStreamToLastKnownAsync skipping a trailing event the aggregate cannot apply, where AggregateStreamAsync would fail — this is the whole point of the method and both stores test it separately today
- Aggregation with no identity member on the aggregate type
- Explicit
Apply/Create conventions vs source-generated EvolveAsync producing the same result (the EvolveAsync half is already covered by SelfAggregatingEvolveCompliance — assert the equivalence, don't re-test evolve)
- Guid and string stream identity
Acceptance
- Suite enrolled in both stores;
SupportsLiveAggregationRegistration used only where a store genuinely rejects explicit registration
- Originals retired in both repos
Part of #5118 (compliance wave growth), epic #5110.
Live aggregation — folding a stream on read with no persisted document — runs entirely through shared surfaces:
AggregateStreamAsync<T>andAggregateStreamToLastKnownAsync<T>onIQueryEventStore, both with Guid and string overloads and both with version/timestamp/fromVersion bounds.The one seam fact worth recording up front:
EventStoreComplianceFixture.SupportsLiveAggregationRegistrationalready exists (false in stores that build live aggregators automatically and reject explicit registration), andComplianceStoreConfig.LiveAggregation<T>()is already wired. So the plumbing for this suite is in place.What each store tests today
Aggregation/when_doing_live_aggregations.csProjections/live_aggregation_tests.csAggregation/aggregate_stream_returns_null_if_the_aggregate_is_null_at_that_point_in_stream.csEvents/aggregate_stream_to_last_known_tests.csAggregation/live_aggregation_without_an_aggregate_identifier.csProjections/aggregateto_linq_operator_tests.csAggregation/explicit_code_for_aggregation_logic.cs,Projections/using_explicit_code_for_live_aggregation.csAggregation/when_finding_the_last_good_aggregation.csScope
New
LiveAggregationCompliancesuite:AggregateStreamAsync<T>over a full stream, a version-bounded slice, and a timestamp-bounded sliceAggregateStreamToLastKnownAsyncskipping a trailing event the aggregate cannot apply, whereAggregateStreamAsyncwould fail — this is the whole point of the method and both stores test it separately todayApply/Createconventions vs source-generatedEvolveAsyncproducing the same result (theEvolveAsynchalf is already covered bySelfAggregatingEvolveCompliance— assert the equivalence, don't re-test evolve)Acceptance
SupportsLiveAggregationRegistrationused only where a store genuinely rejects explicit registration