Skip to content

events.db is opened and written by two Sembast handles (foreground + background isolate) #676

Description

@grunch

Problem

events.db is opened by two independent Sembast handles that can be alive at the same time:

  • lib/core/app_bootstrap.dart:43 — foreground handle, created at bootstrap and never closed.
  • lib/background/background.dart:289 — background service isolate handle.

The background isolate writes through its handle:

  • background.dart:180persistChatEventFromBackground -> eventStore.putItem(id, record)
  • called from lib/features/notifications/services/background_notification_service.dart:273 (dispute chat) and :451 (peer chat)

Sembast IO keeps the store contents in memory per handle and does not re-read the file after open. Consequences:

  1. Stale reads. Any foreground read through eventStorageProviderdispute_chat_notifier.dart:222/313/447, chat_room_notifier.dart:167, session_notifier.dart:63, mostro_service.dart:109 — will not see records written by the background isolate until the app restarts and reopens the database.
  2. Dual-writer risk. Two writers appending to and compacting the same Sembast file is not a supported configuration and can lose records.

Today the user-visible impact is limited: the background service does not advance the chat cursors, so on resume the relay subscription refetches the missed events and the chat still fills in (see #675). The persisted records act as a dedup/marker layer, so the failure mode is a silent loss of that layer rather than missing messages — but it is fragile and will bite as soon as anything relies on the on-disk records being authoritative.

Suggested direction

Stop writing events.db from the background isolate. Options, roughly in order of preference:

  1. Have the background isolate send accepted-event records to the foreground over the flutter_background_service channel and let the foreground (single owner of the handle) persist them. Requires a durable queue for the app-killed case.
  2. Keep an isolate-local write-ahead file in the background isolate and drain it into events.db from the foreground on resume.
  3. Move to a storage engine that supports multi-isolate access.

Reopening the foreground database on resume is not a sufficient fix: eventDatabaseProvider is an overrideWithValue created at bootstrap, so every consumer would need rebuilding, and the dual-writer corruption risk would remain.

Context

Raised by an automated review on #675 (comment).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions