-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Implement DDP session resumption for graceful reconnects #14051
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: release-3.4.1
Are you sure you want to change the base?
Implement DDP session resumption for graceful reconnects #14051
Conversation
This feature allows Meteor clients to resume their DDP connections after temporary disconnections without re-establishing full session state. Key changes: - Server tracks sent message count per session (sentCount) - Client tracks received message count (receivedCount) - On reconnect, client sends receivedCount with session ID - Server validates counts match to allow session resumption - New disconnect message allows graceful disconnects - Grace period (default 15s) keeps session alive after disconnect - Message queue (max 100) buffers messages during disconnect Server options: - Meteor.server.options.disconnectGracePeriod (default: 15000ms) - Meteor.server.options.maxMessageQueueLength (default: 100) This significantly reduces server CPU spikes when clients reconnect (e.g., after Google Cloud Run timeouts) by avoiding full session recreation and data re-fetch. Based on PR meteor#13378. Rebased onto current devel branch with refactored ddp-client handlers. Co-authored-by: Jan Dvorak <AsciiDoctor@outlook.com> Co-authored-by: Valentin Slatineanu <valentin.slatineanu@gmail.com> Co-authored-by: zodern <zodern@icloud.com>
The test was failing when the browser page was reloaded during test runs because the subscription ready callback could fire before the added messages arrived. This can happen when a previous test run was interrupted and the server is still processing the old session. The fix adds a polling mechanism to wait for data to arrive before asserting, with a 5-second timeout.
✅ Deploy Preview for v3-meteor-api-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for v3-migration-docs canceled.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements DDP session resumption, allowing clients to automatically reconnect to their previous session after temporary network disconnects without triggering onConnection callbacks or losing their connection ID. The implementation uses message count tracking to verify data consistency and supports graceful vs. ungraceful disconnect handling with a configurable grace period (default 15 seconds).
Key Changes:
- Server tracks sent message count and queues messages during disconnects for later replay
- Client tracks received message count and sends it during reconnect attempts
- Sessions are preserved during a grace period for ungraceful disconnects, with automatic cleanup for graceful disconnects or timeouts
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| v3-docs/docs/api/meteor.md | Documents the new session resumption feature and configuration options (disconnectGracePeriod, maxMessageQueueLength) |
| packages/ddp-server/livedata_server.js | Implements server-side session resumption logic including message counting, session queueing, grace period handling, and disconnect type detection |
| packages/ddp-server/livedata_server_tests.js | Adds comprehensive test suite (7 tests) covering grace period behavior, graceful vs ungraceful disconnects, onConnection hook behavior, and count mismatch scenarios |
| packages/ddp-server/livedata_server_async_tests.js | Adds defensive polling to handle race conditions from lingering sessions in test environment |
| packages/ddp-client/common/livedata_connection.js | Initializes receivedCount tracking and sends disconnect message before closing connection |
| packages/ddp-client/common/connection_stream_handlers.js | Tracks received message count (excluding ping/pong) and includes it in reconnect messages |
| packages/ddp-client/common/message_processors.js | Handles receivedCount reset for new sessions vs preservation for resumed sessions |
| packages/ddp-client/test/livedata_connection_tests.js | Adds client-side tests (5 tests) for receivedCount tracking, session resume vs new session behavior, and disconnect message sending; updates existing tests to include receivedCount in connect messages |
| packages/ddp-client/test/stub_stream.js | Adds disconnect() stub method for testing |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Fix wording: "insure" → "to help prevent" in docs and JSDoc - Extract heartbeat cleanup to _stopHeartbeat() helper method - Simplify disconnect handling: remove redundant condition check - Update documentation: add Reconnection section, use "Meteor 3.5+" instead of time-sensitive language, update PR link to meteor#14051 - Update comment at line 1480 to reflect session resume/create behavior - Replace delete statements with = undefined for V8 JIT optimization - Remove unused variable clientConn in test - Add comment clarifying _permanent flag purpose in close()
Summary
This PR implements DDP session resumption, allowing clients to automatically resume their previous session after a temporary network disconnect without re-triggering
onConnectioncallbacks or losing their connection ID.This PR supersedes PR #13378 with a completely rewritten implementation that includes comprehensive tests to give everyone confidence in its correctness.
Key Features
Meteor.server.options.disconnectGracePeriod(default: 15000ms)Meteor.server.options.maxMessageQueueLength(default: 100) prevents memory leaks during disconnectsImplementation Details
Client-side changes (ddp-client):
receivedCountof messages from server (excluding ping/pong)receivedCountin reconnect messagessession_resumedvs new session responsesdisconnectmessage before intentional disconnectsServer-side changes (ddp-server):
sentCountof messages sent to each clientComprehensive Test Coverage
Server-side tests (7 new tests):
DDP resumption: unexpected disconnect preserves session- verifies grace period worksDDP resumption: graceful disconnect removes session immediately- verifies client disconnect msg worksDDP resumption: server-initiated close removes session immediately- verifies server kicks workDDP resumption: onConnection not called on resume- verifies hook behaviorDDP resumption: server close prevents resumption- verifies server kicks are not resumableDDP resumption: graceful disconnect prevents resumption- verifies client disconnects are not resumableDDP resumption: count mismatch creates new session- verifies mismatched counts create new sessionClient-side tests (5 new tests):
receivedCount tracking- verifies count increments and ignores ping/pongreceivedCount sent on reconnect- verifies reconnect includes countreceivedCount reset on new session- verifies reset on new sessionreceivedCount preserved on session resume- verifies count continues on resumedisconnect sends disconnect message- verifies disconnect() sends msgDocumentation
Updated v3-docs to document the new feature and configuration options.
Test plan
Closes #13378