Menu
AkurAI-Build
publicLatest change 7c16b1f17125e5f333737f549579c368e9380877 - Close PR approval races and validate current Git revisions by Ólafur Búi Ólafsson
-- Fix merge_queue_entries uniqueness: the milestone-1 constraint was
-- UNIQUE(repository_id, pull_request_id, status), which blocks a PR from
-- ever being re-enqueued after a first failed attempt, because the second
-- row's status='queued' collides with... no, actually it blocks a second
-- 'failed' row for the same PR once the first attempt fails, since SQLite
-- unique constraints treat repeated (repository_id, pull_request_id,
-- 'failed') tuples as duplicates. Recovery then leaves the PR permanently
-- unable to re-enter a terminal 'failed' state a second time.
--
-- Fix: replace the table-wide UNIQUE with a partial unique index that only
-- applies to the two *active* statuses ('queued', 'running'), so a PR can
-- have at most one active queue entry at a time (this is the invariant
-- that actually matters for serialization), while terminal statuses
-- ('succeeded', 'failed', 'canceled') can repeat freely across attempts.
DROP INDEX IF EXISTS merge_queue_repository_status;
CREATE TABLE merge_queue_entries_new (
id INTEGER PRIMARY KEY,
repository_id INTEGER NOT NULL REFERENCES repositories(id) ON DELETE CASCADE,
pull_request_id INTEGER NOT NULL REFERENCES pull_requests(id) ON DELETE CASCADE,
position INTEGER NOT NULL CHECK (position > 0),
base_sha TEXT NOT NULL CHECK (length(base_sha) IN (40, 64)),
head_sha TEXT NOT NULL CHECK (length(head_sha) IN (40, 64)),
status TEXT NOT NULL DEFAULT 'queued'
CHECK (status IN ('queued', 'running', 'succeeded', 'failed', 'canceled')),
run_id INTEGER REFERENCES runs(id) ON DELETE SET NULL,
error TEXT,
enqueued_by TEXT NOT NULL CHECK (length(enqueued_by) BETWEEN 1 AND 256),
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
started_at INTEGER,
finished_at INTEGER
) STRICT;
INSERT INTO merge_queue_entries_new
SELECT id, repository_id, pull_request_id, position, base_sha, head_sha,
status, run_id, error, enqueued_by, created_at, started_at, finished_at
FROM merge_queue_entries;
DROP TABLE merge_queue_entries;
ALTER TABLE merge_queue_entries_new RENAME TO merge_queue_entries;
CREATE INDEX merge_queue_repository_position ON merge_queue_entries(repository_id, position);
CREATE INDEX merge_queue_repository_status ON merge_queue_entries(repository_id, status, position);
CREATE UNIQUE INDEX merge_queue_one_active_entry_per_pr
ON merge_queue_entries(pull_request_id)
WHERE status IN ('queued', 'running');
PRAGMA user_version = 13;