Skip to content

#4679 — composite catch-up guard + unskip fixture (root cause fixed in JasperFx.Events 2.9.0)#4704

Merged
jeremydmiller merged 1 commit into
masterfrom
feature/4679-composite-fix-and-close
Jun 9, 2026
Merged

#4679 — composite catch-up guard + unskip fixture (root cause fixed in JasperFx.Events 2.9.0)#4704
jeremydmiller merged 1 commit into
masterfrom
feature/4679-composite-fix-and-close

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

Closes #4679.

Root cause

The reporter's instinct — that composite projections were the trigger — was exactly right. Composite projection member stages built their shard names as:

var shardName = new ShardName(projection.Name, ShardName.All, projection.Version); // store-global — tenant dropped

Under catchUpPerTenantAsync (per-tenant event partitioning), each tenant iteration rebuilt the same store-global member progression row, so the second tenant's InsertProjectionProgress (SequenceFloor 0) violated pk_mt_event_progression23505 on the bare :All identity. That matches the report exactly: every global :All shard, failing once the loop hits a second tenant.

Fix (already shipped upstream)

jasperfx#419 changed composite ProjectionStage to compose member shard names with the parent's tenant id:

var shardName = ShardName.Compose(projection.Name, tenantId: parent.TenantId, version: projection.Version);

(its fix comment names marten#4679 as the root cause). This shipped in JasperFx.Events 2.9.0 and is already referenced by Marten — now 2.9.1. So #4679 is resolved for anyone on Marten 9.7.0 / JasperFx.Events ≥ 2.9.0; the report was on 2.8.2.

This PR

  • Sharded/Bug_4679_sharded_catch_up_23505 — adds a multi-stage CompositeProjectionFor catch-up guard (3 tenants on one shard) asserting that both the composite's own shard (…Composite:All:tenant) and every member stage (…:All:tenant) write tenant-scoped progression rows. This exercises the exact path Revisit Event Type Registration #419 corrected; it would have failed pre-2.9.0.
  • Regressions/Bug_4679_catch_up_per_tenant_23505unskipped (the fix is in the referenced JasperFx.Events). This single-DB SingleStream repro never triggered the 23505 on its own — the real trigger was composite projections — but it stays as a per-tenant catch-up advance + no-23505 guard.

All three Bug_4679 tests pass against JasperFx.Events 2.9.1.

🤖 Generated with Claude Code

…ents 2.9.0; add composite guard + unskip fixture

Root cause (the reporter's composite-projection lead was exactly right): composite projection
MEMBER stages built their shard names as `new ShardName(projection.Name, ShardName.All, version)`
— store-global, tenant dropped. Under catchUpPerTenantAsync each tenant iteration rebuilt the SAME
store-global member progression row, so the second tenant's InsertProjectionProgress collided →
23505 duplicate pk_mt_event_progression on the bare :All name.

Fixed upstream by #419 (composite ProjectionStage now uses
`ShardName.Compose(projection.Name, tenantId: parent.TenantId, version: ...)`), shipped in
JasperFx.Events 2.9.0 and already referenced by Marten (now 2.9.1). Its fix comment names
marten#4679 as the root cause.

- Sharded/Bug_4679_sharded_catch_up_23505: add a multi-stage CompositeProjectionFor catch-up
  guard (3 tenants on one shard) asserting both the composite's own shard AND every member stage
  write tenant-scoped progression rows — the exact path #419 corrected.
- Regressions/Bug_4679_catch_up_per_tenant_23505: unskip (fix is in the referenced JasperFx.Events).
  This single-DB SingleStream repro never triggered the 23505 on its own; kept as a per-tenant
  catch-up advance + no-23505 guard.

All three Bug_4679 tests green against JasperFx.Events 2.9.1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Regression in #4665 fix: catchUpPerTenantAsync throws 23505 duplicate pk_mt_event_progression for global (:All) shards under UseTenantPartitionedEvents

1 participant