Skip to content

Reconcile queued Discord member subscriptions after gateway session resume #42

Closed

Description

@vbmithr

A reconnect can discard an unsent Discord member subscription while retaining local state that says the subscription was already sent. A successful session resume does not reconcile that state, potentially leaving the member pane pending even though the gateway is connected.

Relevant paths in crates/chatd/src/adapters/discord/:

  • members.rs::subscribe assigns Watched.sent when enqueueing the desired subscription, before the gateway actually writes it.
  • gateway.rs::run clears the outbox when a new gateway connection is established.
  • On RESUMED, ready.rs::resumed restores cached presence but does not requeue/reconcile the current member subscription.
  • An unchanged Watch is ignored, and an identical desired subscription is deduplicated against Watched.sent.

A concrete failure sequence is: queue a viewport subscription, lose the connection before sending it, clear the queue on reconnect, then successfully resume. Discord may retain the earlier viewport while chatd considers the discarded newer viewport subscribed. Repeated cache reads do not repair this mismatch.

Observed symptom during member-pane investigation: occasional initial loading skeletons lasting seconds, with immediate Members cache replies containing pending: true, no groups and no rows. Laptop suspend/network loss was also observed. The causal connection between that live symptom and this code path has not yet been reproduced or confirmed. Merely resuming a session with an already-delivered subscription is not evidence of failure.

Expected behavior: after resume, reconcile the latest desired viewport with what was actually delivered. Preserve or regenerate discarded subscription state without treating queued frames as acknowledged subscriptions. Handle obsolete roster data consistently when the viewport changed while offline.

Suggested regression coverage: interrupt the connection with a subscription still queued, resume the existing session, and verify that the latest viewport is delivered and its member cache can fill. Include viewport changes while disconnected.

Related: #40 introduces viewport-driven member caching and coalesced subscription snapshots. This issue tracks reconnect recovery separately; #40 explicitly does not claim to resolve intermittent initial loading.

Activity

  1. vbmithr commented on Oct 18, 2026

    @vbmithr
    ContributorAuthor

    The standalone daemon audit now reproduces the queue-loss failure, rather than only identifying a possible code path.

    Tested main 44ad327 plus #40 (6fa84d4), using the real release chatd binary with temporary synthetic account data and local fake Discord HTTP/WebSocket servers. No GUI or real account participated.

    Reproduction:

    1. Subscribe to channel A and wait for its subscription to reach the fake Gateway.
    2. Drop the Gateway TCP connection and wait for the account to become Offline.
    3. While offline, send Watch selecting channel B and its first 50 members.
    4. Allow the existing session to resume and wait for Connected.
    5. Inspect subscriptions delivered to the Gateway.

    Observed: no subscription for B arrives within 500 ms after resume. The explicit regression member_viewport_changed_while_offline_is_delivered_after_resume fails with “resumed gateway never received the viewport selected while offline” in 2.74 seconds overall. The 500 ms deadline does not measure eventual recovery. The test currently exists locally and is explicitly ignored in the ordinary suite pending a fix.

    This confirms the controlled failure sequence described here. Whether it caused a particular earlier live blank-pane incident remains unconfirmed. The existing dropped-socket integration test passes because it checks session resume, messages, presence and heartbeats without changing the member viewport while disconnected.

  2. added a commit that references this issue on Oct 20, 2026
    c7fa3cb
  3. added a commit that references this issue on Oct 20, 2026
    e3c325c
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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions