The writer loop in src/runtime/server.rs:310 waits inside a loop until emitted - last_ack < window. If the window is full and the client disconnects before sending another session.ack, teardown at src/runtime/server.rs:569 drops out_tx, notifies once, and then awaits the writer. The writer wakes, recomputes the same full window, and parks on writer_ack_notify.notified().await again, so run_connection can hang forever instead of returning. A configured with_ack_window(0) makes the loop unsatisfiable immediately for the first countable event.
Fix prompt: Give the writer an explicit shutdown signal or include channel-closed state in the wait condition so it can exit while parked on flow control. Reject or normalize an ack window of zero in RuntimeBuilder::with_ack_window, and consider moving the flow-control gate before persistence and subscription publication so unsent envelopes are not exposed as delivered. Add tests where a client fills a one-message ack window and then drops the transport, and where with_ack_window(0) does not deadlock.
The writer loop in
src/runtime/server.rs:310waits inside aloopuntilemitted - last_ack < window. If the window is full and the client disconnects before sending anothersession.ack, teardown atsrc/runtime/server.rs:569dropsout_tx, notifies once, and then awaits the writer. The writer wakes, recomputes the same full window, and parks onwriter_ack_notify.notified().awaitagain, sorun_connectioncan hang forever instead of returning. A configuredwith_ack_window(0)makes the loop unsatisfiable immediately for the first countable event.Fix prompt: Give the writer an explicit shutdown signal or include channel-closed state in the wait condition so it can exit while parked on flow control. Reject or normalize an ack window of zero in
RuntimeBuilder::with_ack_window, and consider moving the flow-control gate before persistence and subscription publication so unsent envelopes are not exposed as delivered. Add tests where a client fills a one-message ack window and then drops the transport, and wherewith_ack_window(0)does not deadlock.