fix: resequence workbench trace migration

This commit is contained in:
lyon
2026-06-20 20:33:27 +08:00
parent fb1fe8d94a
commit 482218f2cc
2 changed files with 23 additions and 0 deletions
@@ -294,6 +294,25 @@ CREATE TABLE IF NOT EXISTS workbench_trace_events (
);
CREATE INDEX IF NOT EXISTS idx_workbench_trace_events_trace_seq ON workbench_trace_events(trace_id, source_seq, projected_seq, id);
CREATE INDEX IF NOT EXISTS idx_workbench_trace_events_session_seq ON workbench_trace_events(session_id, source_seq, projected_seq, id);
WITH traces_needing_resequence AS (
SELECT trace_id
FROM workbench_trace_events
WHERE trace_id IS NOT NULL
GROUP BY trace_id
HAVING COUNT(*) <> COUNT(DISTINCT projected_seq)
), ranked_trace_events AS (
SELECT
workbench_trace_events.id,
(ROW_NUMBER() OVER (PARTITION BY workbench_trace_events.trace_id ORDER BY workbench_trace_events.occurred_at, workbench_trace_events.id))::integer AS durable_projection_seq
FROM workbench_trace_events
INNER JOIN traces_needing_resequence
ON traces_needing_resequence.trace_id = workbench_trace_events.trace_id
)
UPDATE workbench_trace_events AS existing_trace_events
SET projected_seq = ranked_trace_events.durable_projection_seq
FROM ranked_trace_events
WHERE existing_trace_events.id = ranked_trace_events.id
AND existing_trace_events.projected_seq IS DISTINCT FROM ranked_trace_events.durable_projection_seq;
CREATE UNIQUE INDEX IF NOT EXISTS idx_workbench_trace_events_trace_source_event ON workbench_trace_events(trace_id, source_event_id) WHERE source_event_id IS NOT NULL;
CREATE UNIQUE INDEX IF NOT EXISTS idx_workbench_trace_events_trace_projected_seq ON workbench_trace_events(trace_id, projected_seq);
+4
View File
@@ -84,6 +84,10 @@ test("initial migration declares Workbench fact backfill sources", async () => {
assert.ok(traceBackfillMatch, "missing workbench_trace_events idempotent backfill");
assert.match(traceBackfillMatch[0], /ROW_NUMBER\(\) OVER \(PARTITION BY trace_id ORDER BY occurred_at, id\)/u);
assert.match(traceBackfillMatch[0], /durable_projection_seq/u);
const traceResequenceMatch = sql.match(/WITH traces_needing_resequence AS \([\s\S]*?CREATE UNIQUE INDEX IF NOT EXISTS idx_workbench_trace_events_trace_projected_seq/u);
assert.ok(traceResequenceMatch, "missing workbench_trace_events projected_seq resequence before unique index");
assert.match(traceResequenceMatch[0], /COUNT\(\*\) <> COUNT\(DISTINCT projected_seq\)/u);
assert.match(traceResequenceMatch[0], /UPDATE workbench_trace_events AS existing_trace_events/u);
});
test("protocol record guards catch schema drift before runtime writes", () => {