Repository navigation
Pin subscription rewind under per-tenant partitioning end to end - #5719
Merged
jeremydmiller merged 2 commits intoOct 23, 2026
Merged
Conversation
JasperFx 2.91.0 (JasperFx#1025) rewinds a subscription per tenant under UseTenantPartitionedEvents, through RewindSubscriptionProgressAsync with each tenant shard's own identity, which Marten accepts since JasperFx#5700. The daemon logic is pinned in JasperFx against a substituted store, and rewind_subscription_per_tenant_pin (JasperFx#5713) pins a per-tenant rewind of a projection to the beginning. Nothing in Marten pinned the rest against a live store. Three facts, with a raw ISubscription and two tenants at heights 5 and 3: - Rewinding every tenant to the beginning restarts each tenant's own agent, never a store-global one, and each replays only its own tenant's events. - Rewinding one tenant to sequence floor 2 replays only that tenant's events above it, deletes only that tenant's dead letters at or above it, and leaves the other tenant's agent instance running with its progression and dead letters untouched. - Rewinding every tenant to a sequence number is refused, and changes no agent, no progression row and no dead letter. All three fail on 8065f44, the master commit before JasperFx#5700 merged (JasperFx 2.90.1), and pass on master. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A subscription sees a page in ProcessEventsAsync, but the page's progression row is only committed with the batch afterwards. Asserting progress the moment the events were seen raced that commit, most visibly right after a rewind, where the row still holds the floor. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 24, 2026
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.
Why
#1025 (JasperFx 2.91.0) rewinds a subscription per tenant under
UseTenantPartitionedEvents. It callsRewindSubscriptionProgressAsyncwith each tenant shard's own identity, which Marten accepts since #5700. #1025's tests run the daemon against a substituted store, and its body planned Marten end-to-end tests for the bump. #5713 did the bump and turnedrewind_subscription_per_tenant_pininto a test of the new behaviour (1ee3615). It pins three things: a per-tenant rewind of a projection to the beginning, that the sibling tenant's progression row is untouched, and that the tenant-less rewind refusessequenceFloor: 1. This PR adds the rest of the end-to-end coverage, against a live store, with a rawISubscription.RewindProbe:Alltenantless_RewindSubscriptionAsync_does_NOT_throw_under_partitioning). JasperFx covers it against a substitute.RewindSubscriptionProgressAsynccalled directly (#5700)RewindSubscriptionAsync(name, tenantId, …)RunningTest
New file:
TenantPartitionedEventsTests/Daemon/rewind_subscription_under_partitioning.cs. It usesPartitionedStoreContext, a recording subscription and two tenants at heights 5 and 3:rewinding_every_tenant_to_the_beginning_replays_each_tenant_through_its_own_agentrewinding_one_tenant_moves_only_that_tenantrewinding_every_tenant_to_a_sequence_number_is_refused_and_changes_nothingNo production code changes.
Red and green (net10.0, PostgreSQL 17)
Red on
8065f4467, master's commit before #5700 merged (JasperFx 2.90.1): 3 of 3 fail.On today's master, with #5700's source change reverted locally, the first two fail with
Unknown subscription name 'RewindProbe:All:t_…'. With only #5700'sTenantIdpredicate removed from the dead-letter delete,rewinding_one_tenant_moves_only_that_tenantfails withdeadLetterSequencesAsync(beta) should be [2L, 3L] but was [].Green on master
7045d09bb: 3 of 3, and 10 of 10 consecutive runs.TenantPartitionedEventsTests.Daemon: 41 of 41.Searched open and closed issues and PRs for "rewind subscription tenant", "RewindSubscriptionAsync partitioned" and "rewind dead letters tenant". Only #5700, #5713, #4856, #4617 and #5294 come up, and none adds these tests.
🤖 Generated with Claude Code