fix(notifications): upsert device token on (user_id, endpoint)#2
Draft
SIRXIII wants to merge 1 commit into
Draft
fix(notifications): upsert device token on (user_id, endpoint)#2SIRXIII wants to merge 1 commit into
SIRXIII wants to merge 1 commit into
Conversation
FCM device-token registration failed on every launch with "DeviceTokenSaveException: ... no unique or exclusion constraint matching the ON CONFLICT specification" (42P10), silently breaking push notifications on device. The repository upserted into push_subscriptions with onConflict: 'user_id,device_token', but the live table (shared with the FitConnect web app) has no such unique constraint. Its only matching unique key is push_subscriptions_user_id_endpoint_key on (user_id, endpoint). Since endpoint = 'fcm:' + device_token is a 1:1 function of the token, conflicting on (user_id, endpoint) yields identical re-registration idempotency without touching the shared schema the webapp relies on. Add a regression test asserting saveToken upserts with onConflict: 'user_id,endpoint'. https://claude.ai/code/session_012unpTSSNZTagJj9VwuqU45
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
FCM device-token registration failed on every app launch (Phase 23 simulator verification) with:
This silently broke push notifications on device — including the Phase 21 "trainer account approved" push.
Root cause:
SupabaseDeviceTokenRepository.saveTokenupserted intopush_subscriptionswithonConflict: 'user_id,device_token', but the live table (Supabase projectqecwxvvlpvrnrqyrdxrj, shared with the FitConnect web app) has no such unique constraint. Its only matching unique key ispush_subscriptions_user_id_endpoint_keyon (user_id, endpoint).Fix: Target the constraint that actually exists —
onConflict: 'user_id,endpoint'. The DTO already writesendpoint = 'fcm:' + device_token, a 1:1 function of the token, so conflicting on(user_id, endpoint)gives identical re-registration idempotency. No schema change, so the shared(user_id, endpoint)constraint the webapp relies on is untouched.Why a client fix, not a migration
A migration adding a
(user_id, device_token)unique constraint would modify a shared production database (hard to reverse, needs a duplicate-row guard, complicated by nullabledevice_tokenfor web-push rows). The client-only fix is minimal, fully reversible, and risk-free for FitConnect.Verification
Confirmed directly against the live DB (no rows written — a deliberately fake
user_idis blocked by the FK):(user_id, device_token)(old)42P10: there is no unique or exclusion constraint…— reproduces the exact reported error(user_id, endpoint)(new)23503FK violation from the fake user — proves the upsert is validChanges
supabase_device_token_repository.dart:onConflict: 'user_id,device_token'→'user_id,endpoint'(+ explanatory comment).device_token_dto.dart: corrected the stale conflict-handling doc comment.supabase_device_token_repository_test.dart: regression test assertingsaveTokenupserts withonConflict: 'user_id,endpoint'.Follow-up (out of scope, flagged)
The live table has a CHECK constraint
platform IN ('web','ios'), butSupabaseDeviceTokenRepositorysends'android'for non-iOS devices. On Android this upsert would fail the check constraint — a separate latent bug to address before Android launch (either widen the shared CHECK or map the platform value).Test plan
flutter analyzecleanflutter test test/features/notifications/data/repositories/supabase_device_token_repository_test.dartpassesflutter runon iOS simulator against the live backend — confirm noDeviceTokenSaveExceptionin logs and a row appears inpush_subscriptionshttps://claude.ai/code/session_012unpTSSNZTagJj9VwuqU45
Generated by Claude Code