-
Notifications
You must be signed in to change notification settings - Fork 356
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
feat(internal-plugin-mercury): add mercuryTimeOffset #4035
base: next
Are you sure you want to change the base?
Conversation
Warning There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure. 🔧 eslint
warning [email protected]: This version is no longer supported. Please see https://eslint.org/version-support for other options. (For a CapTP with native promises, see @endo/eventual-send and @endo/captp) WalkthroughThis pull request introduces enhancements to the Mercury plugin's time tracking capabilities. The changes focus on adding a Changes
Sequence DiagramsequenceDiagram
participant Client
participant Socket
participant Mercury
Client->>Socket: Send WebSocket Message
Socket->>Socket: Extract wsWriteTimestamp
Socket->>Mercury: Emit Message with Timestamp
Mercury->>Mercury: Calculate mercuryTimeOffset
Mercury-->>Client: Update Time Synchronization
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Finishing Touches
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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.
Actionable comments posted: 0
🧹 Nitpick comments (3)
packages/@webex/internal-plugin-mercury/src/mercury.js (1)
538-543
: Consider adding time zone handling and documentationWhile the implementation is correct, consider:
- Adding JSDoc to document the method's purpose and parameters
- Adding validation for extreme time differences that might indicate issues
- Considering time zone implications in the offset calculation
+/** + * Updates the Mercury time offset based on the websocket message timestamp + * @param {Object} event - The websocket event containing the write timestamp + * @private + */ _setTimeOffset(event) { const {wsWriteTimestamp} = event; - if (typeof wsWriteTimestamp === 'number' && wsWriteTimestamp > 0) { + if (typeof wsWriteTimestamp === 'number' && wsWriteTimestamp > 0) { + const offset = Date.now() - wsWriteTimestamp; + // Validate that the offset is within reasonable bounds (e.g., ±24 hours) + if (Math.abs(offset) > 24 * 60 * 60 * 1000) { + this.logger.warn(`${this.namespace}: Unusually large time offset detected: ${offset}ms`); + } + this.mercuryTimeOffset = offset; - this.mercuryTimeOffset = Date.now() - wsWriteTimestamp; } }packages/@webex/internal-plugin-mercury/test/unit/spec/socket.js (1)
Line range hint
753-803
: Add test coverage for edge casesWhile the basic functionality is well tested, consider adding test cases for:
- Invalid wsWriteTimestamp values (null, negative, non-numeric)
- Extreme time differences
- Time synchronization behavior over multiple pong messages
Example test cases to add:
it('handles invalid wsWriteTimestamp values', () => { const invalidTimestamps = [null, -1, 'invalid', undefined]; invalidTimestamps.forEach(timestamp => { mockWebSocket.emit('message', { data: JSON.stringify({ sequenceNumber: 3, id: 'mockid', wsWriteTimestamp: timestamp }) }); assert.isUndefined(socket.mercuryTimeOffset); }); }); it('updates time offset consistently across multiple pongs', () => { const timestamps = [1735689600000, 1735689601000, 1735689602000]; const spy = sinon.spy(); socket.on('pong', spy); timestamps.forEach(timestamp => { mockWebSocket.emit('message', { data: JSON.stringify({ sequenceNumber: 3, id: 'mockid', type: 'pong', wsWriteTimestamp: timestamp }) }); }); assert.equal(spy.callCount, timestamps.length); assert.isNumber(socket.mercuryTimeOffset); });packages/@webex/internal-plugin-mercury/test/unit/spec/mercury.js (1)
776-789
: Add more test cases for comprehensive coverage.While the current test case verifies basic functionality, consider adding these scenarios:
- Test with different time offsets (positive and negative)
- Test with missing or invalid
wsWriteTimestamp
- Test with edge cases (e.g., very large time differences)
describe('#_setTimeOffset', () => { it('sets mercuryTimeOffset based on the difference between wsWriteTimestamp and now', () => { const event = { data: { wsWriteTimestamp: Date.now() - 1000, } }; assert.isUndefined(mercury.mercuryTimeOffset); mercury._setTimeOffset(event); assert.isDefined(mercury.mercuryTimeOffset); assert.true(mercury.mercuryTimeOffset > 0); }); + + it('handles missing wsWriteTimestamp gracefully', () => { + const event = { data: {} }; + mercury._setTimeOffset(event); + assert.isUndefined(mercury.mercuryTimeOffset); + }); + + it('handles negative time offsets', () => { + const event = { + data: { + wsWriteTimestamp: Date.now() + 1000, + } + }; + mercury._setTimeOffset(event); + assert.isDefined(mercury.mercuryTimeOffset); + assert.true(mercury.mercuryTimeOffset < 0); + }); });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
packages/@webex/internal-plugin-mercury/src/mercury.js
(4 hunks)packages/@webex/internal-plugin-mercury/src/socket/socket-base.js
(2 hunks)packages/@webex/internal-plugin-mercury/test/unit/spec/mercury.js
(1 hunks)packages/@webex/internal-plugin-mercury/test/unit/spec/socket.js
(2 hunks)
🔇 Additional comments (3)
packages/@webex/internal-plugin-mercury/src/socket/socket-base.js (1)
Line range hint 298-312
: LGTM: Clean implementation of wsWriteTimestamp handling
The addition of wsWriteTimestamp parsing and inclusion in the processedEvent object is implemented correctly. The parseInt ensures proper type conversion for the timestamp.
packages/@webex/internal-plugin-mercury/src/mercury.js (2)
44-47
: LGTM: Well-defined mercuryTimeOffset property
The property is correctly defined with appropriate type and default value, following the existing pattern in the session object.
204-204
: LGTM: Proper event handler for time offset updates
The pong event handler is correctly added to update the time offset, ensuring synchronization on each pong message.
This pull request is automatically being deployed by Amplify Hosting (learn more). |
b7c2036
to
7f4f023
Compare
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.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/@webex/internal-plugin-mercury/test/unit/spec/mercury.js (1)
776-809
: LGTM! Comprehensive test coverage for time offset calculation.The test suite thoroughly verifies the
_setTimeOffset
functionality with test cases for:
- Positive time offset calculation
- Negative time offset calculation
- Invalid timestamp handling
Consider adding a test case to verify that
mercuryTimeOffset
is updated correctly when multiple messages are received with different timestamps. This would ensure that the offset is consistently updated throughout the WebSocket connection lifecycle.Example test case:
it('updates mercuryTimeOffset when multiple messages are received', () => { const firstEvent = { data: { wsWriteTimestamp: Date.now() - 60000, } }; const secondEvent = { data: { wsWriteTimestamp: Date.now() - 30000, } }; mercury._setTimeOffset(firstEvent); const firstOffset = mercury.mercuryTimeOffset; mercury._setTimeOffset(secondEvent); const secondOffset = mercury.mercuryTimeOffset; assert.notEqual(firstOffset, secondOffset); assert.isTrue(secondOffset < firstOffset); });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
packages/@webex/internal-plugin-mercury/src/mercury.js
(4 hunks)packages/@webex/internal-plugin-mercury/src/socket/socket-base.js
(2 hunks)packages/@webex/internal-plugin-mercury/test/unit/spec/mercury.js
(1 hunks)packages/@webex/internal-plugin-mercury/test/unit/spec/socket.js
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/@webex/internal-plugin-mercury/src/socket/socket-base.js
- packages/@webex/internal-plugin-mercury/src/mercury.js
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Initialize Project
🔇 Additional comments (2)
packages/@webex/internal-plugin-mercury/test/unit/spec/socket.js (2)
753-761
: LGTM! Test case correctly verifies wsWriteTimestamp handling.The test case properly verifies that the
wsWriteTimestamp
is included in the emitted message data, which is essential for calculating the time offset between the client and Mercury service.
795-803
: LGTM! Test case correctly verifies wsWriteTimestamp in acknowledged messages.The test case properly verifies that the
wsWriteTimestamp
is included in the acknowledged message data, maintaining consistency with the message emission test.
COMPLETES CX-17334
This pull request addresses CX-17334
< DESCRIBE THE CONTEXT OF THE ISSUE >
by making the following changes we allow clients to know the difference between their system clock, and the time according to Mercury
< DESCRIBE YOUR CHANGES >
Each message and pong from mercury includes a fiend
wsWriteTimestamp
, the time (millis since epoch) at which the message was written to the websocket. The Webex App already uses this time to check whether the local system clock is correct (and compensate if it's not). This change exposes a valuemercuryTimeOffset
onmercury
, which is the difference between this timestamp from mercury andDate.now()
, updated each time we receive a message or pong; which will allow consumers of the SDK to do the same. This has already been successfully tested in the Webex contact center agent desktop client.Change Type
The following scenarios were tested
I certified that
I have read and followed contributing guidelines
I discussed changes with code owners prior to submitting this pull request
I have not skipped any automated checks
All existing and new tests passed
I have updated the documentation accordingly
Make sure to have followed the contributing guidelines before submitting.
Summary by CodeRabbit
New Features
mercuryTimeOffset
property for improved time tracking in Mercury operations.wsWriteTimestamp
to enhance event data structure for better context in socket messages.Bug Fixes
send()
method to prevent sending messages when not in an OPEN state.Tests
_setTimeOffset
method in the Mercury plugin.Socket
class to validate new properties and enhance message handling robustness.