Per-tenant-partitioned-events Phase 1: ReadAggregate, append return shapes, WriteAggregate (#3021)#3022
Merged
Merged
Conversation
…hapes, WriteAggregate (#3021) Extends the foundational single-store partitioned-events slice (#3020) with the remaining single-store aggregate-handler scenarios, each scoped by tenant against a Conjoined + Quick + UseTenantPartitionedEvents store (string identity), reusing TenantTally / PartitionedTenancyHost: - [ReadAggregate] reads the routed tenant's partition; Required=false returns null for a tenant with no such stream. - Every append return shape lands only in the routed tenant's partition: single event, IEnumerable<object>, Events, IAsyncEnumerable<object>. - [WriteAggregate] (optimistic) appends to the routed tenant and stays isolated from other tenants. Findings (folded into the #3021 checklist): - MartenOps.StartStream has no tenant overload (only Store/Insert/Update/Delete do) — StartStream uses the ambient session tenant. The issue's StartStream(id, tenantId, events) does not exist. - [WriteAggregate] Required=true -> 404 is an HTTP-endpoint concept; a message handler does not throw for a missing required aggregate. The Required/404 wrong-tenant-isolation case therefore belongs in the deferred HTTP cluster. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Closed
17 tasks
This was referenced Jun 8, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 1 of #3021 — extends the foundational single-store partitioned-events slice (#3020) with the remaining single-store aggregate-handler scenarios. Test-only (no shippable code change; Marten 9.5.2 already on main).
Each is scoped by tenant against a
Conjoined + Quick + UseTenantPartitionedEventsstore (string identity), reusingTenantTally/PartitionedTenancyHost:[ReadAggregate]reads the routed tenant's partition;Required=falsereturns null for a tenant with no such stream.IEnumerable<object>,Events,IAsyncEnumerable<object>— each lands only in the routed tenant's partition (and is invisible to other tenants).[WriteAggregate](optimistic) appends to the routed tenant and stays isolated.6 new tests; full
AggregateHandlerWorkflowfolder green (77, was 71 — clean +6, no discovery collisions).Findings (folded into the #3021 checklist)
MartenOps.StartStreamhas no tenant overload (onlyStore/Insert/Update/Deletedo) —StartStreamuses the ambient session tenant. The issue'sStartStream(id, tenantId, events)does not exist.[WriteAggregate]Required=true → 404is an HTTP-endpoint concept; a message handler does not throw for a missing required aggregate. The Required/404 wrong-tenant-isolation case therefore belongs in the deferred HTTP cluster.Still deferred (tracked on #3021)
Exclusive concurrency, optimistic version /
AlwaysEnforceConsistency, HTTP[Aggregate]/[WriteAggregate]/[ReadAggregate]+ tenancy detection, natural-key, cascading-event tenant inheritance, event-as-message, ancillary stores; and all of Phase 2 (multi-node distribution) + Phase 3 (sharded DBs).🤖 Generated with Claude Code