ALTER TABLE job_audit ADD COLUMN request_hash TEXT; ALTER TABLE job_audit ADD COLUMN request_sequence BIGINT GENERATED ALWAYS AS IDENTITY; ALTER TABLE job_audit ADD COLUMN request_json JSONB; ALTER TABLE job_audit ADD COLUMN owner_id TEXT; ALTER TABLE job_audit ADD COLUMN lease_until TIMESTAMPTZ; ALTER TABLE job_audit ADD COLUMN attempt INTEGER NOT NULL DEFAULT 0; ALTER TABLE job_audit ADD COLUMN fencing_token BIGINT NOT NULL DEFAULT 0; ALTER TABLE job_audit ADD COLUMN available_at TIMESTAMPTZ NOT NULL DEFAULT now(); ALTER TABLE job_audit ADD COLUMN cancel_requested BOOLEAN NOT NULL DEFAULT false; INSERT INTO tenant (id, name, slug) VALUES ('00000000-0000-0000-0000-000000000000', 'EvoBGP system jobs', 'evobgp-system-jobs') ON CONFLICT (id) DO NOTHING; CREATE INDEX idx_job_audit_claim ON job_audit (available_at, created_at) WHERE status = 'queued'; CREATE INDEX idx_job_audit_expired_lease ON job_audit (lease_until) WHERE status = 'running'; -- Give pre-upgrade workers their old 15-minute grace; later claims can recover them. UPDATE job_audit SET owner_id = 'legacy-unfenced', lease_until = now() + interval '15 minutes', attempt = 1 WHERE status = 'running' AND lease_until IS NULL;