mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-16 06:39:01 +02:00
fix(migrations): rebuild legacy label index CONCURRENTLY on rollback (MUL-4479) (#5357)
The 162_resource_labels down migration recreated issue_label_workspace_name_lower_idx with a plain CREATE UNIQUE INDEX, which takes a blocking lock on the existing issue_label table during a rollback to v0.3.43 and violates the online-migration rule that every CREATE INDEX must be CONCURRENTLY. CREATE INDEX CONCURRENTLY cannot run in a transaction or a multi-command migration, so the rebuild is split out of 162.down: - 171.down now rebuilds the legacy index as a single CREATE UNIQUE INDEX CONCURRENTLY (the natural inverse of 171.up, which drops it). - 174 (new, no-op up) deletes the agent/skill label rows in its down so they are gone before 171.down rebuilds the workspace-wide unique index. Down migrations apply high->low, so 174.down -> 171.down -> 162.down runs in the required order. - 162.down keeps only the transaction-safe structural teardown. Validated on an isolated Postgres: full up->down->up chain with a colliding issue/agent label pair; the concurrent rebuild succeeds after the rows are deleted, restores the valid pre-162 unique index, and a negative control (rebuild before the delete) fails on the exact collision. Co-authored-by: J <j@multica.ai> Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -1,16 +1,21 @@
|
||||
-- Revert issue_label to its pre-162 issue-only shape and drop the resource
|
||||
-- label junction tables. The two rollback steps that each need their own
|
||||
-- transaction live in earlier down migrations, because a single migration
|
||||
-- file cannot mix DML/DDL with CREATE INDEX CONCURRENTLY:
|
||||
-- * 174.down removes the agent/skill rows, and
|
||||
-- * 171.down rebuilds the legacy workspace-wide unique name index
|
||||
-- CONCURRENTLY.
|
||||
-- Both run before this file (down migrations apply high->low), so the
|
||||
-- non-issue rows are already gone by the time we drop resource_type here.
|
||||
DROP TABLE IF EXISTS skill_to_label;
|
||||
DROP TABLE IF EXISTS agent_to_label;
|
||||
|
||||
-- Defensive: a short-lived pre-release deploy may have applied the original
|
||||
-- 162 that created these indexes inline. On the normal down chain 167/168
|
||||
-- already dropped them CONCURRENTLY, so these are no-ops.
|
||||
DROP INDEX IF EXISTS issue_label_workspace_type_idx;
|
||||
DROP INDEX IF EXISTS issue_label_workspace_type_name_lower_idx;
|
||||
|
||||
-- The pre-162 schema can only represent issue labels. Resource-scoped rows
|
||||
-- must be removed before restoring its workspace-wide unique name index.
|
||||
DELETE FROM issue_label WHERE resource_type <> 'issue';
|
||||
|
||||
ALTER TABLE issue_label
|
||||
DROP COLUMN IF EXISTS description,
|
||||
DROP COLUMN IF EXISTS resource_type;
|
||||
|
||||
CREATE UNIQUE INDEX issue_label_workspace_name_lower_idx
|
||||
ON issue_label (workspace_id, LOWER(name));
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
-- Migration 162 restores the legacy index after it removes non-issue labels.
|
||||
-- Recreating it here could fail while those rows still exist during rollback.
|
||||
SELECT 1;
|
||||
-- Inverse of 171.up, which drops the pre-162 workspace-wide unique name
|
||||
-- index. Recreated as a single CREATE INDEX CONCURRENTLY statement so the
|
||||
-- rollback stays online-safe (it cannot be combined with other statements
|
||||
-- or run inside a transaction block).
|
||||
--
|
||||
-- The agent/skill rows that would violate this workspace-wide uniqueness are
|
||||
-- removed earlier in the down chain by 174.down (down migrations apply
|
||||
-- high->low), so only issue rows remain when this index is rebuilt.
|
||||
CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS issue_label_workspace_name_lower_idx
|
||||
ON issue_label (workspace_id, LOWER(name));
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
-- Remove the resource-scoped (agent/skill) labels before 171.down rebuilds
|
||||
-- the pre-162 workspace-wide unique name index, which cannot coexist with
|
||||
-- rows that share (workspace_id, LOWER(name)) across resource types. This
|
||||
-- runs first in the down chain (high->low), and resource_type still exists
|
||||
-- here because 162.down (which drops it) runs later.
|
||||
DELETE FROM issue_label WHERE resource_type <> 'issue';
|
||||
@@ -0,0 +1,8 @@
|
||||
-- Forward no-op. This migration exists only to sequence a rollback step:
|
||||
-- its down removes the agent/skill rows from issue_label before 171.down
|
||||
-- rebuilds the workspace-wide unique name index. Because down migrations
|
||||
-- apply high->low, keeping this delete in the highest-numbered resource
|
||||
-- label migration guarantees the non-issue rows are gone before both
|
||||
-- 171.down (index rebuild) and 162.down (drops resource_type). There is
|
||||
-- nothing to do on the way up.
|
||||
SELECT 1;
|
||||
Reference in New Issue
Block a user