persistSessionUpdate method
Persist a learning_sessions update (e.g. completed_at,
reflection_text) through the outbox + Supabase. Uses the current
_sessionId — caller must ensure a session exists. The replay path
in SyncWorker applies updates in queued order, which is naturally
last-write-wins within a single session because every update for
the same sessionId is consumed in created_at order.
Returns silently on Supabase failure (durable in the outbox; will
retry on next online tick) so end-of-session UX flows (closing the
chat screen, opening the reflection sheet) don't get blocked by
connectivity. If the session id is missing entirely, the call is a
no-op (matches the pre-outbox behavior where chat_screen guarded
with if (sessionId != null)).
Implementation
Future<void> persistSessionUpdate(Map<String, dynamic> updates) async {
final sessionId = _sessionId ?? _endedSessionId;
if (sessionId == null) return;
final supabase = ref.read(supabaseDatasourceProvider);
final outboxed = ref.read(outboxedWritesProvider);
await outboxed.persistUpdate(
table: 'learning_sessions',
localId: sessionId,
payload: {'id': sessionId, ...updates},
supabaseCall: () => supabase.updateSession(sessionId, updates),
);
}