Move push notification to client instead of db trigger

This commit is contained in:
2026-02-28 16:19:08 +08:00
parent dab43a7f30
commit 0a8e388757
8 changed files with 698 additions and 226 deletions
@@ -0,0 +1,24 @@
-- 2026-02-28: cleanup duplicates and enforce device_id NOT NULL
-- 1) Deduplicate rows keeping the newest by created_at
WITH ranked AS (
SELECT id, ROW_NUMBER() OVER (PARTITION BY token, user_id ORDER BY created_at DESC) rn
FROM public.fcm_tokens
)
DELETE FROM public.fcm_tokens
WHERE id IN (SELECT id FROM ranked WHERE rn > 1);
-- 2) Ensure device_id is populated for any legacy rows
UPDATE public.fcm_tokens
SET device_id = gen_random_uuid()::text
WHERE device_id IS NULL;
-- 3) Enforce NOT NULL on device_id
ALTER TABLE public.fcm_tokens
ALTER COLUMN device_id SET NOT NULL;
-- 4) Ensure unique index on (user_id, device_id) exists
CREATE UNIQUE INDEX IF NOT EXISTS fcm_tokens_user_device_idx
ON public.fcm_tokens(user_id, device_id);
-- 5) (Optional) keep a normal index on user_id for queries
CREATE INDEX IF NOT EXISTS fcm_tokens_user_idx ON public.fcm_tokens(user_id);
@@ -0,0 +1,20 @@
-- Create a table to record which notifications have been pushed by the edge function
CREATE TABLE IF NOT EXISTS public.notification_pushes (
notification_id uuid PRIMARY KEY,
pushed_at timestamptz NOT NULL DEFAULT now()
);
-- Helper function: try to mark a notification as pushed. Returns true if the
-- insert succeeded (i.e. this notification was not previously pushed), false
-- if it already existed.
CREATE OR REPLACE FUNCTION public.try_mark_notification_pushed(p_notification_id uuid)
RETURNS boolean LANGUAGE plpgsql AS $$
BEGIN
INSERT INTO public.notification_pushes(notification_id) VALUES (p_notification_id)
ON CONFLICT DO NOTHING;
RETURN FOUND; -- true if insert happened, false if ON CONFLICT prevented insert
END;
$$;
-- index for quick lookup by pushed_at if needed
CREATE INDEX IF NOT EXISTS idx_notification_pushes_pushed_at ON public.notification_pushes(pushed_at);
@@ -0,0 +1,16 @@
-- Migration: Drop notifications trigger that posts to the send_fcm edge function
-- Reason: moving push invocation to client-side; remove server trigger to avoid duplicate sends
BEGIN;
-- Remove the trigger that calls the edge function on insert into public.notifications
DROP TRIGGER IF EXISTS notifications_send_fcm_trigger ON public.notifications;
-- Remove the trigger function as well (if present)
DROP FUNCTION IF EXISTS notifications_send_fcm_trigger() CASCADE;
COMMIT;
-- NOTE: After deploying this migration, the application will rely on the
-- client-side push path. Ensure client builds are released and rollout is
-- coordinated before applying this migration in production to avoid missing
-- pushes for any clients that still expect server-side delivery.