You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Make managed tenant partition bucketing actually share a partition (#391) (#392)
* fix(partitioning): make managed tenant bucketing actually share a partition (#391)
Both managed-partition strategies advertised multi-tenant "bucketing" -- several small
tenants sharing one physical partition to stay clear of per-table partition ceilings --
but neither could express it end to end. Reproduced against real PostgreSQL and SQL Server.
PostgreSQL (ManagedListPartitions)
AddPartitionToAllTables emitted one single-value ListPartition per value, so two values
sharing a suffix produced two CREATE TABLE IF NOT EXISTS statements against the same
partition table name. The first created it with only its own value and the second was
silently swallowed, so the partition never accepted the second value and its first write
died with 23514 "no partition of relation found for row".
The additive path now groups by SANITIZED suffix (that is what names the physical table)
and carries the bucket's full membership. Since CREATE TABLE IF NOT EXISTS cannot alter an
existing bound, widening an already-present partition is DETACH + re-ATTACH inside ONE
transaction -- a failure between them would orphan the partition and leave every tenant in
the bucket unroutable.
DropPartitionFromAllTablesForValue resolved a value to its suffix and then dropped BY
SUFFIX, deleting every registry row in the bucket and DROPping the shared partition table.
Removing one small tenant therefore silently destroyed its co-tenants' rows. It now narrows
the bucket -- deleting only the departing value's rows, then re-binding to the remaining
members -- and releases the partition only with the last member.
SQL Server (ManagedTenantPartitions)
Bucketing worked inside a single batch (the caller supplied the shared ordinal itself) but
silently did not across calls -- the natural tenant-onboarding shape. The registry persisted
only tenant_id -> ordinal, so a brand-new tenant had no way to discover which ordinal its
bucket already owned and each call allocated a fresh one; the tenants never actually shared.
The registry gains a nullable `bucket` column plus a bucket-aware AddPartitionsToAllTables
overload taking tenant -> bucket. Deliberately a COLUMN rather than a pseudo-tenant row: a
row would keep the ordinal referenced forever, defeating release-on-last-member and
TenantDropBehavior.DeleteData. A bucket is forgotten once its last member is dropped.
Coverage: 5 new PostgreSQL tests (all red on the prior code) and 5 new SQL Server tests.
Full suites green -- Weasel.Postgresql 780/783, Weasel.SqlServer 323/331 (skips pre-existing).
* release: 9.20.0
New API surface on ManagedTenantPartitions (bucket-aware AddPartitionsToAllTables + Buckets),
so a minor bump rather than a patch. Wolverine's GH-3683 adoption depends on this version.
"select pg_get_expr(c.relpartbound, c.oid) from pg_class c join pg_namespace n on n.oid = c.relnamespace where n.nspname = 'managed_lists' and c.relname = :name")
0 commit comments