@@ -150,7 +150,12 @@ internal final class InternalDefaultLiveCounter: Sendable {
150150 objectMessageSerialTimestamp: Date ? ,
151151 ) -> LiveObjectUpdate < DefaultLiveCounterUpdate > {
152152 mutex. withLock {
153- mutableState. replaceData ( using: state, objectMessageSerialTimestamp: objectMessageSerialTimestamp)
153+ mutableState. replaceData (
154+ using: state,
155+ objectMessageSerialTimestamp: objectMessageSerialTimestamp,
156+ logger: logger,
157+ clock: clock,
158+ )
154159 }
155160 }
156161
@@ -191,11 +196,28 @@ internal final class InternalDefaultLiveCounter: Sendable {
191196 objectMessageSerialTimestamp: objectMessageSerialTimestamp,
192197 objectsPool: & objectsPool,
193198 logger: logger,
199+ clock: clock,
194200 userCallbackQueue: userCallbackQueue,
195201 )
196202 }
197203 }
198204
205+ // MARK: - LiveObject
206+
207+ /// Returns the object's RTLO3d `isTombstone` property.
208+ internal var isTombstone : Bool {
209+ mutex. withLock {
210+ mutableState. liveObjectMutableState. isTombstone
211+ }
212+ }
213+
214+ /// Returns the object's RTLO3e `tombstonedAt` property.
215+ internal var tombstonedAt : Date ? {
216+ mutex. withLock {
217+ mutableState. liveObjectMutableState. tombstonedAt
218+ }
219+ }
220+
199221 // MARK: - Mutable state and the operations that affect it
200222
201223 private struct MutableState : InternalLiveObject {
@@ -212,10 +234,31 @@ internal final class InternalDefaultLiveCounter: Sendable {
212234 internal mutating func replaceData(
213235 using state: ObjectState ,
214236 objectMessageSerialTimestamp: Date ? ,
237+ logger: Logger ,
238+ clock: SimpleClock ,
215239 ) -> LiveObjectUpdate < DefaultLiveCounterUpdate > {
216240 // RTLC6a: Replace the private siteTimeserials with the value from ObjectState.siteTimeserials
217241 liveObjectMutableState. siteTimeserials = state. siteTimeserials
218242
243+ // RTLC6e, RTLC6e1: No-op if we're already tombstone
244+ if liveObjectMutableState. isTombstone {
245+ return . noop
246+ }
247+
248+ // RTLC6f: Tombstone if state indicates tombstoned
249+ if state. tombstone {
250+ let dataBeforeTombstoning = data
251+
252+ tombstone (
253+ objectMessageSerialTimestamp: objectMessageSerialTimestamp,
254+ logger: logger,
255+ clock: clock,
256+ )
257+
258+ // RTLC6f1
259+ return . update( . init( amount: - dataBeforeTombstoning) )
260+ }
261+
219262 // RTLC6b: Set the private flag createOperationIsMerged to false
220263 liveObjectMutableState. createOperationIsMerged = false
221264
@@ -259,6 +302,7 @@ internal final class InternalDefaultLiveCounter: Sendable {
259302 objectMessageSerialTimestamp: Date ? ,
260303 objectsPool: inout ObjectsPool ,
261304 logger: Logger ,
305+ clock: SimpleClock ,
262306 userCallbackQueue: DispatchQueue ,
263307 ) {
264308 guard let applicableOperation = liveObjectMutableState. canApplyOperation ( objectMessageSerial: objectMessageSerial, objectMessageSiteCode: objectMessageSiteCode, logger: logger) else {
@@ -270,6 +314,12 @@ internal final class InternalDefaultLiveCounter: Sendable {
270314 // RTLC7c
271315 liveObjectMutableState. siteTimeserials [ applicableOperation. objectMessageSiteCode] = applicableOperation. objectMessageSerial
272316
317+ // RTLC7e
318+ // TODO: are we still meant to update siteTimeserials? https://github.com/ably/specification/pull/350/files#r2218718854
319+ if liveObjectMutableState. isTombstone {
320+ return
321+ }
322+
273323 switch operation. action {
274324 case . known( . counterCreate) :
275325 // RTLC7d1
@@ -284,6 +334,18 @@ internal final class InternalDefaultLiveCounter: Sendable {
284334 let update = applyCounterIncOperation ( operation. counterOp)
285335 // RTLC7d2a
286336 liveObjectMutableState. emit ( update, on: userCallbackQueue)
337+ case . known( . objectDelete) :
338+ let dataBeforeApplyingOperation = data
339+
340+ // RTLC7d4
341+ applyObjectDeleteOperation (
342+ objectMessageSerialTimestamp: objectMessageSerialTimestamp,
343+ logger: logger,
344+ clock: clock,
345+ )
346+
347+ // RTLC7d4a
348+ liveObjectMutableState. emit ( . update( . init( amount: - dataBeforeApplyingOperation) ) , on: userCallbackQueue)
287349 default :
288350 // RTLC7d3
289351 logger. log ( " Operation \( operation) has unsupported action for LiveCounter; discarding " , level: . warn)
@@ -317,5 +379,11 @@ internal final class InternalDefaultLiveCounter: Sendable {
317379 data += amount
318380 return . update( DefaultLiveCounterUpdate ( amount: amount) )
319381 }
382+
383+ /// Needed for ``InternalLiveObject`` conformance.
384+ mutating func resetDataToZeroValued( ) {
385+ // RTLC4
386+ data = 0
387+ }
320388 }
321389}
0 commit comments