-
Notifications
You must be signed in to change notification settings - Fork 61
Implement message append, protocol v5 with publish/update return values, and update/delete over realtime #2127
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: main
Are you sure you want to change the base?
Conversation
WalkthroughAdds per-message publish serials and versioned update/delete/append results to public types and channel APIs; threads publish/update responses through transport and queue callbacks; updates REST and Realtime channels to return these results; bumps protocol to v5; and adds tests for serials, updates, deletes, and appends. Changes
Sequence Diagram(s)sequenceDiagram
participant App as Application
participant Channel as Channel (Rest|Realtime)
participant Protocol as Transport/Protocol
participant Queue as MessageQueue
participant Backend as Server
rect rgb(235,248,255)
Note over App,Backend: Publish (single or batch)
App->>Channel: publish(messages)
Channel->>Protocol: send(ProtocolMessage with body)
Protocol->>Queue: queue(PendingMessage with PublishCallback)
Queue->>Backend: network send
Backend-->>Protocol: ACK(serial, count, res[])
Protocol->>Queue: completeMessages(serial, count, null, res[])
Queue->>Queue: invoke each callback(err, publishResponse)
Channel-->>App: resolve Promise<PublishResult> { serials: [...] }
end
rect rgb(255,245,235)
Note over App,Backend: Update / Delete / Append
App->>Channel: updateMessage(...) / deleteMessage(...) / appendMessage(...)
Channel->>Channel: sendUpdate(message, action, op)
Channel->>Protocol: send(ProtocolMessage action=message.update|.delete|.append)
Protocol->>Queue: queue(PendingMessage with PublishCallback)
Queue->>Backend: network send
Backend-->>Protocol: ACK(serial, count, res[] with version)
Protocol->>Queue: completeMessages(serial, count, null, res[])
Queue->>Queue: invoke callback(err, publishResponse)
Channel-->>App: resolve Promise<UpdateDeleteResult> { versionSerial: "..." }
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~55 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
ably.d.ts (1)
1451-1465: Public typings for publish/update/delete/append and new MESSAGE_APPEND action look consistent with implementation
- Adding
serials: (string | null)[]toBatchPublishSuccessResultand introducingPublishResult/UpdateDeleteResultmatches the new protocol responses and REST/realtime implementations.- Updating
Channel.publishandRealtimeChannel.publishoverloads to returnPromise<PublishResult>(and corresponding doc changes) aligns withRestChannel.publishandRealtimeChannel.publishnow returningPublishResponse.- Exposing
updateMessage/deleteMessage/appendMessageas returningPromise<UpdateDeleteResult>fits the new REST and realtime flows, which always return an object with aversionfield.- Adding
MessageActions.MESSAGE_APPENDand extendingMessageActionwithMESSAGE_APPENDdovetails with the new'message.append'operation used in both REST and realtime paths.One consideration: the public types narrow
serialsfrom optional (in internalPublishResponse) to required (in publicPublishResult). The realtime implementation defensively resolvespublishResponse || {}when the callback fires, and update/delete operations access serials with optional chainingserials?.[0]. This assumes protocol v5+ always populatesserialsfor successful publish operations—tests confirm it currently does, but if backwards compatibility with older protocol versions or edge cases becomes relevant, the required-type assumption may need revisiting.
🧹 Nitpick comments (3)
src/common/lib/client/restchannelmixin.ts (1)
11-12: Update/delete/append over REST are wired cleanlyThe refactor to build a fresh
requestMessage, encode it, and PATCH/messages/{serial}while returning a decodedUpdateDeleteResponse(or{ version: null }) is sound and keeps the caller’sMessageimmutable. Only minor nit: the error string “cannot be updated” now also covers delete/append – consider slightly more generic wording if you touch this again.Also applies to: 93-139
src/common/lib/client/realtimechannel.ts (2)
2-6: Realtime publish now returns protocol publish metadata as intendedChanging
publish(...args)andsendMessageto returnPromise<PublishResponse>cleanly exposes per-message serials from the transport layer. ThepublishResponse || {}fallback is safe given thatPublishResponse.serialsis optional, and keeps callers from having to handleundefined.If you want stricter guarantees in the future (to better align with the public
PublishResult.serialsalways being present), you could default to{ serials: [] }rather than{}when no response is provided.- } else { - resolve(publishResponse || {}); - } + } else { + resolve(publishResponse || { serials: [] }); + }Also applies to: 244-287, 493-503
1030-1088: sendUpdate flow is solid but could mirror REST’s request shape more closelyThe realtime
updateMessage/deleteMessage/appendMessagehelpers correctly:
- Require
message.serial.- Check channel/connection are publishable.
- Encode a single MESSAGE with the appropriate action.
- Return
UpdateDeleteResponseusingpublishResponse.serials?.[0] ?? null.One small improvement would be to align the constructed
Messagewith the REST path and avoid spreading the entire originalmessage, to reduce risk of sending unintended fields:- const updateDeleteMsg = Message.fromValues({ - ...message, - action: action, - }); - if (operation) { - updateDeleteMsg.version = operation; - } + const updateDeleteMsg = Message.fromValues({ + action, + serial: message.serial, + name: message.name, + data: message.data, + extras: message.extras, + }); + if (operation) { + updateDeleteMsg.version = operation; + }This would match
RestChannelMixin.updateDeleteMessageand keep the wire payload minimal.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (15)
ably.d.ts(8 hunks)src/common/lib/client/realtimeannotations.ts(1 hunks)src/common/lib/client/realtimechannel.ts(5 hunks)src/common/lib/client/restchannel.ts(4 hunks)src/common/lib/client/restchannelmixin.ts(3 hunks)src/common/lib/transport/connectionmanager.ts(3 hunks)src/common/lib/transport/messagequeue.ts(3 hunks)src/common/lib/transport/protocol.ts(2 hunks)src/common/lib/transport/transport.ts(1 hunks)src/common/lib/types/message.ts(1 hunks)src/common/lib/types/protocolmessage.ts(2 hunks)src/common/lib/util/defaults.ts(1 hunks)test/realtime/message.test.js(0 hunks)test/realtime/updates-deletes.test.js(1 hunks)test/rest/updates-deletes.test.js(8 hunks)
💤 Files with no reviewable changes (1)
- test/realtime/message.test.js
🧰 Additional context used
🧬 Code graph analysis (10)
test/rest/updates-deletes.test.js (2)
src/common/lib/client/realtimechannel.ts (2)
updateMessage(1030-1037)appendMessage(1048-1055)src/common/lib/client/restchannel.ts (2)
updateMessage(172-179)appendMessage(190-197)
src/common/lib/types/message.ts (2)
src/common/lib/types/protocolmessagecommon.ts (1)
actions(5-28)ably.d.ts (1)
MessageAction(3572-3578)
src/common/lib/transport/messagequeue.ts (1)
src/common/lib/types/protocolmessage.ts (1)
PublishResponse(152-154)
src/common/lib/transport/protocol.ts (1)
src/common/lib/types/protocolmessage.ts (1)
PublishResponse(152-154)
src/common/lib/client/realtimeannotations.ts (2)
ably.d.ts (2)
Message(3311-3369)Annotation(3374-3429)src/common/lib/util/utils.ts (1)
Properties(479-479)
test/realtime/updates-deletes.test.js (2)
src/common/lib/client/realtimechannel.ts (2)
updateMessage(1030-1037)appendMessage(1048-1055)src/common/lib/client/restchannel.ts (2)
updateMessage(172-179)appendMessage(190-197)
src/common/lib/transport/connectionmanager.ts (1)
src/common/lib/transport/protocol.ts (2)
PublishCallback(11-11)PendingMessage(13-30)
src/common/lib/client/restchannel.ts (2)
src/common/lib/types/protocolmessage.ts (2)
PublishResponse(152-154)UpdateDeleteResponse(156-158)src/common/types/http.ts (1)
RequestBody(26-29)
src/common/lib/client/restchannelmixin.ts (2)
ably.d.ts (2)
Message(3311-3369)MessageOperation(3494-3507)src/common/lib/types/protocolmessage.ts (1)
UpdateDeleteResponse(156-158)
src/common/lib/client/realtimechannel.ts (1)
src/common/lib/types/protocolmessage.ts (2)
PublishResponse(152-154)UpdateDeleteResponse(156-158)
🪛 GitHub Actions: Lint
src/common/lib/client/realtimechannel.ts
[error] 1033-1033: ESLint: '_params' is defined but never used. (@typescript-eslint/no-unused-vars)
🪛 GitHub Check: lint
src/common/lib/transport/connectionmanager.ts
[failure] 5-5:
'PublishResponse' is defined but never used. Allowed unused vars must match /^_/u
[failure] 1807-1807:
'lastQueued' is assigned a value but never used. Allowed unused vars must match /^_/u
src/common/lib/client/realtimechannel.ts
[failure] 1051-1051:
'_params' is defined but never used
[failure] 1042-1042:
'_params' is defined but never used
[failure] 1033-1033:
'_params' is defined but never used
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: test-node (20.x)
- GitHub Check: test-node (18.x)
- GitHub Check: test-node (16.x)
- GitHub Check: test-npm-package
- GitHub Check: test-browser (firefox)
- GitHub Check: test-browser (chromium)
- GitHub Check: test-browser (webkit)
🔇 Additional comments (21)
src/common/lib/util/defaults.ts (1)
94-94: Protocol version upgrade to v5 is correctly implemented.The change properly updates the protocol version across all layers: REST headers via
defaultGetHeaders/defaultPostHeaders, realtime connections viaconnectionmanager.ts, and connection parameters. No hardcoded v4 references remain in the codebase. The implementation allows version override via therequest()method parameter, enabling flexibility for testing.src/common/lib/types/message.ts (3)
23-30: LGTM! Actions array correctly updated.The addition of 'message.append' to the actions array aligns with the protocol v5 upgrade and the MessageAction type definition in the public API.
32-34: LGTM! Improved type safety.The updated return type
API.MessageActionprovides better type safety while remaining backward compatible.
36-38: LGTM! Useful encoding helper.The
encodeActionfunction provides the inverse operation tostringifyAction, enabling conversion from MessageAction strings to their numeric indices. The default to 'message.create' is appropriate.src/common/lib/transport/transport.ts (1)
164-164: LGTM! ACK handler correctly propagates response data.The addition of
message.resas a third argument to the 'ack' event emission enables the transport layer to propagate PublishResponse data, supporting the protocol v5 upgrade for publish/update return values.src/common/lib/client/realtimeannotations.ts (1)
48-48: LGTM! Explicit await improves error propagation.The change from
returntoawaitfor async operations ensures errors are caught and propagated in the current execution context, improving error handling consistency across publish/update/delete flows.Also applies to: 53-53
src/common/lib/types/protocolmessage.ts (2)
152-158: LGTM! New response types support protocol v5.The
PublishResponseandUpdateDeleteResponsetypes provide the structure for returning publish/update/delete operation results, enabling per-message serials and version metadata.
184-184: LGTM! ProtocolMessage extended with response field.The addition of
res?: PublishResponse[]enables the protocol message to carry response data for publish operations, supporting the new return value semantics in protocol v5.test/rest/updates-deletes.test.js (4)
23-55: LGTM! Comprehensive publish serial tests.The tests correctly validate that publish operations return serials for both single and batch messages, confirming the protocol v5 enhancement.
62-93: LGTM! getMessage tests validate serial-based retrieval.The tests properly verify getMessage functionality with both string serials and Message objects, aligning with the new serial-based retrieval pattern.
99-181: LGTM! Update and delete operations thoroughly tested.The tests validate operation metadata (clientId, description, metadata) and version tracking for both update and delete operations. The use of
waitForappropriately handles eventual consistency.
286-341: LGTM! Append operation test validates message concatenation.The test properly verifies that appendMessage appends data, maintains operation metadata, and that the action is correctly set to 'message.update' after the append completes. The serial-based verification approach is consistent with other tests.
test/realtime/updates-deletes.test.js (3)
23-67: LGTM! Realtime publish serial tests.The tests correctly validate that publish operations over realtime return serials for both single and batch messages, with proper resource cleanup using
realtime.close().
72-171: LGTM! Realtime update and delete operations well-tested.The tests properly use channel subscriptions to capture update and delete events, validating all aspects of the operation including version metadata, clientId, description, and metadata fields. The promise-based approach correctly handles asynchronous event delivery.
212-280: LGTM! Append test includes reattach verification.The test thoroughly validates the append operation by first capturing the append event, then reattaching with rewind to verify the full concatenated message. This confirms both the immediate append event and the eventual consistency of the message state.
src/common/lib/transport/messagequeue.ts (1)
43-65: LGTM! Message completion updated to propagate PublishResponse.The
completeMessagesmethod now correctly propagates PublishResponse data to per-message callbacks. The iteration properly maps each response to its corresponding message using the array index.Note: This changes the callback signature from
(err)to(err, publishResponse). Existing callbacks that only expect an error parameter will continue to work due to JavaScript's flexible argument handling.src/common/lib/transport/connectionmanager.ts (1)
1751-1751: LGTM! Callback signature updated for PublishResponse support.The
sendmethod signature correctly updated to usePublishCallbackinstead ofErrCallback, enabling the propagation of PublishResponse data through the messaging pipeline.src/common/lib/transport/protocol.ts (2)
2-3: Publish callback type change is coherent with new response shapeUsing
PublishCallback = StandardCallback<PublishResponse>and updatingPendingMessage.callbackkeeps the callback contract clear while enabling response metadata.ackRequiredgating remains unchanged and appropriate.Also applies to: 9-12, 15-29
36-42: Confirmed:ackemitter signature properly wired across all implementationsTransport base class correctly emits
ackevents with(message.msgSerial, message.count, message.res). Protocol listener receives this as(serial, count, res?: PublishResponse[])and passesrestoMessageQueue.completeMessages(), which has the signature(serial, count, err?, res?)and properly uses it at the callback site. Both WebSocketTransport and CometTransport inherit this behavior without override. Thenackpath correctly omitsressince NACK messages don't carry publish responses.src/common/lib/client/restchannel.ts (1)
19-26: REST publish and update/delete/append result plumbing looks correctNormalizing the POST response into
RestPublishResponseand then returning a barePublishResponsefrom_publishis tidy, and the newupdateMessage/deleteMessage/appendMessagewrappers cleanly delegate tochannelMixin.updateDeleteMessagewith the appropriate action and returnUpdateDeleteResponse. No issues spotted.Also applies to: 81-161, 172-197
src/common/lib/client/realtimechannel.ts (1)
505-512: sendPresence/sendState use sendMessage consistentlyPresence and objects state now go through
sendMessageand await its completion, so they’ll correctly propagate errors from the connection manager while ignoring the publish metadata they don’t need. This keeps all messaging paths uniform.Also applies to: 514-521
6600755 to
b28b6c0
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.
Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.
b28b6c0 to
ff35286
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 (2)
src/common/lib/client/restchannelmixin.ts (2)
93-99: Consider renaming method to reflect append capability.The method name
updateDeleteMessageno longer accurately describes its functionality now that it also handles'message.append'. Consider renaming to something likeupdateDeleteAppendMessageor a more genericmodifyMessagefor clarity.This is a minor inconsistency and can be deferred if backwards compatibility is a concern.
126-127: Simplify: remove unnecessary variable assignment.
methodis assigned but never conditionally changed. CallResource.patchdirectly.- let method = Resource.patch; - const { body, unpacked } = await method<UpdateDeleteResponse>( + const { body, unpacked } = await Resource.patch<UpdateDeleteResponse>(
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (8)
src/common/lib/client/realtimechannel.ts(5 hunks)src/common/lib/client/restchannel.ts(4 hunks)src/common/lib/client/restchannelmixin.ts(3 hunks)src/common/lib/transport/connectionmanager.ts(3 hunks)src/common/lib/types/protocolmessage.ts(2 hunks)src/platform/react-hooks/src/hooks/useChannelAttach.ts(1 hunks)test/realtime/message.test.js(0 hunks)test/realtime/updates-deletes.test.js(1 hunks)
💤 Files with no reviewable changes (1)
- test/realtime/message.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
- test/realtime/updates-deletes.test.js
🔇 Additional comments (13)
src/platform/react-hooks/src/hooks/useChannelAttach.ts (1)
42-42: LGTM! Proper React hooks compliance.Adding
ablyto the dependency array is correct since it's referenced inside the effect (line 39). This ensures the effect re-runs when the Ably instance changes, triggering a re-attachment with the new instance.src/common/lib/types/protocolmessage.ts (2)
152-158: LGTM! Protocol v5 response types are well-defined.The new
PublishResponseandUpdateDeleteResponsetypes clearly define the response shapes for publish/update/delete/append operations. The nullable types (string | nulland(string | null)[]) appropriately handle cases where values may be absent in protocol responses.
184-184: LGTM! PublishResponse array field appropriately added.The optional
resfield correctly allows a ProtocolMessage to carry multiple publish responses, consistent with the protocol v5 upgrade.src/common/lib/transport/connectionmanager.ts (3)
7-7: LGTM! Callback type import updated for protocol v5.The import change from
ErrCallbacktoPublishCallbackaligns with the protocol v5 upgrade that introduces publish/update/delete return values.
1747-1747: LGTM! Send method signature updated correctly.The
sendmethod callback parameter type correctly changed toPublishCallback, consistent with the protocol v5 changes that enable returning publish responses to callers.
1801-1803: LGTM! Queue method updated and past issue resolved.The
queuemethod callback parameter correctly changed toPublishCallback. The previously flagged unused variables (lastQueuedandmaxSize) have been removed, leaving a clean implementation that simply logs and queues the message.src/common/lib/client/restchannelmixin.ts (2)
11-11: LGTM!Import aligns with the new return type for
updateDeleteMessage.
113-121: Good practice: constructing new Message to avoid mutation.Creating a new
MessageviafromValues()instead of mutating the input is the right approach. This prevents unexpected side effects for callers.src/common/lib/client/restchannel.ts (2)
157-160: Delete operations on potentially missing keys are safe but worth noting.The code handles both unpacked and non-unpacked responses correctly, defaulting to an empty object. The
deleteoperations onchannelandmessageIdare safe even if these keys don't exist, which is appropriate here since these fields are being intentionally stripped from the RestPublishResponse before returning a PublishResponse.
172-197: LGTM! Clean delegation pattern for update/delete/append operations.All three methods (
updateMessage,deleteMessage,appendMessage) follow a consistent delegation pattern toupdateDeleteMessage, appropriately differentiating operations via the action parameter. The return type changes toPromise<UpdateDeleteResponse>align with the PR objectives.src/common/lib/client/realtimechannel.ts (3)
493-521: LGTM! sendMessage propagates PublishResponse correctly.The
sendMessagemethod now correctly returnsPromise<PublishResponse>(line 493) and defaults to an empty object if the response is undefined (line 499). ThesendPresenceandsendStatemethods appropriately consume the response viaawaitwithout exposing it to their callers, maintaining theirPromise<void>return types.
1030-1052: LGTM! Lint issue resolved and clean delegation pattern.The previously reported
@typescript-eslint/no-unused-varsissue with the_paramsparameter has been resolved by removing it from the signatures. All three methods (updateMessage,deleteMessage,appendMessage) now follow a consistent pattern, delegating to the newsendUpdatehelper with appropriate action strings.
1054-1085: Implementation is sound.Verified that
PublishResponse.serialsis correctly defined as an optional array of(string | null)[]in the codebase (src/common/lib/types/protocolmessage.ts:153). The code correctly:
- Uses optional chaining
?.to handle undefined serials- Accesses
[0]appropriately for the single message being sent- Uses nullish coalescing
?? nullto handle null elements (which occur when messages are discarded due to conflation rules)The implementation matches the documented behavior that serials is an array with 1:1 correspondence to published messages.
ff35286 to
704a9ad
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)
src/common/lib/client/restchannelmixin.ts (1)
121-121: Useconstinstead ofletfor method.The
methodvariable is never reassigned, so it should be declared withconstfor better code clarity and to prevent accidental reassignment.Apply this diff:
- let method = Resource.patch; + const method = Resource.patch;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
src/common/lib/client/restchannelmixin.ts(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/common/lib/client/restchannelmixin.ts (3)
ably.d.ts (1)
Message(3311-3369)src/common/lib/types/protocolmessage.ts (1)
UpdateDeleteResponse(156-158)src/common/lib/types/basemessage.ts (1)
CipherOptions(13-24)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: test-browser (webkit)
- GitHub Check: test-node (18.x)
- GitHub Check: test-node (16.x)
- GitHub Check: test-browser (chromium)
- GitHub Check: test-browser (firefox)
- GitHub Check: test-node (20.x)
- GitHub Check: test-npm-package
🔇 Additional comments (4)
src/common/lib/client/restchannelmixin.ts (4)
11-11: LGTM!The import of
UpdateDeleteResponsecorrectly supports the new return type for theupdateDeleteMessagemethod.
113-119: LGTM!Creating a new
MessageviaMessage.fromValuesinstead of mutating the input message is good practice. The encoding flow is clean and consistent.
132-134: LGTM!The response handling with a fallback to
{ version: null }is appropriate defensive coding, ensuring the method always returns a validUpdateDeleteResponseeven if the server response body is empty or null.
93-99: No type compatibility issues exist. The method signature change improves clarity by using explicit action parameter and explicit return type. The action parameter correctly maps toAPI.MessageAction, and theMessageOperationargument is structurally compatible with theMessage.versionproperty of typeAPI.MessageVersion.
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)
src/common/lib/client/restchannelmixin.ts (1)
120-121: Consider inlining the method variable.The
methodvariable is assigned but only used once immediately after. Since all update/delete/append operations now use PATCH, this could be simplified.🔎 Suggested simplification:
- let method = Resource.patch; - const { body, unpacked } = await method<API.UpdateDeleteResult>( + const { body, unpacked } = await Resource.patch<API.UpdateDeleteResult>(
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (8)
ably.d.ts(8 hunks)src/common/lib/client/realtimechannel.ts(5 hunks)src/common/lib/client/restchannel.ts(4 hunks)src/common/lib/client/restchannelmixin.ts(2 hunks)src/common/lib/transport/messagequeue.ts(3 hunks)src/common/lib/transport/protocol.ts(2 hunks)src/common/lib/types/protocolmessage.ts(1 hunks)test/realtime/updates-deletes.test.js(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- test/realtime/updates-deletes.test.js
- src/common/lib/types/protocolmessage.ts
🧰 Additional context used
🧬 Code graph analysis (3)
src/common/lib/transport/messagequeue.ts (1)
ably.d.ts (1)
PublishResult(3512-3518)
src/common/lib/client/restchannelmixin.ts (1)
src/common/lib/types/basemessage.ts (1)
CipherOptions(13-24)
src/common/lib/client/restchannel.ts (2)
ably.d.ts (3)
PublishResult(3512-3518)Message(3311-3369)MessageOperation(3494-3507)src/common/types/http.ts (1)
RequestBody(26-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: test-node (18.x)
- GitHub Check: test-node (20.x)
- GitHub Check: test-node (16.x)
- GitHub Check: test-browser (firefox)
- GitHub Check: test-browser (webkit)
- GitHub Check: test-browser (chromium)
- GitHub Check: test-npm-package
🔇 Additional comments (19)
src/common/lib/transport/messagequeue.ts (1)
43-65: LGTM! The indexed iteration correctly correlates publish responses with messages.The refactored loop properly passes
publishResponse(if available) from theresarray to each message's callback by index. This aligns with thePublishCallbacktype signature inprotocol.ts.One consideration: the code assumes
resarray (when present) has at least as many elements ascompleteMessages. If the server ever returns fewer elements,res?.[i]would beundefined, which is safely handled by the optional chaining. This appears intentional given thePublishResult.serialscan contain null entries per the type definition.src/common/lib/transport/protocol.ts (2)
9-12: LGTM! Clean type definition for PublishCallback.The
PublishCallbacktype alias correctly wrapsAPI.PublishResultinStandardCallback, providing proper typing for the callback chain. The import of bothStandardCallbackandErrCallbackis appropriate sinceErrCallbackis still used inonceIdle.
41-51: LGTM! Consistent propagation of publish results through the ack flow.The changes correctly thread the
resparameter from the transport'sackevent throughonAcktocompleteMessages. The optional typing (res?: API.PublishResult[]) appropriately handles cases where the response may not be present.src/common/lib/client/restchannelmixin.ts (2)
112-118: LGTM! Clean message construction avoiding mutation of user's input.Creating a new
MessageviafromValuesand then assigningactionandversionproperties correctly avoids mutating the original message object passed by the user. This is a good practice for API design.
131-132: LGTM! Safe fallback for missing response body.The fallback
{ versionSerial: null }correctly handles cases where the response body might be empty or undefined, matching theUpdateDeleteResultinterface contract whereversionSerialcan be null when a message was superseded.src/common/lib/client/restchannel.ts (3)
24-25: LGTM! Clean type extension for internal response handling.The
RestPublishResponsetype correctly extendsAPI.PublishResultwith optional internal fields (channel,messageId) that are stripped before returning to the caller.
140-161: LGTM! Response handling correctly decodes and sanitizes the publish result.The implementation properly:
- Decodes the response body based on format (binary/JSON)
- Falls back to an empty object if body is undefined
- Strips internal-only fields (
channel,messageId) before returningThe
deleteoperations mutate the decoded object, but since this is a freshly decoded object (not user-provided), this is acceptable.
191-198: LGTM! New appendMessage method follows the established pattern.The
appendMessageimplementation correctly delegates toupdateDeleteMessagewith the'message.append'action, maintaining consistency withupdateMessageanddeleteMessage.src/common/lib/client/realtimechannel.ts (4)
240-283: LGTM! Publish flow correctly returns PublishResult.The updated
publishmethod properly:
- Returns
Promise<API.PublishResult>- Propagates the response from
sendMessage- Provides a safe fallback
{ serials: [] }when response is undefined
490-500: LGTM! sendMessage correctly typed for optional PublishResult.The return type
Promise<API.PublishResult | undefined>correctly reflects that not all protocol messages (e.g., ATTACH, DETACH) return a publish result. The callback parameterpublishResponseis properly propagated.
1027-1040: LGTM! Update/delete/append methods correctly delegate to sendUpdate.The refactored methods are cleaner than the previous implementation:
- Removed the unused
_paramsparameter (addressing the past lint issue)- All three methods consistently delegate to
sendUpdatewith the appropriate action- Return type
Promise<API.UpdateDeleteResult>matches the API contract
1042-1073: LGTM! sendUpdate implements realtime update/delete/append correctly.The private
sendUpdatemethod properly:
- Validates message serial presence with a clear error message
- Checks publishable state before proceeding
- Constructs a new Message to avoid mutating the input
- Encodes and wraps in a protocol message
- Extracts
versionSerialfrom the first serial in the responseMinor observation: Line 1072 uses optional chaining (
publishResponse?.serials?.[0]) which safely handles edge cases where the response or serials array might be missing.ably.d.ts (7)
1460-1464: LGTM: Well-documented serials field additionThe addition of the
serialsarray toBatchPublishSuccessResultis consistent with the newPublishResultinterface and properly documents the 1:1 mapping to published messages, including the null case for conflated messages.
3509-3529: LGTM: Clean and well-documented result interfacesThe new
PublishResultandUpdateDeleteResultinterfaces provide clear return types for the protocol v5 publish and update/delete operations. The nullable fields are appropriately documented for edge cases (conflation and superseded updates).
3561-3578: LGTM: MESSAGE_APPEND properly integratedThe new
MESSAGE_APPENDaction type is properly added to both theMessageActionsnamespace and theMessageActionunion type, following the existing pattern. The documentation clearly explains the append semantics.
2807-2826: Breaking change: Publish methods now return PublishResultThe
publishmethod overloads now returnPromise<PublishResult>instead ofPromise<void>. This is a breaking change to the public API that allows callers to access the serials of published messages.This appears intentional for the protocol v5 upgrade, but please confirm:
- Is this a documented breaking change for v5?
- Are there migration notes for users upgrading from v4?
2848-2878: LGTM: Well-designed message mutation APIThe new
updateMessage,deleteMessage, andappendMessagemethods provide a consistent API for message mutations. The documentation clearly explains:
- Patch semantics for update/delete (non-null fields replace)
- Append semantics (data appended, other fields replace)
- Return type includes versionSerial for tracking
The API design is clean and consistent across all three operations.
3079-3095: LGTM: Realtime publish methods consistent with RESTThe
RealtimeChannel.publishoverloads are updated consistently with theChannelinterface, all returningPromise<PublishResult>. This maintains consistency between REST and Realtime APIs.
3117-3147: LGTM: Realtime message mutations match REST interfaceThe
updateMessage,deleteMessage, andappendMessagemethods onRealtimeChannelare perfectly consistent with theChannelinterface, maintaining API parity between REST and Realtime clients.
requiring protocolv5 acks. also add the corresponding publish response for publish().
Not very useful, not done by any other sdks, and would be annoying to implement with the new ack protocol (handling res in the multicaster), so just removing it.
psdr5: server always sends serials, it's up to us to extract the version if it's an update
1067c51 to
7ece4a5
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: 1
🧹 Nitpick comments (5)
src/common/lib/client/restchannelmixin.ts (1)
92-133: updateDeleteMessage flow looks sound; consider broadening the error wordingThe new
updateDeleteMessagecorrectly:
- Requires a
serial,- Clones the input
Messageto avoid mutation,- Sets
actionandversion(fromoperation),- Encodes and PATCHes
/messages/{serial},- Normalizes the response to an
UpdateDeleteResultwith a{ versionSerial: null }fallback.Only nit: the error text
"cannot be updated"is now also used for delete/append operations; if you want it to read naturally for all three, you might rephrase (e.g. “cannot be updated, appended, or deleted”). Behavior-wise this is fine as-is.src/common/lib/client/restchannel.ts (1)
22-25: REST publish → PublishResult wiring is correct; optionally harden the fallback pathThe new
publish/_publishpath:
- Correctly serializes encoded messages,
- Calls
Resource.post<RestPublishResponse>,- Decodes either unpacked or encoded responses, and
- Strips
channel/messageIdto return a cleanPublishResult.One minor robustness point: in unexpected cases where the response body is empty,
decodedbecomes{}(cast toRestPublishResponse), soserialswould beundefinedat runtime even though the public type requires it. If you want to keep the type contract rock-solid, you could normalize this:const decoded = (unpacked ? body : Utils.decodeBody<RestPublishResponse>(body, client._MsgPack, format)) || ({} as RestPublishResponse); const serials = decoded.serials ?? []; delete decoded.channel; delete decoded.messageId; return { serials };This keeps behavior identical in the normal case while guaranteeing
serialsis always an array.Also applies to: 80-138, 140-162
ably.d.ts (2)
3023-3043: PublishResult / UpdateDeleteResult types align with the new protocol; consider mentioning append in the docsExported
PublishResultandUpdateDeleteResultaccurately capture:
- Per-message serials for publish, and
- The single new-version serial for an update/delete/append operation.
One small doc tweak:
UpdateDeleteResult’s comment currently reads “updated or deleted message”, but this type is also used forappendMessage. Consider updating the wording (e.g. “updated, appended, or deleted message”) to avoid confusion for consumers reading just the d.ts.
2321-2345: Channel / RealtimeChannel publish overloads: types are right, wording could be slightly clearerBoth REST
Channel.publish(...)andRealtimeChannel.publish(...)now correctly returnPromise<PublishResult>across:
publish(messages: Message[], ...)publish(message: Message, ...)publish(name: string, data: any, ...)The implementation elsewhere returns a
PublishResultwhoseserialsarray is 1:1 with the messages. For the single-message overload JSDoc, you currently say “containing the serial of the published message”; to be strictly accurate you might say “containing the serials of the published messages (a single-element array in this overload)”.Also applies to: 2591-2603
src/common/lib/client/realtimechannel.ts (1)
1027-1073: Align sendUpdate’s version handling with the REST path to avoid leaking old version metadataThe new realtime update/delete/append APIs are wired sensibly:
- Public methods log and delegate to
sendUpdatewith the appropriate action literal.sendUpdateenforces presence ofmessage.serial, checks publishability, builds a new Message, sends it via the MESSAGE action, and maps the first returned serial toversionSerial.One behavioral difference from the REST implementation: here you build the update message via:
const updateDeleteMsg = Message.fromValues({ ...message, action, }); if (operation) { updateDeleteMsg.version = operation; }Whereas the REST mixin does:
const requestMessage = Message.fromValues(message); requestMessage.action = action; requestMessage.version = operation;So for realtime updates with no
operationargument, any existingmessage.version(from a prior receive) is forwarded back to the server; in the REST path it is always cleared/overridden. To keep the wire payloads minimal and semantics aligned between REST and Realtime, you may want to mirror the REST pattern:Suggested alignment with REST version handling
- const updateDeleteMsg = Message.fromValues({ - ...message, - action: action, - }); - if (operation) { - updateDeleteMsg.version = operation; - } + const updateDeleteMsg = Message.fromValues(message); + updateDeleteMsg.action = action; + // Always override any existing version metadata (even if operation is undefined), + // matching the REST path and avoiding resending server-generated version fields. + updateDeleteMsg.version = operation;Also, as in the REST mixin, the error string still says “cannot be updated” even when performing delete/append; adjust wording if you’d like it to read naturally for all three operations.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (16)
ably.d.tssrc/common/lib/client/realtimeannotations.tssrc/common/lib/client/realtimechannel.tssrc/common/lib/client/restchannel.tssrc/common/lib/client/restchannelmixin.tssrc/common/lib/transport/connectionmanager.tssrc/common/lib/transport/messagequeue.tssrc/common/lib/transport/protocol.tssrc/common/lib/transport/transport.tssrc/common/lib/types/message.tssrc/common/lib/types/protocolmessage.tssrc/common/lib/util/defaults.tssrc/platform/react-hooks/src/hooks/useChannelAttach.tstest/realtime/message.test.jstest/realtime/updates-deletes.test.jstest/rest/updates-deletes.test.js
💤 Files with no reviewable changes (1)
- test/realtime/message.test.js
🚧 Files skipped from review as they are similar to previous changes (2)
- src/common/lib/util/defaults.ts
- src/common/lib/client/realtimeannotations.ts
🧰 Additional context used
🧬 Code graph analysis (9)
src/common/lib/types/protocolmessage.ts (1)
ably.d.ts (1)
PublishResult(3026-3032)
src/common/lib/transport/protocol.ts (1)
ably.d.ts (1)
PublishResult(3026-3032)
src/common/lib/transport/messagequeue.ts (1)
ably.d.ts (1)
PublishResult(3026-3032)
src/common/lib/transport/connectionmanager.ts (1)
src/common/lib/transport/protocol.ts (2)
PublishCallback(12-12)PendingMessage(14-31)
test/realtime/updates-deletes.test.js (2)
src/common/lib/client/realtimechannel.ts (2)
updateMessage(1027-1030)appendMessage(1037-1040)src/common/lib/client/restchannel.ts (2)
updateMessage(173-180)appendMessage(191-198)
src/common/lib/client/restchannel.ts (2)
ably.d.ts (4)
PublishResult(3026-3032)Message(2825-2883)MessageOperation(3008-3021)UpdateDeleteResult(3037-3043)src/common/types/http.ts (1)
RequestBody(26-29)
test/rest/updates-deletes.test.js (2)
src/common/lib/client/realtimechannel.ts (2)
updateMessage(1027-1030)appendMessage(1037-1040)src/common/lib/client/restchannel.ts (2)
updateMessage(173-180)appendMessage(191-198)
src/common/lib/client/realtimechannel.ts (2)
ably.d.ts (2)
PublishResult(3026-3032)UpdateDeleteResult(3037-3043)src/common/lib/types/errorinfo.ts (1)
ErrorInfo(35-66)
src/common/lib/client/restchannelmixin.ts (2)
ably.d.ts (3)
Message(2825-2883)MessageOperation(3008-3021)UpdateDeleteResult(3037-3043)src/common/lib/types/basemessage.ts (1)
CipherOptions(13-24)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: test-npm-package
- GitHub Check: test-node (18.x)
- GitHub Check: test-node (20.x)
- GitHub Check: test-browser (firefox)
- GitHub Check: test-node (16.x)
- GitHub Check: test-browser (chromium)
- GitHub Check: test-browser (webkit)
🔇 Additional comments (19)
src/platform/react-hooks/src/hooks/useChannelAttach.ts (1)
42-42: LGTM! Correctly adds missing dependency.The
ablyinstance is used within the effect (line 39), so including it in the dependency array follows React's exhaustive-deps rule. This ensures the effect re-runs when the Ably instance changes, which is the correct behavior.src/common/lib/types/message.ts (2)
23-30: LGTM!The addition of 'message.append' to the actions array is correct and aligns with the protocol v5 changes described in the PR objectives.
36-38: This concern is invalid due to TypeScript type safety.The
encodeActionfunction parameter typeAPI.MessageActionis a union type of exactly the 6 string literals that exist in theactionsarray. TypeScript's type system guarantees that only these valid values can be passed to the function, soindexOfwill never return-1for properly typed inputs. No validation is needed; the code is already type-safe at compile time.Note: This function is exported but never actually called in the codebase;
Message.encode()inlines the same logic instead.Likely an incorrect or invalid review comment.
src/common/lib/types/protocolmessage.ts (1)
178-178: LGTM!The addition of the
resfield to supportPublishResult[]is correct and aligns with the protocol v5 changes for returning publish serials.src/common/lib/transport/transport.ts (1)
164-164: LGTM!The ACK event now correctly passes the
resparameter to propagate publish results. This is consistent with the protocol v5 changes and the updated messagequeue completion flow.test/rest/updates-deletes.test.js (1)
1-342: LGTM!This comprehensive test suite provides excellent coverage for REST message operations including:
- Publish serial returns (single and batch)
- Message retrieval, updates, deletes, and appends
- Operation metadata propagation
- Error handling for missing serials
The tests are well-structured and align with the protocol v5 changes.
src/common/lib/transport/messagequeue.ts (1)
43-69: LGTM!The refactoring from
forEachto an index-based loop is necessary and correct for correlating each message with its correspondingPublishResult. The use of optional chaining (res?.[i]) safely handles cases whereresis undefined, and the callback correctly receives both error and publish response.src/common/lib/transport/protocol.ts (3)
9-12: LGTM!The introduction of the
PublishCallbacktype alias correctly extends the callback signature to includePublishResultin addition to errors, supporting the protocol v5 publish result flow.
14-31: LGTM!The
PendingMessageclass correctly updates the callback type toPublishCallback, maintaining type safety throughout the message queuing and acknowledgment flow.
41-52: LGTM!The ACK handling correctly threads the
resparameter from the transport event through tocompleteMessages, enabling per-message publish results to be returned to callers.test/realtime/updates-deletes.test.js (1)
1-281: Excellent test coverage for realtime operations.This comprehensive test suite provides excellent coverage for realtime message operations including:
- Publish serial returns (single and batch)
- Update/delete/append operations over realtime with event subscriptions
- Operation metadata verification
- Error handling for missing serials
- Reattach with rewind to verify message concatenation after append
The tests effectively validate the protocol v5 realtime flow.
src/common/lib/transport/connectionmanager.ts (2)
1747-1747: LGTM!The
sendmethod signature correctly updated to usePublishCallback, maintaining type safety and consistency with the protocol v5 changes.
1801-1804: LGTM!The
queuemethod has been correctly simplified and the unused variables mentioned in the past review comment (lastQueuedandmaxSize) have been removed. The method now cleanly logs and enqueues the message.src/common/lib/client/restchannel.ts (1)
173-198: REST update/delete/append delegations look consistent
updateMessage,deleteMessage, andappendMessagenow all:
- Log with distinct method names, and
- Delegate to
restchannelmixin.updateDeleteMessagewith the appropriate action literal.This keeps the REST surface thin and correctly aligned with the shared implementation in the mixin.
ably.d.ts (3)
1461-1475: Batch publish serials extension looks correctAdding
serials: (string | null)[]toBatchPublishSuccessResultwith the documented 1:1 mapping to messages, and allowing nulls for conflated messages, is consistent withPublishResultand the per-message serial semantics elsewhere in this PR.
2364-2396: updateMessage / deleteMessage / appendMessage typings and docs are consistentFor both REST
ChannelandRealtimeChannel:
updateMessage,deleteMessage, andappendMessageall returnPromise<UpdateDeleteResult>.- The docs clearly describe the patch semantics (for update/delete) and append semantics, and reference the result as containing the serial of the new version.
This matches the implementation strategy in the client code and the shape of
UpdateDeleteResult.Also applies to: 2629-2661
3075-3092: Message append action wiring looks correctIntroducing
MessageActions.MESSAGE_APPEND = 'message.append'and extendingMessageActionwith it (alongsideMESSAGE_SUMMARY) cleanly exposes append operations at the type level. The accompanying doc correctly describes howserialanddatabehave for appended messages.src/common/lib/client/realtimechannel.ts (2)
240-284: Realtime publish now correctly exposes PublishResultThe updated
publish:
- Normalizes input into an array of
Messages,- Encodes and size-checks against
maxMessageSize,- Uses
throwIfUnpublishableState()for connection/channel gating, and- Sends a MESSAGE protocol frame, returning the
PublishResult(or{ serials: [] }as a defensive fallback).
sendMessagewrappingconnectionManager.sendand returning the optionalpublishResponseis a straightforward way to surface the new per-publish result without disturbing existing call sites that ignore it.Also applies to: 490-500
502-509: sendPresence / sendState correctly reuse sendMessageBoth
sendPresenceandsendStatenow:
- Build the appropriate
ProtocolMessage(PRESENCE / OBJECT),- Delegate to
sendMessage, and- Ignore any returned
PublishResult.This shares the transport path with publish without altering semantics for callers of these methods.
Also applies to: 511-518
7ece4a5 to
05db75c
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 (3)
test/realtime/updates-deletes.test.js (1)
211-275: Avoid potential race between rewind options and implicit attach in append testIn the append test, after
await channel.detach();you:
- call
channel.subscribe(...)(which can implicitly start an attach using the current options),- then
await channel.setOptions({ params: { rewind: '1' } });,- then
await channel.attach();.There’s a small risk that the implicit attach started by
subscriberaces ahead ofsetOptions, so the attach that delivers the rewound message might not includerewind=1.Reordering to apply options before any operation that can attach makes the test more robust, for example:
Suggested reorder to eliminate the race
- // now reattach with rewind to get the full concatenated message - await channel.detach(); - const updatePromise = new Promise((resolve) => { - channel.subscribe((msg) => { - resolve(msg); - }); - }); - - await channel.setOptions({ params: { rewind: '1' } }); - await channel.attach(); + // now reattach with rewind to get the full concatenated message + await channel.detach(); + await channel.setOptions({ params: { rewind: '1' } }); + const updatePromise = new Promise((resolve) => { + channel.subscribe((msg) => { + resolve(msg); + }); + }); + await channel.attach();Functionally the same, but guarantees the attach (implicit or explicit) uses the rewound options.
src/common/lib/client/restchannelmixin.ts (1)
92-133: REST update/delete/append flow is consistent and avoids mutating caller inputThe new
updateDeleteMessageshape (explicit action union,UpdateDeleteResultreturn, freshrequestMessageviaMessage.fromValues, PATCH to/messages/{serial}and decoding the typed result) looks correct and matches the new API surface without mutating the caller’smessage.One tiny nit: the error text
"cannot be updated"now also covers delete and append operations; if you want the message to be fully accurate, you could widen it to “updated, deleted, or appended”.ably.d.ts (1)
3023-3043: New PublishResult/UpdateDeleteResult and MESSAGE_APPEND action fit the protocol changes
PublishResultandUpdateDeleteResultdefinitions match how results are used across REST and Realtime APIs.- Adding
MessageActions.MESSAGE_APPENDand including it inMessageActionreflects the new append operation.- Minor documentation nit:
UpdateDeleteResultis also used for append operations; you might want to mention “update, delete, or append” in its description for clarity.Overall the typings and comments line up well with the new message operation features.
Also applies to: 3045-3093
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (11)
ably.d.tssrc/common/lib/client/realtimechannel.tssrc/common/lib/client/restchannel.tssrc/common/lib/client/restchannelmixin.tssrc/common/lib/transport/messagequeue.tssrc/common/lib/transport/protocol.tssrc/common/lib/types/protocolmessage.tstest/realtime/init.test.jstest/realtime/updates-deletes.test.jstest/rest/http.test.jstest/rest/updates-deletes.test.js
🚧 Files skipped from review as they are similar to previous changes (2)
- src/common/lib/types/protocolmessage.ts
- test/rest/updates-deletes.test.js
🧰 Additional context used
🧬 Code graph analysis (6)
src/common/lib/transport/protocol.ts (1)
ably.d.ts (1)
PublishResult(3026-3032)
src/common/lib/client/restchannel.ts (2)
ably.d.ts (4)
PublishResult(3026-3032)Message(2825-2883)MessageOperation(3008-3021)UpdateDeleteResult(3037-3043)src/common/types/http.ts (1)
RequestBody(26-29)
test/realtime/updates-deletes.test.js (4)
test/rest/updates-deletes.test.js (37)
expect(4-4)helper(10-10)helper(24-24)helper(39-39)helper(63-63)helper(82-82)helper(100-100)helper(146-146)helper(189-189)helper(221-221)helper(237-237)helper(253-253)helper(269-269)helper(287-287)helper(331-331)channel(26-26)channel(41-41)channel(65-65)channel(67-67)channel(84-84)channel(86-86)channel(102-102)channel(104-104)channel(148-148)channel(150-150)channel(191-191)channel(193-193)channel(223-223)channel(239-239)channel(255-255)channel(271-271)updateMessage(108-111)updateMessage(196-199)operation(113-117)operation(154-158)operation(300-304)appendMessage(295-298)test/realtime/init.test.js (3)
helper(9-9)helper(28-28)realtime(279-279)src/common/lib/client/realtimechannel.ts (2)
updateMessage(1027-1030)appendMessage(1037-1040)src/common/lib/client/restchannel.ts (2)
updateMessage(173-180)appendMessage(191-198)
src/common/lib/transport/messagequeue.ts (1)
ably.d.ts (1)
PublishResult(3026-3032)
src/common/lib/client/realtimechannel.ts (2)
ably.d.ts (3)
PublishResult(3026-3032)Message(2825-2883)UpdateDeleteResult(3037-3043)src/common/lib/types/errorinfo.ts (1)
ErrorInfo(35-66)
src/common/lib/client/restchannelmixin.ts (1)
src/common/lib/types/basemessage.ts (1)
CipherOptions(13-24)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: test-node (18.x)
- GitHub Check: test-node (16.x)
- GitHub Check: test-npm-package
- GitHub Check: test-node (20.x)
- GitHub Check: test-browser (webkit)
- GitHub Check: test-browser (chromium)
- GitHub Check: test-browser (firefox)
🔇 Additional comments (14)
src/common/lib/transport/messagequeue.ts (1)
5-5: Ack response propagation into per-message callbacks looks correctThe additional
res?: API.PublishResult[]parameter and the per-index mapping insidecompleteMessagesalign with the existingserial/countlogic and safely handle missing results (resundefined or shorter thancount). No issues spotted with this wiring.Also applies to: 43-65
test/rest/http.test.js (1)
35-40: Header version assertion correctly updated for protocol v5Updating the
X-Ably-Versionexpectation to'5'matches the protocol bump; the rest of the header checks remain consistent.test/realtime/init.test.js (1)
46-47: Transport URI version check matches protocol v5The
connectUriassertion now expecting'v=5'is consistent with the new default protocol version and the REST header test.src/common/lib/transport/protocol.ts (1)
9-13: PublishResult-aware ack handling is wired cleanly end-to-endUsing
PublishCallback = StandardCallback<API.PublishResult>forPendingMessage.callbackand threading the optionalres?: API.PublishResult[]from the transport intoonAckandmessageQueue.completeMessageskeeps the existing callback contract while adding result data. The types and control flow remain coherent.Also applies to: 16-22, 41-43, 49-52
test/realtime/updates-deletes.test.js (1)
23-170: Realtime publish/update/delete tests give solid coverageThese tests exercise the new realtime behaviours well: single and batch serials from
publish, plus end-to-end verification thatupdateMessageanddeleteMessagepropagateserial,versionSerial,clientId,description,metadata,action,name, and payload as expected. No issues here.Also applies to: 175-206
src/common/lib/client/restchannel.ts (1)
24-25: REST publish and message mutation APIs now line up cleanly with the new result types
publish/_publishnow correctly surface anAPI.PublishResult, decoding the HTTP response and stripping internalchannel/messageIdfields defined inRestPublishResponse.- The new/updated
updateMessage,deleteMessage, andappendMessagemethods returningAPI.UpdateDeleteResultmatch the mixin implementation and the public typings.Behaviour and types look consistent with the new protocol semantics.
Also applies to: 80-81, 137-162, 173-198
ably.d.ts (3)
1462-1475: BatchPublishSuccessResult now exposes per-message serialsAdding
serials: (string | null)[]here, with docs matchingPublishResult.serials, usefully exposes the per-message serials for successful batch publishes per channel and is consistent with the new publish result model.
2321-2396: REST Channel publish/update/delete/append typings match the new behaviourThe updated
Channel.publishoverloads returningPromise<PublishResult>and theupdateMessage/deleteMessage/appendMessagemethods returningPromise<UpdateDeleteResult>mirror the REST implementation and the new tests. The doc comments clearly explain the result objects and patch/append semantics.
2593-2661: RealtimeChannel publish and message mutation typings are consistent with the realtime APIRealtimeChannel’s
publishoverloads now returningPromise<PublishResult>, andupdateMessage/deleteMessage/appendMessagereturningPromise<UpdateDeleteResult>, accurately describe what the realtime layer now returns and align with the new realtime tests exercising serials and versionSerials.src/common/lib/client/realtimechannel.ts (5)
240-284: LGTM: Publish flow correctly returns PublishResult.The updated
publishmethod properly awaits and returns thePublishResultfromsendMessage, with a sensible fallback to{ serials: [] }when the response is undefined. This aligns with the protocol v5 changes and thePublishResultinterface definition.
490-500: LGTM: sendMessage properly propagates PublishResult.The method correctly threads the
publishResponsefrom theconnectionManager.sendcallback through to the promise resolution, returningundefinedon the error path.
502-518: LGTM: sendPresence and sendState correctly updated.Both methods appropriately converted to async/await style. They correctly ignore the
PublishResultreturn value since presence and state messages don't need to track serials.
1027-1040: LGTM: Update/delete/append methods follow consistent pattern.All three methods correctly delegate to the
sendUpdatehelper with appropriate actions. The previously flagged unused_paramsparameter has been removed, resolving the lint errors.✅ Addressed previous review feedback about unused parameters.
1042-1071: LGTM: sendUpdate implementation is robust and well-structured.The helper method correctly:
- Validates
message.serialpresence with a clear, actionable error message- Reuses
throwIfUnpublishableState()for consistent state checking- Encodes and sends the update/delete/append via the publish flow
- Safely extracts
versionSerialfrom the response with proper null-handling for all edge casesThe extraction logic
publishResponse?.serials?.[0] ?? nullcorrectly handles undefined responses, empty arrays, and null serials, matching theUpdateDeleteResultinterface specification.
the code was intercepting it to return nothing, but expecting the publish call to still work without error..?
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)
test/browser/modular.test.js (1)
613-619: Excellent fix: Spy now delegates to original function.This correctly resolves the issue described in the commit message. The spy now captures the
Content-Typeheader for the target request while always delegating to and returning the result oforiginalDo, ensuring the publish operation completes successfully.Optional: Use strict equality for method comparison
Consider using strict equality (
===) instead of loose equality (==) on line 615 for consistency with JavaScript best practices:- if (method == 'post' && path == `/channels/${channelName}/messages`) { + if (method === 'post' && path === `/channels/${channelName}/messages`) {
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
test/browser/modular.test.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: test-browser (firefox)
- GitHub Check: test-browser (chromium)
- GitHub Check: test-browser (webkit)
- GitHub Check: test-npm-package
- GitHub Check: test-node (18.x)
- GitHub Check: test-node (16.x)
- GitHub Check: test-node (20.x)
🔇 Additional comments (1)
test/browser/modular.test.js (1)
25-25: LGTM: ErrorInfo export added to modular bundle.The addition of
ErrorInfoto the modular bundle exports is appropriate and aligns with enhanced error handling capabilities in the updated protocol.
| updateMessage( | ||
| message: Message, | ||
| operation?: MessageOperation, | ||
| params?: Record<string, any>, |
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.
The realtime variants of these methods still accept a params although they don't in the spec and they are presumably ignored.
cc @ttypic is the removal of these params from the Realtime variant a breaking change in Java? in ably-cocoa we can introduce an overload that doesn't take params and then document that the variant that takes params will ignore them in the realtime case (not great). We haven't marked these APIs as experimental or anything so can't really just remove the params-accepting variant
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.
in ably-cocoa we can introduce an overload that doesn't take params and then document that the variant that takes params will ignore them in the realtime case
What'd be the point?
Like: right now there are no supported per-message params. So there is no user-visible behaviour difference between doing something with the params, in either rest or realtime apis, and not. But if at some point we discover a need for a per-message param, it's pretty likely we'll want to support it in both rest and realtime apis, no?
Right now there's no spec'd standard for conveying params in a realtime publish, only a REST publish, but the asymmetry is obviously weird and annoying. I'm tempted to say that we should just have params in the api and put in the spec that if the user provides params the sdk should encode them in a ProtocolMessage.params map<string, string>. We don't currently do anything with that field serverside for a MESSAGE protocolmessage, but if we need to we can just.. start, with no protocol change
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.
Sure, my preference is to avoid any sort of breaking change to the realtime API — in that case can we revert the API change in the spec PR and reintroduce the params (I don't hugely care what we do with them — spec can just say to ignore them for now if we like)?
Missed in abf2a71. Copied from [1] at faf7497. [1] ably/ably-js#2127
Missed in abf2a71. Copied from [1] at faf7497. [1] ably/ably-js#2127
AIT-94
Summary by CodeRabbit
New Features
Behavior / Bug Fixes
Tests
✏️ Tip: You can customize this high-level summary in your review settings.