Skip to content

Commit 1998057

Browse files
Inject a clock into our LiveObjects
We'll use this when setting the upcoming tombstonedAt value for objects and map entries. This was all generated by Cursor; my only change was to add some locking into the mock class.
1 parent 51e3f9f commit 1998057

11 files changed

Lines changed: 238 additions & 124 deletions

Sources/AblyLiveObjects/Internal/DefaultInternalPlugin.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ internal final class DefaultInternalPlugin: NSObject, AblyPlugin.LiveObjectsInte
3838
let callbackQueue = pluginAPI.callbackQueue(for: client)
3939

4040
logger.log("LiveObjects.DefaultInternalPlugin received prepare(_:)", level: .debug)
41-
let liveObjects = InternalDefaultRealtimeObjects(logger: logger, userCallbackQueue: callbackQueue)
41+
let liveObjects = InternalDefaultRealtimeObjects(logger: logger, userCallbackQueue: callbackQueue, clock: DefaultSimpleClock())
4242
pluginAPI.setPluginDataValue(liveObjects, forKey: Self.pluginDataKey, channel: channel)
4343
}
4444

Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,27 +29,31 @@ internal final class InternalDefaultLiveCounter: Sendable {
2929

3030
private let logger: AblyPlugin.Logger
3131
private let userCallbackQueue: DispatchQueue
32+
private let clock: SimpleClock
3233

3334
// MARK: - Initialization
3435

3536
internal convenience init(
3637
testsOnly_data data: Double,
3738
objectID: String,
3839
logger: AblyPlugin.Logger,
39-
userCallbackQueue: DispatchQueue
40+
userCallbackQueue: DispatchQueue,
41+
clock: SimpleClock
4042
) {
41-
self.init(data: data, objectID: objectID, logger: logger, userCallbackQueue: userCallbackQueue)
43+
self.init(data: data, objectID: objectID, logger: logger, userCallbackQueue: userCallbackQueue, clock: clock)
4244
}
4345

4446
private init(
4547
data: Double,
4648
objectID: String,
4749
logger: AblyPlugin.Logger,
48-
userCallbackQueue: DispatchQueue
50+
userCallbackQueue: DispatchQueue,
51+
clock: SimpleClock
4952
) {
5053
mutableState = .init(liveObject: .init(objectID: objectID), data: data)
5154
self.logger = logger
5255
self.userCallbackQueue = userCallbackQueue
56+
self.clock = clock
5357
}
5458

5559
/// Creates a "zero-value LiveCounter", per RTLC4.
@@ -60,12 +64,14 @@ internal final class InternalDefaultLiveCounter: Sendable {
6064
objectID: String,
6165
logger: AblyPlugin.Logger,
6266
userCallbackQueue: DispatchQueue,
67+
clock: SimpleClock,
6368
) -> Self {
6469
.init(
6570
data: 0,
6671
objectID: objectID,
6772
logger: logger,
6873
userCallbackQueue: userCallbackQueue,
74+
clock: clock,
6975
)
7076
}
7177

Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ internal final class InternalDefaultLiveMap: Sendable {
4646

4747
private let logger: AblyPlugin.Logger
4848
private let userCallbackQueue: DispatchQueue
49+
private let clock: SimpleClock
4950

5051
// MARK: - Initialization
5152

@@ -55,13 +56,15 @@ internal final class InternalDefaultLiveMap: Sendable {
5556
testsOnly_semantics semantics: WireEnum<ObjectsMapSemantics>? = nil,
5657
logger: AblyPlugin.Logger,
5758
userCallbackQueue: DispatchQueue,
59+
clock: SimpleClock,
5860
) {
5961
self.init(
6062
data: data,
6163
objectID: objectID,
6264
semantics: semantics,
6365
logger: logger,
6466
userCallbackQueue: userCallbackQueue,
67+
clock: clock,
6568
)
6669
}
6770

@@ -71,10 +74,12 @@ internal final class InternalDefaultLiveMap: Sendable {
7174
semantics: WireEnum<ObjectsMapSemantics>?,
7275
logger: AblyPlugin.Logger,
7376
userCallbackQueue: DispatchQueue,
77+
clock: SimpleClock,
7478
) {
7579
mutableState = .init(liveObject: .init(objectID: objectID), data: data, semantics: semantics)
7680
self.logger = logger
7781
self.userCallbackQueue = userCallbackQueue
82+
self.clock = clock
7883
}
7984

8085
/// Creates a "zero-value LiveMap", per RTLM4.
@@ -87,13 +92,15 @@ internal final class InternalDefaultLiveMap: Sendable {
8792
semantics: WireEnum<ObjectsMapSemantics>? = nil,
8893
logger: AblyPlugin.Logger,
8994
userCallbackQueue: DispatchQueue,
95+
clock: SimpleClock,
9096
) -> Self {
9197
.init(
9298
data: [:],
9399
objectID: objectID,
94100
semantics: semantics,
95101
logger: logger,
96102
userCallbackQueue: userCallbackQueue,
103+
clock: clock,
97104
)
98105
}
99106

@@ -244,6 +251,7 @@ internal final class InternalDefaultLiveMap: Sendable {
244251
using: state,
245252
objectsPool: &objectsPool,
246253
logger: logger,
254+
clock: clock,
247255
userCallbackQueue: userCallbackQueue,
248256
)
249257
}
@@ -257,6 +265,7 @@ internal final class InternalDefaultLiveMap: Sendable {
257265
objectsPool: &objectsPool,
258266
logger: logger,
259267
userCallbackQueue: userCallbackQueue,
268+
clock: clock,
260269
)
261270
}
262271
}
@@ -269,6 +278,7 @@ internal final class InternalDefaultLiveMap: Sendable {
269278
objectsPool: &objectsPool,
270279
logger: logger,
271280
userCallbackQueue: userCallbackQueue,
281+
clock: clock,
272282
)
273283
}
274284
}
@@ -288,6 +298,7 @@ internal final class InternalDefaultLiveMap: Sendable {
288298
objectsPool: &objectsPool,
289299
logger: logger,
290300
userCallbackQueue: userCallbackQueue,
301+
clock: clock,
291302
)
292303
}
293304
}
@@ -309,6 +320,7 @@ internal final class InternalDefaultLiveMap: Sendable {
309320
objectsPool: &objectsPool,
310321
logger: logger,
311322
userCallbackQueue: userCallbackQueue,
323+
clock: clock,
312324
)
313325
}
314326
}
@@ -352,6 +364,7 @@ internal final class InternalDefaultLiveMap: Sendable {
352364
using state: ObjectState,
353365
objectsPool: inout ObjectsPool,
354366
logger: AblyPlugin.Logger,
367+
clock: SimpleClock,
355368
userCallbackQueue: DispatchQueue,
356369
) -> LiveObjectUpdate<DefaultLiveMapUpdate> {
357370
// RTLM6a: Replace the private siteTimeserials with the value from ObjectState.siteTimeserials
@@ -370,6 +383,7 @@ internal final class InternalDefaultLiveMap: Sendable {
370383
objectsPool: &objectsPool,
371384
logger: logger,
372385
userCallbackQueue: userCallbackQueue,
386+
clock: clock,
373387
)
374388
} else {
375389
// TODO: I assume this is what to do, clarify in https://github.com/ably/specification/pull/346/files#r2201363446
@@ -383,6 +397,7 @@ internal final class InternalDefaultLiveMap: Sendable {
383397
objectsPool: inout ObjectsPool,
384398
logger: AblyPlugin.Logger,
385399
userCallbackQueue: DispatchQueue,
400+
clock: SimpleClock,
386401
) -> LiveObjectUpdate<DefaultLiveMapUpdate> {
387402
// RTLM17a: For each key–ObjectsMapEntry pair in ObjectOperation.map.entries
388403
let perKeyUpdates: [LiveObjectUpdate<DefaultLiveMapUpdate>] = if let entries = operation.map?.entries {
@@ -404,6 +419,7 @@ internal final class InternalDefaultLiveMap: Sendable {
404419
objectsPool: &objectsPool,
405420
logger: logger,
406421
userCallbackQueue: userCallbackQueue,
422+
clock: clock,
407423
)
408424
}
409425
}
@@ -439,6 +455,7 @@ internal final class InternalDefaultLiveMap: Sendable {
439455
objectsPool: inout ObjectsPool,
440456
logger: Logger,
441457
userCallbackQueue: DispatchQueue,
458+
clock: SimpleClock,
442459
) {
443460
guard let applicableOperation = liveObject.canApplyOperation(objectMessageSerial: objectMessageSerial, objectMessageSiteCode: objectMessageSiteCode, logger: logger) else {
444461
// RTLM15b
@@ -457,6 +474,7 @@ internal final class InternalDefaultLiveMap: Sendable {
457474
objectsPool: &objectsPool,
458475
logger: logger,
459476
userCallbackQueue: userCallbackQueue,
477+
clock: clock,
460478
)
461479
// RTLM15d1a
462480
liveObject.emit(update, on: userCallbackQueue)
@@ -478,6 +496,7 @@ internal final class InternalDefaultLiveMap: Sendable {
478496
objectsPool: &objectsPool,
479497
logger: logger,
480498
userCallbackQueue: userCallbackQueue,
499+
clock: clock,
481500
)
482501
// RTLM15d2a
483502
liveObject.emit(update, on: userCallbackQueue)
@@ -507,6 +526,7 @@ internal final class InternalDefaultLiveMap: Sendable {
507526
objectsPool: inout ObjectsPool,
508527
logger: AblyPlugin.Logger,
509528
userCallbackQueue: DispatchQueue,
529+
clock: SimpleClock,
510530
) -> LiveObjectUpdate<DefaultLiveMapUpdate> {
511531
// RTLM7a: If an entry exists in the private data for the specified key
512532
if let existingEntry = data[key] {
@@ -533,7 +553,7 @@ internal final class InternalDefaultLiveMap: Sendable {
533553
// RTLM7c: If the operation has a non-empty ObjectData.objectId attribute
534554
if let objectId = operationData.objectId, !objectId.isEmpty {
535555
// RTLM7c1: Create a zero-value LiveObject in the internal ObjectsPool per RTO6
536-
_ = objectsPool.createZeroValueObject(forObjectID: objectId, logger: logger, userCallbackQueue: userCallbackQueue)
556+
_ = objectsPool.createZeroValueObject(forObjectID: objectId, logger: logger, userCallbackQueue: userCallbackQueue, clock: clock)
537557
}
538558

539559
// RTLM7f
@@ -615,6 +635,7 @@ internal final class InternalDefaultLiveMap: Sendable {
615635
objectsPool: inout ObjectsPool,
616636
logger: AblyPlugin.Logger,
617637
userCallbackQueue: DispatchQueue,
638+
clock: SimpleClock,
618639
) -> LiveObjectUpdate<DefaultLiveMapUpdate> {
619640
if liveObject.createOperationIsMerged {
620641
// RTLM16b
@@ -630,6 +651,7 @@ internal final class InternalDefaultLiveMap: Sendable {
630651
objectsPool: &objectsPool,
631652
logger: logger,
632653
userCallbackQueue: userCallbackQueue,
654+
clock: clock,
633655
)
634656
}
635657

Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPool
1010

1111
private let logger: AblyPlugin.Logger
1212
private let userCallbackQueue: DispatchQueue
13+
private let clock: SimpleClock
1314

1415
// These drive the testsOnly_* properties that expose the received ProtocolMessages to the test suite.
1516
private let receivedObjectProtocolMessages: AsyncStream<[InboundObjectMessage]>
@@ -70,13 +71,14 @@ internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPool
7071
}
7172
}
7273

73-
internal init(logger: AblyPlugin.Logger, userCallbackQueue: DispatchQueue) {
74+
internal init(logger: AblyPlugin.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock) {
7475
self.logger = logger
7576
self.userCallbackQueue = userCallbackQueue
77+
self.clock = clock
7678
(receivedObjectProtocolMessages, receivedObjectProtocolMessagesContinuation) = AsyncStream.makeStream()
7779
(receivedObjectSyncProtocolMessages, receivedObjectSyncProtocolMessagesContinuation) = AsyncStream.makeStream()
7880
(waitingForSyncEvents, waitingForSyncEventsContinuation) = AsyncStream.makeStream()
79-
mutableState = .init(objectsPool: .init(logger: logger, userCallbackQueue: userCallbackQueue))
81+
mutableState = .init(objectsPool: .init(logger: logger, userCallbackQueue: userCallbackQueue, clock: clock))
8082
}
8183

8284
// MARK: - LiveMapObjectPoolDelegate
@@ -175,6 +177,7 @@ internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPool
175177
objectMessages: objectMessages,
176178
logger: logger,
177179
userCallbackQueue: userCallbackQueue,
180+
clock: clock,
178181
receivedObjectProtocolMessagesContinuation: receivedObjectProtocolMessagesContinuation,
179182
)
180183
}
@@ -192,6 +195,7 @@ internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPool
192195
protocolMessageChannelSerial: protocolMessageChannelSerial,
193196
logger: logger,
194197
userCallbackQueue: userCallbackQueue,
198+
clock: clock,
195199
receivedObjectSyncProtocolMessagesContinuation: receivedObjectSyncProtocolMessagesContinuation,
196200
)
197201
}
@@ -202,7 +206,7 @@ internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPool
202206
/// Intended as a way for tests to populate the object pool.
203207
internal func testsOnly_createZeroValueLiveObject(forObjectID objectID: String) -> ObjectsPool.Entry? {
204208
mutex.withLock {
205-
mutableState.objectsPool.createZeroValueObject(forObjectID: objectID, logger: logger, userCallbackQueue: userCallbackQueue)
209+
mutableState.objectsPool.createZeroValueObject(forObjectID: objectID, logger: logger, userCallbackQueue: userCallbackQueue, clock: clock)
206210
}
207211
}
208212

@@ -264,6 +268,7 @@ internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPool
264268
protocolMessageChannelSerial: String?,
265269
logger: Logger,
266270
userCallbackQueue: DispatchQueue,
271+
clock: SimpleClock,
267272
receivedObjectSyncProtocolMessagesContinuation: AsyncStream<[InboundObjectMessage]>.Continuation,
268273
) {
269274
logger.log("handleObjectSyncProtocolMessage(objectMessages: \(objectMessages), protocolMessageChannelSerial: \(String(describing: protocolMessageChannelSerial)))", level: .debug)
@@ -321,6 +326,7 @@ internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPool
321326
completedSyncObjectsPool,
322327
logger: logger,
323328
userCallbackQueue: userCallbackQueue,
329+
clock: clock,
324330
)
325331

326332
// RTO5c6
@@ -331,6 +337,7 @@ internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPool
331337
objectMessage,
332338
logger: logger,
333339
userCallbackQueue: userCallbackQueue,
340+
clock: clock,
334341
)
335342
}
336343
}
@@ -347,6 +354,7 @@ internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPool
347354
objectMessages: [InboundObjectMessage],
348355
logger: Logger,
349356
userCallbackQueue: DispatchQueue,
357+
clock: SimpleClock,
350358
receivedObjectProtocolMessagesContinuation: AsyncStream<[InboundObjectMessage]>.Continuation,
351359
) {
352360
receivedObjectProtocolMessagesContinuation.yield(objectMessages)
@@ -366,6 +374,7 @@ internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPool
366374
objectMessage,
367375
logger: logger,
368376
userCallbackQueue: userCallbackQueue,
377+
clock: clock,
369378
)
370379
}
371380
}
@@ -376,6 +385,7 @@ internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPool
376385
_ objectMessage: InboundObjectMessage,
377386
logger: Logger,
378387
userCallbackQueue: DispatchQueue,
388+
clock: SimpleClock,
379389
) {
380390
guard let operation = objectMessage.operation else {
381391
// RTO9a1
@@ -392,6 +402,7 @@ internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPool
392402
forObjectID: operation.objectId,
393403
logger: logger,
394404
userCallbackQueue: userCallbackQueue,
405+
clock: clock,
395406
) else {
396407
logger.log("Unable to create zero-value object for \(operation.objectId) when processing OBJECT message; dropping", level: .warn)
397408
return

0 commit comments

Comments
 (0)