@@ -27,7 +27,8 @@ the latest state.
2727 - ` (RTO1a) ` Requires the ` OBJECT_SUBSCRIBE ` channel mode to be granted
2828 per [ RTO2] ( #RTO2 )
2929 - ` (RTO1b) ` If the channel is in the ` DETACHED ` or ` FAILED ` state, the
30- library should indicate an error with code 90001
30+ library should throw an ` ErrorInfo ` error with ` statusCode ` 400 and
31+ ` code ` 90001
3132 - ` (RTO1c) ` Waits for the objects sync sequence to complete and for
3233 [ RTO5c] ( #RTO5c ) to finish
3334 - ` (RTO1d) ` Returns the object with id ` root ` from the internal
@@ -41,23 +42,28 @@ the latest state.
4142 - ` (RTO2a1) ` If the channel mode is in the set, the operation is
4243 allowed
4344 - ` (RTO2a2) ` If the channel mode is missing, unless otherwise
44- specified by the operation, the library should indicate an error
45- with code 40024 stating that the operation cannot be performed
46- without the required channel mode
45+ specified by the operation, the library should throw an
46+ ` ErrorInfo ` error with ` statusCode ` 400 and ` code ` 40024,
47+ indicating that the operation cannot be performed without the
48+ required channel mode
4749 - ` (RTO2b) ` Otherwise, a best-effort attempt is made, and the channel
4850 mode is checked against the set of channel modes requested by the
4951 user per [ TB2d] ( ../features#TB2d ) :
5052 - ` (RTO2b1) ` If the channel mode is in the set, the operation is
5153 allowed
5254 - ` (RTO2b2) ` If the channel mode is missing, unless otherwise
53- specified by the operation, the library should indicate an error
54- with code 40024 stating that the operation cannot be performed
55- without the required channel mode
55+ specified by the operation, the library should throw an
56+ ` ErrorInfo ` error with ` statusCode ` 400 and ` code ` 40024,
57+ indicating that the operation cannot be performed without the
58+ required channel mode
5659- ` (RTO3) ` An internal ` ObjectsPool ` should be used to maintain the list
5760 of objects present on a channel
5861 - ` (RTO3a) ` ` ObjectsPool ` is a ` Dict<String, LiveObject> ` - a map of
5962 ` LiveObject ` s keyed by [ ` objectId ` ] ( ../features#OST2a ) string
6063 - ` (RTO3b) ` It must always contain a ` LiveMap ` object with id ` root `
64+ - ` (RTO3b1) ` Upon initialization of the ` ObjectsPool ` , create a new
65+ ` LiveMap ` (per [ RTLM4] ( #RTLM4 ) ) with ` objectId ` set to ` root ` and
66+ add it to the ` ObjectsPool `
6167- ` (RTO4) ` When a channel ` ATTACHED ` ` ProtocolMessage ` is received, the
6268 ` ProtocolMessage ` may contain a ` HAS_OBJECTS ` bit flag indicating that
6369 it will perform an objects sync, see [ TR3] ( ../features#TR3 ) . Note
@@ -72,7 +78,10 @@ the latest state.
7278 - ` (RTO4b1) ` All objects except the one with id ` root ` must be
7379 removed from the internal ` ObjectsPool `
7480 - ` (RTO4b2) ` The data for the ` LiveMap ` with id ` root ` must be
75- cleared by setting it to a zero-value per [ RTLM4] ( #RTLM4 )
81+ cleared by setting it to a zero-value per [ RTLM4] ( #RTLM4 ) . Note
82+ that the client SDK must not create a new ` LiveMap ` instance with
83+ id ` root ` ; it must only clear the internal data of the existing
84+ ` LiveMap ` with id ` root `
7685 - ` (RTO4b3) ` The ` SyncObjectsPool ` must be cleared
7786 - ` (RTO4b4) ` Perform the actions for objects sync completion as
7887 described in [ RTO5c] ( #RTO5c )
@@ -102,27 +111,27 @@ the latest state.
102111 temporarily stored in the internal ` SyncObjectsPool ` list
103112 - ` (RTO5c) ` When the objects sync has completed, the client library
104113 must perform the following actions in order:
105- - ` (RTO5c1) ` For each ` ObjectState ` member in the ` SyncObjectsPool `
106- list:
114+ - ` (RTO5c1) ` For each ` ObjectState ` in the ` SyncObjectsPool ` list:
107115 - ` (RTO5c1a) ` If an object with ` ObjectState.objectId ` exists in
108116 the internal ` ObjectsPool ` :
109- - ` (RTO5c1a1) ` Override the internal data for the object as per
110- [ RTLC6] ( #RTLC6 ) , [ RTLM6] ( #RTLM6 )
117+ - ` (RTO5c1a1) ` Replace the internal data for the object as
118+ described in [ RTLC6] ( #RTLC6 ) or [ RTLM6] ( #RTLM6 ) depending on
119+ the object type, passing in current ` ObjectState `
111120 - ` (RTO5c1b) ` If an object with ` ObjectState.objectId ` does not
112121 exist in the internal ` ObjectsPool ` :
113122 - ` (RTO5c1b1) ` Create a new ` LiveObject ` using the data from
114123 ` ObjectState ` and add it to the internal ` ObjectsPool ` :
115124 - ` (RTO5c1b1a) ` If ` ObjectState.counter ` is present, create a
116125 zero-value ` LiveCounter ` (per [ RTLC4] ( #RTLC4 ) ), set its
117126 private ` objectId ` equal to ` ObjectState.objectId ` and
118- override its internal data using the current ` ObjectState `
127+ replace its internal data using the current ` ObjectState `
119128 per [ RTLC6] ( #RTLC6 )
120129 - ` (RTO5c1b1b) ` If ` ObjectState.map ` is present, create a
121130 zero-value ` LiveMap ` (per [ RTLM4] ( #RTLM4 ) ), set its private
122131 ` objectId ` equal to ` ObjectState.objectId ` , set its private
123- ` semantics ` equal to ` ObjectState.map.semantics ` and
124- override its internal data using the current ` ObjectState `
125- per [ RTLM6] ( #RTLM6 )
132+ ` semantics ` equal to ` ObjectState.map.semantics ` and replace
133+ its internal data using the current ` ObjectState ` per
134+ [ RTLM6] ( #RTLM6 )
126135 - ` (RTO5c1b1c) ` Otherwise, log a warning that an unsupported
127136 object state message has been received, and discard the
128137 current ` ObjectState ` without taking any action
@@ -148,6 +157,11 @@ the latest state.
148157 - ` (RTO6b3) ` If the parsed type is ` counter ` , create a zero-value
149158 ` LiveCounter ` per [ RTLC4] ( #RTLC4 ) in the ` ObjectsPool `
150159
160+ ### LiveObject
161+
162+ - ` (RTLO1) ` The ` LiveObject ` represents the common interface and
163+ includes shared functionality for concrete object types
164+
151165### LiveCounter
152166
153167- ` (RTLC1) ` The ` LiveCounter ` extends ` LiveObject `
@@ -160,9 +174,10 @@ the latest state.
160174 - ` (RTLC5a) ` Requires the ` OBJECT_SUBSCRIBE ` channel mode to be
161175 granted per [ RTO2] ( #RTO2 )
162176 - ` (RTLC5b) ` If the channel is in the ` DETACHED ` or ` FAILED ` state,
163- the library should indicate an error with code 90001
177+ the library should throw an ` ErrorInfo ` error with ` statusCode ` 400
178+ and ` code ` 90001
164179 - ` (RTLC5c) ` Returns the current ` data ` value
165- - ` (RTLC6) ` ` LiveCounter ` ’s internal ` data ` can be overridden with the
180+ - ` (RTLC6) ` ` LiveCounter ` ’s internal ` data ` can be replaced with the
166181 provided ` ObjectState ` in the following way:
167182 - ` (RTLC6a) ` Replace the private ` siteTimeserials ` of the
168183 ` LiveCounter ` with the value from ` ObjectState.siteTimeserials `
@@ -188,7 +203,8 @@ the latest state.
188203 - ` (RTLM5b) ` Requires the ` OBJECT_SUBSCRIBE ` channel mode to be
189204 granted per [ RTO2] ( #RTO2 )
190205 - ` (RTLM5c) ` If the channel is in the ` DETACHED ` or ` FAILED ` state,
191- the library should indicate an error with code 90001
206+ the library should throw an ` ErrorInfo ` error with ` statusCode ` 400
207+ and ` code ` 90001
192208 - ` (RTLM5d) ` Returns the value from the current ` data ` at the
193209 specified key, as follows:
194210 - ` (RTLM5d1) ` If no ` ObjectsMapEntry ` exists at the key, return
@@ -208,8 +224,8 @@ the latest state.
208224 - ` (RTLM5d2f2) ` If an object with id ` objectId ` exists, return
209225 it
210226 - ` (RTLM5d2g) ` Otherwise, return undefined/null
211- - ` (RTLM6) ` ` LiveMap ` internal ` data ` can be overridden with the
212- provided ` ObjectState ` in the following way:
227+ - ` (RTLM6) ` ` LiveMap ` internal ` data ` can be replaced with the provided
228+ ` ObjectState ` in the following way:
213229 - ` (RTLM6a) ` Replace the private ` siteTimeserials ` of the ` LiveMap `
214230 with the value from ` ObjectState.siteTimeserials `
215231 - ` (RTLM6b) ` Set the private flag ` createOperationIsMerged ` to ` false `
@@ -218,22 +234,23 @@ the latest state.
218234 - ` (RTLM6d) ` If ` ObjectState.createOp ` is present:
219235 - ` (RTLM6d1) ` For each key–@ObjectsMapEntry @ pair in
220236 ` ObjectState.createOp.map.entries ` :
221- - ` (RTLM6d1a) ` If ` ObjectsMapEntry.tombstone ` is ` false ` , apply
222- the ` MAP_SET ` operation to the specified key using
223- ` ObjectsMapEntry.timeserial ` and ` ObjectsMapEntry.data ` per
224- [ RTLM7] ( #RTLM7 )
237+ - ` (RTLM6d1a) ` If ` ObjectsMapEntry.tombstone ` is ` false ` or
238+ omitted, apply the ` MAP_SET ` operation to the specified key
239+ using ` ObjectsMapEntry.timeserial ` and ` ObjectsMapEntry.data `
240+ per [ RTLM7] ( #RTLM7 )
225241 - ` (RTLM6d1b) ` If ` ObjectsMapEntry.tombstone ` is ` true ` , apply the
226242 ` MAP_REMOVE ` operation to the specified key using
227243 ` ObjectsMapEntry.timeserial ` per [ RTLM8] ( #RTLM8 )
228244 - ` (RTLM6d2) ` Set the private flag ` createOperationIsMerged ` to
229245 ` true `
230246- ` (RTLM7) ` ` MAP_SET ` operation for a key can be applied to a ` LiveMap `
231247 in the following way:
232- - ` (RTLM7a) ` If an entry exists in the private ` data ` for the
233- specified key:
234- - ` (RTLM7a1) ` If the operation cannot be applied as per
235- [ RTLM9] ( #RTLM9 ) , discard the operation without taking any action
236- - ` (RTLM7a2) ` Otherwise, apply the operation:
248+ - ` (RTLM7a) ` If an ` ObjectsMapEntry ` exists in the private ` data ` for
249+ the specified key:
250+ - ` (RTLM7a1) ` If the operation cannot be applied to the existing
251+ entry as per [ RTLM9] ( #RTLM9 ) , discard the operation without taking
252+ any action
253+ - ` (RTLM7a2) ` Otherwise, apply the operation to the existing entry:
237254 - ` (RTLM7a2a) ` Set ` ObjectsMapEntry.data ` to the ` ObjectData ` from
238255 the operation
239256 - ` (RTLM7a2b) ` Set ` ObjectsMapEntry.timeserial ` to the operation’s
@@ -247,15 +264,17 @@ the latest state.
247264 ` false `
248265 - ` (RTLM7c) ` If the operation has a non-empty ` ObjectData.objectId `
249266 attribute:
250- - ` (RTLM7c1) ` Create a zero-value ` LiveObject ` in the internal
251- ` ObjectsPool ` per [ RTO6] ( #RTO6 )
267+ - ` (RTLM7c1) ` Create a zero-value ` LiveObject ` for this
268+ ` ObjectData.objectId ` in the internal ` ObjectsPool ` per
269+ [ RTO6] ( #RTO6 )
252270- ` (RTLM8) ` ` MAP_REMOVE ` operation for a key can be applied to a
253271 ` LiveMap ` in the following way:
254- - ` (RTLM8a) ` If an entry exists in the private ` data ` for the
255- specified key:
256- - ` (RTLM8a1) ` If the operation cannot be applied as per
257- [ RTLM9] ( #RTLM9 ) , discard the operation without taking any action
258- - ` (RTLM8a2) ` Otherwise, apply the operation:
272+ - ` (RTLM8a) ` If an ` ObjectsMapEntry ` exists in the private ` data ` for
273+ the specified key:
274+ - ` (RTLM8a1) ` If the operation cannot be applied to the existing
275+ entry as per [ RTLM9] ( #RTLM9 ) , discard the operation without taking
276+ any action
277+ - ` (RTLM8a2) ` Otherwise, apply the operation to the existing entry:
259278 - ` (RTLM8a2a) ` Set ` ObjectsMapEntry.data ` to undefined/null
260279 - ` (RTLM8a2b) ` Set ` ObjectsMapEntry.timeserial ` to the operation’s
261280 serial
@@ -269,19 +288,19 @@ the latest state.
269288 ` true `
270289- ` (RTLM9) ` Whether a map operation can be applied to a map entry is
271290 determined as follows:
272- - ` (RTLM9a) ` For a ` LiveMap ` using ` LWW ` (Last-Write-Wins) CRDT
273- semantics, the operation must only be applied if its serial is
274- strictly greater (”after”) than the entry’s serial when compared
275- lexicographically
291+ - ` (RTLM9a) ` For a ` LiveMap ` with ` semantics ` set to
292+ ` ObjectsMapSemantics.LWW ` (Last-Write-Wins CRDT semantics), the
293+ operation must only be applied if its serial is strictly greater
294+ (”after”) than the entry’s serial when compared lexicographically
276295 - ` (RTLM9b) ` If both the entry serial and the operation serial are
277296 null or empty strings, they are treated as the “earliest possible”
278297 serials and considered “equal”, so the operation must not be applied
279- - ` (RTLM9c) ` If only the entry serial exists, the missing operation
280- serial is considered lower than the existing entry serial, so the
281- operation must not be applied
282- - ` (RTLM9d) ` If only the operation serial exists, it is considered
283- greater than the missing entry serial, so the operation can be
284- applied
285- - ` (RTLM9e) ` If both serials exist, compare them lexicographically and
286- allow operation to be applied only if the operation’s serial is
287- greater than the entry’s serial
298+ - ` (RTLM9c) ` If only the entry serial exists and is not an empty
299+ string, the missing operation serial is considered lower than the
300+ existing entry serial, so the operation must not be applied
301+ - ` (RTLM9d) ` If only the operation serial exists and is not an empty
302+ string, it is considered greater than the missing entry serial, so
303+ the operation can be applied
304+ - ` (RTLM9e) ` If both serials exist and are not empty strings, compare
305+ them lexicographically and allow operation to be applied only if the
306+ operation’s serial is greater than the entry’s serial
0 commit comments