83 lines
2.4 KiB
PL/PgSQL
83 lines
2.4 KiB
PL/PgSQL
BEGIN;
|
|
|
|
ALTER TABLE public.push_dispatch_attempts
|
|
ADD COLUMN actor_kind text NOT NULL DEFAULT 'user'
|
|
CHECK (actor_kind IN ('user', 'system'));
|
|
|
|
ALTER TABLE public.push_dispatch_attempts
|
|
ALTER COLUMN caller_id DROP NOT NULL,
|
|
ADD CONSTRAINT push_dispatch_attempt_actor_check CHECK (
|
|
(actor_kind = 'user' AND caller_id IS NOT NULL)
|
|
OR (actor_kind = 'system' AND caller_id IS NULL)
|
|
);
|
|
|
|
CREATE INDEX idx_push_dispatch_attempts_system_event
|
|
ON public.push_dispatch_attempts(event_type, resource_id, created_at DESC)
|
|
WHERE actor_kind = 'system';
|
|
|
|
CREATE OR REPLACE FUNCTION public.reserve_system_push_dispatch(
|
|
push_event_type text,
|
|
push_resource_id uuid
|
|
)
|
|
RETURNS jsonb
|
|
LANGUAGE plpgsql
|
|
SECURITY DEFINER
|
|
SET search_path = ''
|
|
AS $$
|
|
DECLARE
|
|
normalized_event_type text := lower(btrim(push_event_type));
|
|
existing_attempt_id uuid;
|
|
created_attempt_id uuid;
|
|
BEGIN
|
|
IF auth.role() <> 'service_role' THEN
|
|
RAISE EXCEPTION 'service_role_required' USING ERRCODE = '42501';
|
|
END IF;
|
|
IF push_resource_id IS NULL OR normalized_event_type NOT IN (
|
|
'transcription.completed',
|
|
'team.invite.created',
|
|
'billing.status.changed'
|
|
) THEN
|
|
RAISE EXCEPTION 'invalid_push_event' USING ERRCODE = '22023';
|
|
END IF;
|
|
|
|
PERFORM pg_advisory_xact_lock(
|
|
hashtextextended(normalized_event_type || ':' || push_resource_id::text, 73049)
|
|
);
|
|
SELECT attempt.id INTO existing_attempt_id
|
|
FROM public.push_dispatch_attempts AS attempt
|
|
WHERE attempt.actor_kind = 'system'
|
|
AND attempt.event_type = normalized_event_type
|
|
AND attempt.resource_id = push_resource_id
|
|
AND attempt.created_at > now() - interval '30 seconds'
|
|
ORDER BY attempt.created_at DESC
|
|
LIMIT 1;
|
|
|
|
IF existing_attempt_id IS NOT NULL THEN
|
|
RETURN jsonb_build_object(
|
|
'reserved', false,
|
|
'duplicate', true,
|
|
'attempt_id', existing_attempt_id
|
|
);
|
|
END IF;
|
|
|
|
INSERT INTO public.push_dispatch_attempts (
|
|
caller_id, actor_kind, event_type, resource_id
|
|
) VALUES (
|
|
NULL, 'system', normalized_event_type, push_resource_id
|
|
)
|
|
RETURNING id INTO created_attempt_id;
|
|
|
|
RETURN jsonb_build_object(
|
|
'reserved', true,
|
|
'duplicate', false,
|
|
'attempt_id', created_attempt_id
|
|
);
|
|
END;
|
|
$$;
|
|
|
|
REVOKE ALL ON FUNCTION public.reserve_system_push_dispatch(text, uuid)
|
|
FROM PUBLIC, anon, authenticated;
|
|
GRANT EXECUTE ON FUNCTION public.reserve_system_push_dispatch(text, uuid)
|
|
TO service_role;
|
|
|
|
COMMIT;
|