d3ro-voice/server/supabase/migrations/20260821000019_push_claim_nonretryable_busy.sql
2026-08-29 18:33:45 +09:00

57 lines
1.6 KiB
PL/PgSQL

BEGIN;
-- PostgREST versions backed by hasql-transaction automatically retry SQLSTATE
-- 40001. A contended try-lock would therefore busy-loop until the lock holder
-- exited instead of reaching Edge as an immediate conflict. 55P03 expresses
-- the same lock-not-available condition without transaction auto-retry.
CREATE OR REPLACE FUNCTION public.enforce_system_push_claim_rate()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = ''
AS $$
BEGIN
IF NEW.actor_kind <> 'system'
OR NEW.status <> 'processing'
OR NEW.dispatch_lease_token IS NULL THEN
RETURN NEW;
END IF;
IF TG_OP = 'UPDATE'
AND OLD.dispatch_lease_token IS NOT DISTINCT FROM NEW.dispatch_lease_token THEN
RETURN NEW;
END IF;
IF NOT pg_try_advisory_xact_lock(
hashtextextended('system-push-global', 73050)
) THEN
RAISE EXCEPTION 'push_claim_busy' USING ERRCODE = '55P03';
END IF;
DELETE FROM public.push_dispatch_claim_events
WHERE claimed_at < now() - interval '2 days';
IF (
SELECT count(*)
FROM public.push_dispatch_claim_events
WHERE claimed_at > now() - interval '1 minute'
) >= 500 OR (
SELECT count(*)
FROM public.push_dispatch_claim_events
WHERE claimed_at > now() - interval '24 hours'
) >= 10000 THEN
RAISE EXCEPTION 'push_rate_limited' USING ERRCODE = '54000';
END IF;
INSERT INTO public.push_dispatch_claim_events (
attempt_id, dispatch_lease_token
) VALUES (
NEW.id, NEW.dispatch_lease_token
);
RETURN NEW;
END;
$$;
REVOKE ALL ON FUNCTION public.enforce_system_push_claim_rate()
FROM PUBLIC, anon, authenticated;
COMMIT;