diff --git a/meta.yaml b/meta.yaml index 3d838c44..3d1a07a1 100644 --- a/meta.yaml +++ b/meta.yaml @@ -1,8 +1,8 @@ versions: # Must conform to Semantic Versioning (https://semver.org/). # Should never need to use a pre-release suffix. - specification: 5.0.0 + specification: 6.0.0 # Must be an Integer value. # Previously, prior to version 2 (i.e. versions 0.8, 1.0, 1.1 and 1.2) it was a Decimal value. - protocol: 5 + protocol: 6 diff --git a/textile/objects-features.textile b/textile/objects-features.textile index 9762400c..51957974 100644 --- a/textile/objects-features.textile +++ b/textile/objects-features.textile @@ -109,7 +109,7 @@ h3(#realtime-objects). RealtimeObjects *** @(RTO4b1)@ All objects except the one with id @root@ must be removed from the internal @ObjectsPool@ *** @(RTO4b2)@ The data for the @LiveMap@ with id @root@ must be cleared by setting it to a zero-value per "RTLM4":#RTLM4. Note that the client SDK must not create a new @LiveMap@ instance with id @root@; it must only clear the internal data of the existing @LiveMap@ with id @root@ **** @(RTO4b2a)@ Emit a @LiveMapUpdate@ object for the @LiveMap@ with ID @root@, with @LiveMapUpdate.update@ consisting of entries for the keys that were removed, each set to @removed@ -*** @(RTO4b3)@ The @SyncObjectsPool@ list must be cleared +*** @(RTO4b3)@ The @SyncObjectsPool@ must be cleared *** @(RTO4b5)@ The @bufferedObjectOperations@ list must be cleared *** @(RTO4b4)@ Perform the actions for objects sync completion as described in "RTO5c":#RTO5c * @(RTO5)@ The realtime system reserves the right to initiate an objects sync of the objects on a channel at any point once a channel is attached. A server initiated objects sync provides Ably with a means to send a complete list of objects present on the channel at any point @@ -118,14 +118,22 @@ h3(#realtime-objects). RealtimeObjects ** @(RTO5a)@ When an @OBJECT_SYNC@ @ProtocolMessage@ is received with a @channel@ attribute matching the channel name, the client library must parse the @channelSerial@ attribute: *** @(RTO5a1)@ The @channelSerial@ is used as the sync cursor and is a two-part identifier: @:@ *** @(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 +**** @(RTO5a2a)@ The @SyncObjectsPool@ must be cleared **** @(RTO5a2b)@ The @bufferedObjectOperations@ list must be cleared *** @(RTO5a3)@ If the sequence id matches the previously received sequence id, the client library should continue the sync process *** @(RTO5a4)@ The objects sync sequence for that sequence identifier is considered complete once the cursor is empty; that is when the @channelSerial@ looks like @:@ *** @(RTO5a5)@ An @OBJECT_SYNC@ may also be sent with no @channelSerial@ attribute. In this case, the sync data is entirely contained within the @ProtocolMessage@ -** @(RTO5b)@ During the sync sequence, the "@ObjectMessage.object@":../features#TR4r values from incoming @OBJECT_SYNC@ @ProtocolMessages@ must be temporarily stored in the internal @SyncObjectsPool@ list +** @(RTO5b)@ This clause has been replaced by "RTO5f":#RTO5f +** @(RTO5f)@ During the sync sequence, @ObjectMessages@ from incoming @OBJECT_SYNC@ @ProtocolMessages@ must be temporarily stored in the internal @SyncObjectsPool@, keyed by @ObjectMessage.object.objectId@. The @SyncObjectsPool@ stores one @ObjectMessage@ per @objectId@, which may represent merged state from multiple incoming messages. For each @ObjectMessage@ in the incoming @OBJECT_SYNC@ @ProtocolMessage@, let @ObjectState@ be @ObjectMessage.object@: +*** @(RTO5f1)@ If an entry with the given @ObjectState.objectId@ does not yet exist in the @SyncObjectsPool@, store the @ObjectMessage@ +*** @(RTO5f2)@ If an entry with the given @ObjectState.objectId@ already exists in the @SyncObjectsPool@, this indicates a partial object state - the server has split a large object across multiple @OBJECT_SYNC@ @ProtocolMessages@. The client must merge the partial state into the existing entry based on the object type: +**** @(RTO5f2a)@ If @ObjectState.map@ is present on the incoming message, merge the map state: +***** @(RTO5f2a1)@ If the incoming @ObjectState.tombstone@ is @true@, replace the existing entry in the @SyncObjectsPool@ with the incoming @ObjectMessage@ entirely +***** @(RTO5f2a2)@ Otherwise, merge @ObjectState.map.entries@ from the incoming message into the existing @ObjectState.map.entries@. During partial sync, no two messages for the same map object contain the same map key, so no conflict resolution is needed +**** @(RTO5f2b)@ If @ObjectState.counter@ is present on the incoming message, log an error indicating that an unexpected partial object state for a counter was received, and skip the incoming message +**** @(RTO5f2c)@ Otherwise, log a warning that a state message with an unsupported object type was received and skip the incoming message ** @(RTO5c)@ When the objects sync has completed, the client library must perform the following actions in order: -*** @(RTO5c1)@ For each @ObjectState@ in the @SyncObjectsPool@ list: +*** @(RTO5c1)@ For each @ObjectMessage@ in the @SyncObjectsPool@, let @ObjectState@ be @ObjectMessage.object@: **** @(RTO5c1a)@ If an object with @ObjectState.objectId@ exists in the internal @ObjectsPool@: ***** @(RTO5c1a1)@ Replace the internal data for the object as described in "RTLC6":#RTLC6 or "RTLM6":#RTLM6 depending on the object type, passing in current @ObjectState@ ***** @(RTO5c1a2)@ Store the @LiveObjectUpdate@ object returned by the operation, along with a reference to the updated object