84 lines
2.5 KiB
PL/PgSQL
84 lines
2.5 KiB
PL/PgSQL
-- Owners can safely retry a round after all worker attempts have failed.
|
|
-- The queue has one durable outbox row per round. A retry records the failed
|
|
-- state in the audit log, then safely re-queues that same row.
|
|
create or replace function public.stage_two_retry_failed_round(
|
|
p_round_id uuid,
|
|
p_owner_id uuid
|
|
) returns uuid language plpgsql security definer set search_path = '' as $$
|
|
declare
|
|
v_round public.rounds%rowtype;
|
|
v_job public.ai_jobs%rowtype;
|
|
begin
|
|
select * into v_round
|
|
from public.rounds
|
|
where id = p_round_id
|
|
for update;
|
|
|
|
if not found then raise exception 'round not found'; end if;
|
|
if v_round.status <> 'failed'::public.round_status then
|
|
raise exception 'round is not failed';
|
|
end if;
|
|
if not exists (
|
|
select 1 from public.campaigns
|
|
where id = v_round.campaign_id
|
|
and owner_id = p_owner_id
|
|
and status = 'active'
|
|
) then
|
|
raise exception 'only the campaign owner can retry a failed round';
|
|
end if;
|
|
if exists (
|
|
select 1 from public.rounds
|
|
where campaign_id = v_round.campaign_id
|
|
and id <> p_round_id
|
|
and status in ('open'::public.round_status, 'queued'::public.round_status, 'resolving'::public.round_status)
|
|
) then
|
|
raise exception 'campaign already has an active round';
|
|
end if;
|
|
|
|
select * into v_job
|
|
from public.ai_jobs
|
|
where job_type = 'resolve-round' and entity_id = p_round_id
|
|
for update;
|
|
if not found or v_job.status <> 'failed' then
|
|
raise exception 'failed round job not found';
|
|
end if;
|
|
|
|
insert into public.audit_entries(
|
|
campaign_id, actor_id, action, entity_type, entity_id, before_state, after_state
|
|
) values (
|
|
v_round.campaign_id,
|
|
p_owner_id,
|
|
'retry_failed_round',
|
|
'round',
|
|
p_round_id,
|
|
jsonb_build_object('roundError', v_round.error, 'jobError', v_job.error, 'attempts', v_job.attempts),
|
|
jsonb_build_object('status', 'queued')
|
|
);
|
|
|
|
update public.ai_jobs
|
|
set status = 'queued',
|
|
attempts = 0,
|
|
claimed_by = null,
|
|
lease_expires_at = null,
|
|
available_at = now(),
|
|
error = null,
|
|
updated_at = now()
|
|
where id = v_job.id;
|
|
|
|
update public.rounds
|
|
set status = 'queued'::public.round_status,
|
|
error = null,
|
|
queued_at = now(),
|
|
resolved_at = null,
|
|
forced_by = p_owner_id
|
|
where id = p_round_id;
|
|
|
|
return v_job.id;
|
|
end;
|
|
$$;
|
|
|
|
revoke all on function public.stage_two_retry_failed_round(uuid, uuid) from public, anon, authenticated;
|
|
grant execute on function public.stage_two_retry_failed_round(uuid, uuid) to service_role;
|
|
|
|
notify pgrst, 'reload schema';
|