fix: restore away status after websocket reconnection
Proposed changes (including videos or screenshots)
Auto-away is lost on every websocket reconnection.
Presence.newConnection() registers every new DDP session as online, and the client kept no memory of activity across the drop — it assumed the reconnected session was online and restarted the idle countdown from zero. An idle user came back online on every reconnect and stayed online for a full idle period; on desktop indefinitely, since the OS idle poller only reports state changes. Any infrastructure that recycles long-lived connections on a timer (HAProxy timeout tunnel, nginx proxy_read_timeout, ALB/Cloudflare idle timeouts, LB failover, restarts) reproduces this workspace-wide on that cadence.
The client now:
- tracks
lastActivityAtacross drops, so disconnected time counts as inactivity; - restates
awayonce the reconnected session is authenticated, instead of assuming online; - schedules the idle timer for the remaining time, not a fresh full period;
- records the idle state at the away entry point, so an idle transition reported by the desktop app while disconnected is no longer dropped;
- only forces away when
enableAutoAwayis enabled.
It also fixes the countdown being restarted by unrelated user-document updates: the effect now depends on user?._id instead of the whole user object, which minted a new reference on every store update.
Steps to test or reproduce
Use two accounts — checking A's own UI means moving the pointer into A's window, which resets the idle countdown, so observe from B instead.
-
In Admin → Settings → Accounts → Default User Preferences, enable Enable Auto Away, set Idle Time Limit to 60s, reload.
-
Open A (your user) in a normal window and B (another user) in incognito, with B viewing A in a DM so A's status dot is visible.
-
In A, undock DevTools into a separate window and stop touching A's window. Once the idle limit passes, B shows A as away.
-
In A's console, trigger a reconnect and leave it alone:
Meteor.disconnect(); setTimeout(() => Meteor.reconnect(), 5000); -
Watch B: A goes offline, then online on reconnect, then back to away within a round trip, with no interaction. Before this PR, A stayed online for a full idle period.
Undocking matters: the client listens for mousemove/mousedown/keydown on the document and focus on the window, so with the console docked, merely moving the pointer across the page to reach it stamps lastActivityAt and legitimately brings A online. Once undocked, stay in the DevTools window.
Issues
Further comments
- The server still writes
onlineinnewConnectionand broadcasts it, so there is a ~1 round-trip window where clients see the user online before theawaylands. - The non-idle branch intentionally does not send
UserPresence:online: the session is already online server-side, so it would add a method call plus a presence broadcast per client on every reconnect, doubling presence work on a mass reconnect for no gain. - Mobile needs no equivalent change — it already re-asserts away on the resume login via
checkBackgroundAndSetAway. - Why not server-side. Preserving the previous status in
newConnectionsounds cheaper, but nothing is left to preserve:connection.onClose→removeConnectionalready recomputed the user toofflinebefore the reconnect arrives. It would need new persisted state, a rule keeping bots and API clients defaulting to online, and the client declaringonlineso nobody gets stuck away — a lot of machinery to close a sub-second window, for something the server cannot observe anyway. Only the client knows whether the user is idle.
https://claude.ai/code/session_01PQu7gFiCHs1nyDtq3Wmufi
Summary by CodeRabbit
Summary by CodeRabbit
- Bug Fixes
- Preserved users’ away status and inactivity progress after websocket reconnections.
- Restored online status when users interact while disconnected.
- Improved presence updates during login, reconnection, and connection changes.
- Ensured desktop and browser activity consistently resets away status.
- Prevented inactivity timers from restarting unnecessarily after reconnecting.
- More accurately restored presence based on the user’s latest activity.