Fix #4706 — managed partitioned tables destructively rebuilt on sharded redeploy#4709
Merged
Merged
Conversation
…ed redeploy Re-applying the schema over existing data to a Marten-managed ByList tenant-partitioned document table destructively rebuilt it (create _temp / copy / drop / recreate) and failed with 23514 "no partition of relation found for row". Root cause: on redeploy a fresh DocumentStore builds a fresh store-wide ManagedListPartitions that loads only the first shard's partition set, then ApplyAllConfiguredChangesToDatabaseAsync diffs EVERY shard against that one set (Parallel.ForEachAsync over databases). Mismatched shards make ListPartitioning.CreateDelta return PartitionDelta.Rebuild → destructive rebuild. Fix: DocumentTable sets IgnorePartitionsInMigration on Marten-managed LIST partitioned tables (PartitionManager != null). The generic schema diff then short-circuits to PartitionDelta.None for those tables — the per-tenant partitions are reconciled out-of-band by AddMartenManagedTenantsAsync / AddTenantToShardAsync (the additive path), which still creates them because Weasel 9.1.2's additivelyMigrateTablesForNewPartitions clears the flag locally. Concurrency-immune: the diff no longer depends on the shared partition manager's state. Bumps Weasel.Postgresql to 9.1.2. Tests: - Bug_4706_sharded_partitioned_doc_rebuild (sharded): eager per-DB apply + per-tenant data, then store-wide parallel re-apply must be idempotent. RED (23514) before the fix, green after. - Bug_4706_partitioned_table_idempotent_migration (single-DB control): managed ByList re-apply is idempotent (passes regardless — proves sharding/concurrency is load-bearing for the bug). Note: event tables (mt_events/mt_streams) are intentionally NOT flagged here — the flag breaks their lazy sharded partition creation; their redeploy hardening (the #4682 migration) needs a deeper per-database partition-state design. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 11, 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.
Fixes #4706.
Problem
Re-applying the schema over existing data to a Marten-managed
ByListtenant-partitioned document table destructively rebuilds it (create <t>_temp as select *→ drop → recreate →insert … select) and fails with23514: no partition of relation found for row— the rebuilt parent has no child partitions. A fresh database is fine; a single-database managed-ByListstore is idempotent. The failure is specific to sharded multi-tenancy on redeploy.Root cause
On redeploy a fresh
DocumentStorebuilds a fresh store-wideManagedListPartitionsthat loads only the first shard'smt_tenant_partitionsset.IMartenStorage.ApplyAllConfiguredChangesToDatabaseAsyncthen diffs every shard against that single set (Parallel.ForEachAsyncover databases). For any shard whose real partitions differ from that first set,ListPartitioning.CreateDeltasees the live per-tenant partitions as "unexpected" and returnsPartitionDelta.Rebuild→ destructive rebuild → 23514.Fix
DocumentTablesetsIgnorePartitionsInMigration = trueon Marten-managed LIST-partitioned tables (Partitioning is ListPartitioning { PartitionManager: not null }). The generic schema diff then short-circuits toPartitionDelta.Nonefor those tables, so it never rebuilds them. The per-tenant partitions are reconciled out-of-band byAddMartenManagedTenantsAsync/AddTenantToShardAsync(the additive path), which still creates them because Weasel 9.1.2'sadditivelyMigrateTablesForNewPartitionsclears the flag locally for that explicit path. This is concurrency-immune: the diff no longer depends on the shared partition manager's state.Bumps
Weasel.Postgresql/Weasel.EntityFrameworkCoreto 9.1.2 (JasperFx/weasel#303).Tests
Bug_4706_sharded_partitioned_doc_rebuild(sharded) — eager per-DB apply + per-tenant data, then a store-wide parallel re-apply must be idempotent. RED (23514) before the fix, green after.Bug_4706_partitioned_table_idempotent_migration(single-DB control) — managedByListre-apply is idempotent (passes regardless; proves sharding/concurrency is load-bearing for the bug).Full
TenantPartitionedEventsTests182/182 andCoreTestspartitioning 33/33 green against the published Weasel 9.1.2.Out of scope
Event tables (
mt_events/mt_streams) are intentionally not flagged here — the flag breaks their lazy sharded partition creation, and their redeploy hardening (the #4682 conjoined→partitioned migration) needs a deeper per-database partition-state design.🤖 Generated with Claude Code