The soft shutdown chained ->then() on Handler::onClose(), which returns
void. The error became a silently dropped promise rejection, loop->stop()
never ran, and the server kept accepting and closing every new socket
without connection_established until a hard restart. Clients queued their
sends forever in that window.
- Close connections directly (Ratchet runs onClose once per stream), stop
the loop after a 1s grace, on a listing error, or at a 5s deadline.
- Websocket\ChannelManager::unsubscribeFromAllChannels returns early for a
connection declined before it got an app, like LocalChannelManager. That
was the "Attempt to read property id on null" flood in the log.
- Tests: SoftShutdownTest drives the shutdown on a fresh loop, StartServerTest
fails on any error logged during a soft shutdown, ClosedBeforeOpenTest.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The dev hot reload forgot the `events` instance, so the container rebuilt an
empty dispatcher and every listener the service providers registered was
gone for that message. Events fired from WS controllers reached nobody (a
shop's "order paid" mails and invoice silently never happened in dev).
Model observers kept working, which hid it: Eloquent holds its own
reference to the old dispatcher.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The per-message fork child's Redis/cache/session isolation (#1445) was inline
in forkWithSocketPair() with no test — verified only by watching prod. Extract
it into Handler::resetInheritedConnectionsInChild() (behavior-preserving) and
add ForkChildConnectionResetTest: asserts it disconnects every host-bearing
connection, skips the client/options pseudo-entries, and never throws when the
redis manager is unresolvable. A future refactor that drops a connection now
fails CI instead of re-opening the predis desync flood.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Introduced `helpers-and-testing.md` to document global helpers and WebsocketService class usage.
- Created `HandlerLifecycleTest.php` to test the full WebSocket handler lifecycle, including connection management, channel subscriptions, and message routing.
- Added `WebsocketServiceTest.php` to validate state tracking methods in WebsocketService, covering user authentication, channel tracking, and broadcast functionality.