Files
gongxue-base/supabase/migrations/202607120016_content_import_job_leases.sql
2026-07-12 19:26:57 +08:00

98 lines
3.0 KiB
SQL

alter table public.content_import_jobs
add column if not exists lease_token uuid,
add column if not exists lease_expires_at timestamptz,
add column if not exists last_heartbeat_at timestamptz;
-- Jobs left in importing by the pre-lease worker cannot prove ownership. Put
-- them back in the queue so the first lease-aware worker can claim them.
update public.content_import_jobs
set status = 'pending',
locked_at = null,
locked_by = null,
lease_token = null,
lease_expires_at = null,
last_heartbeat_at = null,
next_attempt_at = coalesce(next_attempt_at, now()),
summary = coalesce(summary, '{}'::jsonb) || jsonb_build_object(
'leaseMigrationRecovery', jsonb_build_object(
'requeuedAt', now(),
'reason', 'legacy_importing_job_without_persistent_lease'
)
),
updated_at = now()
where execution_mode = 'async'
and status = 'importing'
and (lease_token is null or lease_expires_at is null);
update public.content_import_jobs
set locked_at = null,
locked_by = null,
lease_token = null,
lease_expires_at = null,
last_heartbeat_at = null,
updated_at = now()
where execution_mode = 'async'
and status <> 'importing'
and (
locked_at is not null
or locked_by is not null
or lease_token is not null
or lease_expires_at is not null
or last_heartbeat_at is not null
);
do $$
begin
if not exists (
select 1
from pg_constraint
where conname = 'content_import_jobs_async_lease_state_check'
and conrelid = 'public.content_import_jobs'::regclass
) then
alter table public.content_import_jobs
add constraint content_import_jobs_async_lease_state_check
check (
execution_mode <> 'async'
or (
status = 'importing'
and locked_at is not null
and locked_by is not null
and lease_token is not null
and lease_expires_at is not null
and last_heartbeat_at is not null
and lease_expires_at > locked_at
)
or (
status <> 'importing'
and locked_at is null
and locked_by is null
and lease_token is null
and lease_expires_at is null
and last_heartbeat_at is null
)
);
end if;
end $$;
create index if not exists idx_content_import_jobs_async_pending_ready
on public.content_import_jobs(next_attempt_at, created_at, id)
where execution_mode = 'async'
and status = 'pending'
and attempt_count < max_attempts;
create index if not exists idx_content_import_jobs_async_expired_lease
on public.content_import_jobs(lease_expires_at, created_at, id)
where execution_mode = 'async'
and status = 'importing'
and attempt_count < max_attempts;
do $$
begin
if to_regrole('tiku_api') is not null then
grant select, insert, update, delete on table public.content_import_jobs to tiku_api;
end if;
if to_regrole('tiku_worker') is not null then
grant select, insert, update, delete on table public.content_import_jobs to tiku_worker;
end if;
end $$;