Skip to content

MessageReceiptReporter polls message_receipt every second for the whole connected session, even when idle #6694

Description

@spvince

Describe the bug

MessageReceiptReporter polls the local receipts table on a fixed 1-second timer for the whole
lifetime of a connected user, whatever the app is doing. The query runs even when nothing has
been enqueued since the previous pass, so an idle session with no message traffic still issues
86 400 SQLite reads per day of connected time.

In the published artifact, MessageReceiptReporter.start() launches, on the UserScope:

while (isActive) {
messageReceiptRepository.selectMessageReceipts(MAX_BATCH_SIZE) // 100
if (receipts.isNotEmpty()) api.markDelivered(receipts).execute()
delay(REPORT_INTERVAL_IN_MS) // 1000
}

start() is called from ChatClient.initializeClientWithUser, so the loop spans the entire
connected session rather than the message screen, and ChatClientConfig exposes no way to
change the interval or turn the reporter off. Only the markDelivered call is conditional; the
SELECT is not.

The SQL reaching the database is
SELECT * FROM message_receipt ORDER BY createdAt ASC LIMIT ?.

This surfaced for us through Sentry's db_query performance detectors, which filed the same
query as an issue under unrelated transactions, including screens with no chat on them. We
verified it is nominal SDK behaviour and not something our code triggers: nothing in our app
reads or writes message_receipt, we build one ChatClient per process and connect the user
once per session.

SDK version

  • 7.11.0 (identical in 7.7.0; the two constants and the call site are unchanged between them)

To Reproduce
Steps to reproduce the behavior:

  1. Build a ChatClient with ChatClientConfig(offlineEnabled = true).
  2. Connect a user with connectUser.
  3. Leave the app on any screen, chat or not, and send no message.
  4. Watch the database queries, with Room query logging, the Android Studio profiler, or a
    Sentry performance trace. A SELECT * FROM message_receipt ORDER BY createdAt ASC LIMIT ?
    appears every second for as long as the user stays connected.

Expected behavior

The drain should be driven by the receipts being enqueued rather than by a fixed timer, or at
least back off while the table keeps coming back empty. Three options, in the order we would
prefer them:

  1. Have MessageReceiptManager signal the reporter when it enqueues a receipt, and let the
    loop wait on that signal instead of polling.
  2. Apply a backoff when a pass finds nothing, up to a ceiling of a few tens of seconds, and
    reset it as soon as a receipt is enqueued.
  3. Failing either, expose the interval, and the ability to disable the reporter, in
    ChatClientConfig, next to offlineEnabled and userPresence.

Device:

  • Vendor and model: not device-specific, observed across the production fleet
  • Android version: not version-specific, observed across the production fleet

Screenshots
Not applicable. The relevant evidence is the two constants and the call site quoted above.

Note
With offlineEnabled = false the repository is the no-op one, so no SQL reaches a database,
but the loop itself still runs on the same timer.

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions