Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes the BufferedObjectOperations clearing behavior for LiveObjects synchronization by ensuring operations are cleared at the correct time based on when the server caches object state.
Changes:
- Added RTO4d to specify that BufferedObjectOperations must be cleared when ATTACHED is received without the RESUMED flag, since the server caches object state at channel attachment time
- Added RTO5f as an explanatory note describing the expected and edge-case behaviors for server-initiated resyncs
- Deleted RTO5a2b which previously required clearing BufferedObjectOperations when a new sync sequence ID arrived
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Needed for implementing RTO4d from [1]. [1] ably/specification#416
Needed for implementing RTO4d from [1]. [1] ably/specification#416
Needed for implementing RTO4d from [1]. [1] ably/specification#416
Needed for implementing RTO4d from [1]. [1] ably/specification#416
That is, do it when we get a discontinuity, not when a new sync sequence changes, per spec changes in [1]. [1] ably/specification#416
That is, do it when we get a discontinuity, not when a new sync sequence changes, per spec changes in [1]. [1] ably/specification#416
That is, do it when we get a discontinuity, not when a new sync sequence changes, per spec changes in [1]. [1] ably/specification#416
That is, do it when we get a discontinuity, not when a new sync sequence changes, per spec changes in [1]. [1] ably/specification#416
That is, do it when we get a discontinuity, not when a new sync sequence changes, per spec changes in [1]. All written by Claude. [1] ably/specification#416
That is, do it when we get a discontinuity, not when a new sync sequence changes, per spec changes in [1]. All written by Claude. [1] ably/specification#416
That is, do it when we get a discontinuity, not when a new sync sequence changes, per spec changes in [1]. All written by Claude. [1] ably/specification#416
That is, do it when we get a discontinuity, not when a new sync sequence changes, per spec changes in [1]. Integration tests ported from JS in [2] at 06b746a. All written by Claude. [1] ably/specification#416 [2] ably/ably-js#2150
Let's have a DR?In general, the spec usually describes the "what" and not the "why". When it does explain the "why", it usually:
I think that we'd benefit from having a short DR explaining the motivation behind this new behaviour. I think that the two things it should describe are:
Why it would be an error to apply buffered operations after a discontinuityConsider the case where the client ends up reconnecting to some different region It's thus possible that there exists some operation This diagram, showing the events from the point of view of a Realtime client, might explain it better; assume that all of the blue messages are from the same region, and that there exists another earlier message |
That is, do it when we get a discontinuity, not when a new sync sequence starts, per spec changes in [1]. Integration tests ported from JS in [2] at 06b746a. All written by Claude. [1] ably/specification#416 [2] ably/ably-js#2150
textile/objects-features.textile
Outdated
| *** @(RTO5a2)@ If a new sequence id is sent from Ably, the client library must treat it as the start of a new objects sync sequence, and any previous in-flight sync must be discarded: | ||
| **** @(RTO5a2a)@ The @SyncObjectsPool@ list must be cleared | ||
| **** @(RTO5a2b)@ The @BufferedObjectOperations@ list must be cleared | ||
| **** @(RTO5a2b)@ This clause has been deleted |
There was a problem hiding this comment.
I'd say replaced, not deleted
There was a problem hiding this comment.
updated to say it was replaced by RTO4d
69b2a65 to
9efcfb1
Compare
Done both. Also note: our SDK implementations also had a separate bug where LiveObjects sync handling was only triggered for non-RESUMED ATTACHED messages (fixed in ably-js in ably/ably-js#2150). This is not a spec issue - RTO4 has never conditioned on RESUMED and has always applied to every ATTACHED message. This was purely an implementation bug, likely also present in the Kotlin and Swift plugins. |
9efcfb1 to
48d604d
Compare
This bug doesn't exist in Swift or Kotlin: |
|
Suggested a few language tweaks in 5b1c1a0 plus addressed #416 (comment) |
|
Would you also please be able to update the part of the commit message that refers to receiving an |
48d604d to
3f8bd93
Compare
Buffered object operations must be cleared on every ATTACHED message, not at the start of a new OBJECT_SYNC sequence. If HAS_OBJECTS is set on ATTACHED, the server will deliver a sync sequence following the attachment, guaranteeing that the objects in that sequence include at least all operations up to the attach point. If HAS_OBJECTS is not set, the client performs an implicit sync sequence by transitioning to SYNCING and immediately clearing local state. Read more in the LODR-058 [1]. The behaviour for receiving an OBJECT_SYNC without a preceding ATTACHED is unchanged by this PR and will be addressed separately in LODR-059 [2]. Resolves AIT-286 [1] https://ably.atlassian.net/wiki/x/NQAEHgE [2] https://ably.atlassian.net/wiki/x/AYDeHwE
RTO4c and RTO4d both describe unconditional actions upon receipt of an ATTACHED message, but the existing RTO4 intro read as purely descriptive (talking about the HAS_OBJECTS flag) rather than prescriptive. This made it unclear that actions follow, and RTO4c compensated by redundantly restating "Upon receipt of an ATTACHED ProtocolMessage". Reword RTO4 to clearly frame it as an ordered list of actions, with the HAS_OBJECTS flag noted as relevant to some of them. RTO4c and RTO4d now both read consistently as actions to perform upon receipt of ATTACHED, inheriting that context from the parent. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3f8bd93 to
ea83456
Compare
Updated 997584f
Like the change, thank you. I cherry picked the commit, but moved the |
Buffered object operations must be cleared on every ATTACHED message, not at the start of a new OBJECT_SYNC sequence. If HAS_OBJECTS is set on ATTACHED, the server will deliver a sync sequence following the attachment, guaranteeing that the objects in that sequence include at least all operations up to the attach point. If HAS_OBJECTS is not set, the client performs an implicit sync sequence by transitioning to SYNCING and immediately clearing local state. Read more in LODR-058 [1] and the specification change [2]. Resolves AIT-285 [1] https://ably.atlassian.net/wiki/x/NQAEHgE [2] ably/specification#416 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Buffered object operations must be cleared on every ATTACHED message, not at the start of a new OBJECT_SYNC sequence. If HAS_OBJECTS is set on ATTACHED, the server will deliver a sync sequence following the attachment, guaranteeing that the objects in that sequence include at least all operations up to the attach point. If HAS_OBJECTS is not set, the client performs an implicit sync sequence by transitioning to SYNCING and immediately clearing local state. Read more in LODR-058 [1] and the specification change [2]. Resolves AIT-285 [1] https://ably.atlassian.net/wiki/x/NQAEHgE [2] ably/specification#416 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Buffered object operations must be cleared on every ATTACHED message,
not at the start of a new OBJECT_SYNC sequence.
If HAS_OBJECTS is set on ATTACHED, the server will deliver a sync
sequence following the attachment, guaranteeing that the objects in
that sequence include at least all operations up to the attach point.
If HAS_OBJECTS is not set, the client performs an implicit sync
sequence by transitioning to SYNCING and immediately clearing local
state. Read more in the LODR-058 [1].
The behaviour for receiving an OBJECT_SYNC without a preceding
ATTACHED is unchanged by this PR and will be addressed separately
in LODR-059 [2].
Resolves AIT-286
[1] https://ably.atlassian.net/wiki/x/NQAEHgE
[2] https://ably.atlassian.net/wiki/x/AYDeHwE
Also this PR clarifies RTO4 structure