Skip to content

RpcServer disconnects cannot be observed without competing with cleanup #8461

Description

@schickling-assistant

RpcServer.Protocol.disconnects is exposed as a Queue.Dequeue<number>, but RpcServer.make also consumes that queue internally to interrupt a disconnected client's in-flight handlers. An application that takes from the queue to observe passive disconnects competes with the server and can prevent handler cleanup.

Reproduction

https://github.com/schickling-repros/2026-09-effect-rpc-disconnect-observer

bun install
bun run repro

The repro uses a minimal in-memory protocol and runs a control plus a competing-observer case. It synchronizes on queue takers and handler lifecycle signals directly; no timing sleeps are involved.

Output:

control: both disconnected handlers were interrupted
competing observer: observer stole client 1; only client 2 was interrupted

Expected

There is a non-destructive way to observe passive client disconnects while preserving RpcServer.make's lifecycle handling.

Actual

The event-like API is the same work-sharing queue used by the server. Queue.take(protocol.disconnects) can steal a notification, so server.disconnect(clientId) is not called and that client's handler remains active. Protocol.clientIds is a snapshot and cannot provide equivalent event observation.

An additive callback on RpcServer.make (invoked after the server handles a disconnect) could expose this without changing the Protocol transport shape or queue semantics.

This was reproduced with effect@4.0.0-rc.112, and the same single-consumer flow is present on current main.

Related: #7342 fixed another path where a lost disconnect prevented handler cleanup.

Posted on behalf of @schickling
field value
agent_identity dev3.direct.omp.pdvr6amr
session unknown
agent_persona generalist
agent_supervisor unavailable
agent_tool OMP
agent_tool_version 18.2.11
agent_runtime OMP 18.2.11
agent_model openai-codex/gpt-5.6-sol
worktree 2026-09-effect-rpc-disconnect-observer/main
tooling_profile dotfiles@b0f94e3-dirty

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