Skip to content

[BUG] WebSocket SessionSendQueue can stall indefinitely and lose configuration updates #7313

Closed

Description

@Aias00

Current Behavior

Admin serializes WebSocket writes through one SessionSendQueue per session. The queue advances only when the callback passed to AsyncRemote.sendText executes.

If the async send never invokes its callback—for example on a half-open connection, stalled ingress/LB path, or a non-reading client—sending remains true forever. Later configuration messages are appended to an unbounded ArrayDeque, but no call restarts sendNext().

There is no configured async-send timeout, queue limit, oldest-message deadline, or watchdog.

When a callback reports failure, or sendText throws, the current message is logged and discarded. The session is not closed and no gateway full resynchronization is requested. Because WebSocket events have no ACK/replay cursor, the gateway can remain stale until restart.

Reproduction

  • Mock RemoteEndpoint.Async#sendText so the first send never invokes its SendHandler.
  • Send two or more updates to the same session.
  • Verify only the first call reaches sendText; subsequent messages remain queued indefinitely.
  • In a second case, return a failed SendResult and verify the failed update is discarded without closing the session or triggering MYSELF.

Expected Behavior

A blocked or failed WebSocket send must be detected within a bounded time and force a recoverable connection state. Configuration updates must not remain silently queued or be dropped without reconciliation.

Scope

  • Configure or implement a bounded per-message send timeout.
  • Bound the per-session queue by count and/or bytes.
  • On timeout or send failure, stop the queue, remove the session from all indexes, close it, and allow the gateway to reconnect and perform MYSELF full synchronization.
  • Preserve message ordering for healthy sessions.
  • Define behavior for queue overflow; silent drop is not acceptable.
  • Add metrics for queue length/bytes, oldest message age, in-flight duration, timeout, failure, overflow, and forced reconnect.
  • Cover races among callback completion, timeout, onClose, and new messages.

Acceptance Criteria

  • A missing send callback cannot stall a session queue indefinitely.
  • Failed sends cannot leave the gateway silently stale.
  • Queue memory use is bounded.
  • Failure/timeout removes the session and its queue from all maps.
  • Reconnect triggers a full synchronization before normal incremental delivery resumes.
  • Ordering is preserved on healthy connections.
  • Unit tests cover no-callback, failed callback, synchronous exception, overflow, close race, and recovery.
  • An integration test reproduces a stalled/broken WebSocket connection and verifies final cache convergence.

Activity

  1. github-actions commented on Sep 26, 2026

    @github-actions
    Contributor

    👋 Hello @Aias00

    A new issue has been opened by @Aias00:

    Please review when you have time. Thank you! 🙏

  2. added a commit that references this issue on Oct 1, 2026
    40e6879
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions