Process Realtime INSERT events into BLoC state
epic-in-app-notification-centre-services-task-007 — Handle incoming Realtime INSERT events within the NotificationBloc. Deserialise the raw Supabase payload into a NotificationModel, pass it through the Role-Aware Notification Filter to determine visibility for the current role, and if visible prepend it to the current notification list in state. Increment the unread count atomically. Avoid duplicate insertion by checking notification ID against existing state list before inserting.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 4 - 323 tasks
Can start after Tier 3 completes
Implementation Notes
Add a `Set
Apply `transformer: sequential()` on this event handler to prevent concurrent INSERT processing from producing race conditions on the state list.
Testing Requirements
Unit tests (flutter_test + bloc_test) for NotificationRealtimeInsert handler: (1) valid payload for current role is prepended and unread count increments, (2) valid payload filtered out by role filter produces no state change, (3) duplicate payload (same ID already in state) produces no state change, (4) malformed JSON payload emits NotificationRealtimeParseError without crashing, (5) INSERT event while in NotificationError state is handled without throwing, (6) org_id mismatch in payload is silently rejected. Use bloc_test `seed` to establish a pre-loaded state before each test. Verify state immutability: assert that the original list reference in state is not the same object as the new list after insert.
A Realtime INSERT event arriving during an in-flight mark-all-read operation can cause the new notification to be incorrectly marked read in the optimistic state update, silently hiding it from the user.
Mitigation & Contingency
Mitigation: Process Realtime events sequentially in the BLoC event queue using bloc_concurrency's sequential transformer. The mark-all-read event should only affect notifications whose IDs were fetched before the operation started.
Contingency: Add a reconciliation step after mark-all-read that re-fetches the unread count from the repository and corrects the BLoC state if it diverges from the server value.
A coordinator assigned to many peer mentors may trigger a query returning hundreds or thousands of notifications. Without pagination and query optimisation, the initial load will be slow and memory-heavy.
Mitigation & Contingency
Mitigation: Enforce server-side pagination (50 items per page) in the Role-Aware Filter's query predicates. Add a composite index on (org_id, user_id, created_at DESC) and profile query plans before shipping.
Contingency: If query performance is insufficient for large coordinator scopes, introduce a server-side RPC function that pre-aggregates visible notification IDs and returns only the first page, deferring full scope resolution to lazy-load.
If the read-state optimistic update rolls back frequently due to intermittent connectivity, users will observe notifications toggling between read and unread, creating confusion and distrust of the feature.
Mitigation & Contingency
Mitigation: Queue failed mutations in a local retry store and re-attempt on next connectivity event using a connectivity-aware retry service. Show a non-intrusive banner if offline rather than applying optimistic updates.
Contingency: Disable optimistic updates for mark-as-read in low-connectivity scenarios detected by the connectivity provider, instead showing a loading indicator until server confirmation.