Skip to content

Commit a6875f0

Browse files
Add logger to DefaultLiveCounter and DefaultLiveMap
All done by Cursor at my instruction.
1 parent 79c94da commit a6875f0

File tree

7 files changed

+174
-95
lines changed

7 files changed

+174
-95
lines changed

Sources/AblyLiveObjects/DefaultRealtimeObjects.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ internal final class DefaultRealtimeObjects: RealtimeObjects, LiveMapObjectPoolD
7373
(receivedObjectProtocolMessages, receivedObjectProtocolMessagesContinuation) = AsyncStream.makeStream()
7474
(receivedObjectSyncProtocolMessages, receivedObjectSyncProtocolMessagesContinuation) = AsyncStream.makeStream()
7575
(waitingForSyncEvents, waitingForSyncEventsContinuation) = AsyncStream.makeStream()
76-
mutableState = .init(objectsPool: .init(rootDelegate: self, rootCoreSDK: coreSDK))
76+
mutableState = .init(objectsPool: .init(rootDelegate: self, rootCoreSDK: coreSDK, logger: logger))
7777
}
7878

7979
// MARK: - LiveMapObjectPoolDelegate
@@ -193,7 +193,7 @@ internal final class DefaultRealtimeObjects: RealtimeObjects, LiveMapObjectPoolD
193193
/// Intended as a way for tests to populate the object pool.
194194
internal func testsOnly_createZeroValueLiveObject(forObjectID objectID: String, coreSDK: CoreSDK) -> ObjectsPool.Entry? {
195195
mutex.withLock {
196-
mutableState.objectsPool.createZeroValueObject(forObjectID: objectID, mapDelegate: self, coreSDK: coreSDK)
196+
mutableState.objectsPool.createZeroValueObject(forObjectID: objectID, mapDelegate: self, coreSDK: coreSDK, logger: logger)
197197
}
198198
}
199199

@@ -242,7 +242,7 @@ internal final class DefaultRealtimeObjects: RealtimeObjects, LiveMapObjectPoolD
242242

243243
// RTO4b1, RTO4b2: Reset the ObjectsPool to have a single empty root object
244244
// TODO: this one is unclear (are we meant to replace the root or just clear its data?) https://github.com/ably/specification/pull/333/files#r2183493458
245-
objectsPool = .init(rootDelegate: mapDelegate, rootCoreSDK: coreSDK)
245+
objectsPool = .init(rootDelegate: mapDelegate, rootCoreSDK: coreSDK, logger: logger)
246246

247247
// I have, for now, not directly implemented the "perform the actions for object sync completion" of RTO4b4 since my implementation doesn't quite match the model given there; here you only have a SyncObjectsPool if you have an OBJECT_SYNC in progress, which you might not have upon receiving an ATTACHED. Instead I've just implemented what seem like the relevant side effects. Can revisit this if "the actions for object sync completion" get more complex.
248248

Sources/AblyLiveObjects/Internal/DefaultLiveCounter.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Ably
2+
internal import AblyPlugin
23
import Foundation
34

45
/// Our default implementation of ``LiveCounter``.
@@ -27,24 +28,28 @@ internal final class DefaultLiveCounter: LiveCounter {
2728
}
2829

2930
private let coreSDK: CoreSDK
31+
private let logger: AblyPlugin.Logger
3032

3133
// MARK: - Initialization
3234

3335
internal convenience init(
3436
testsOnly_data data: Double,
3537
objectID: String,
36-
coreSDK: CoreSDK
38+
coreSDK: CoreSDK,
39+
logger: AblyPlugin.Logger
3740
) {
38-
self.init(data: data, objectID: objectID, coreSDK: coreSDK)
41+
self.init(data: data, objectID: objectID, coreSDK: coreSDK, logger: logger)
3942
}
4043

4144
private init(
4245
data: Double,
4346
objectID: String,
44-
coreSDK: CoreSDK
47+
coreSDK: CoreSDK,
48+
logger: AblyPlugin.Logger
4549
) {
4650
mutableState = .init(liveObject: .init(objectID: objectID), data: data)
4751
self.coreSDK = coreSDK
52+
self.logger = logger
4853
}
4954

5055
/// Creates a "zero-value LiveCounter", per RTLC4.
@@ -54,11 +59,13 @@ internal final class DefaultLiveCounter: LiveCounter {
5459
internal static func createZeroValued(
5560
objectID: String,
5661
coreSDK: CoreSDK,
62+
logger: AblyPlugin.Logger,
5763
) -> Self {
5864
.init(
5965
data: 0,
6066
objectID: objectID,
6167
coreSDK: coreSDK,
68+
logger: logger,
6269
)
6370
}
6471

Sources/AblyLiveObjects/Internal/DefaultLiveMap.swift

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Ably
2+
internal import AblyPlugin
23

34
/// Protocol for accessing objects from the ObjectsPool. This is used by a LiveMap when it needs to return an object given an object ID.
45
internal protocol LiveMapObjectPoolDelegate: AnyObject, Sendable {
@@ -50,6 +51,7 @@ internal final class DefaultLiveMap: LiveMap {
5051
}
5152

5253
private let coreSDK: CoreSDK
54+
private let logger: AblyPlugin.Logger
5355

5456
// MARK: - Initialization
5557

@@ -58,14 +60,16 @@ internal final class DefaultLiveMap: LiveMap {
5860
objectID: String,
5961
testsOnly_semantics semantics: WireEnum<ObjectsMapSemantics>? = nil,
6062
delegate: LiveMapObjectPoolDelegate?,
61-
coreSDK: CoreSDK
63+
coreSDK: CoreSDK,
64+
logger: AblyPlugin.Logger
6265
) {
6366
self.init(
6467
data: data,
6568
objectID: objectID,
6669
semantics: semantics,
6770
delegate: delegate,
6871
coreSDK: coreSDK,
72+
logger: logger,
6973
)
7074
}
7175

@@ -74,11 +78,13 @@ internal final class DefaultLiveMap: LiveMap {
7478
objectID: String,
7579
semantics: WireEnum<ObjectsMapSemantics>?,
7680
delegate: LiveMapObjectPoolDelegate?,
77-
coreSDK: CoreSDK
81+
coreSDK: CoreSDK,
82+
logger: AblyPlugin.Logger
7883
) {
7984
mutableState = .init(liveObject: .init(objectID: objectID), data: data, semantics: semantics)
8085
self.delegate = .init(referenced: delegate)
8186
self.coreSDK = coreSDK
87+
self.logger = logger
8288
}
8389

8490
/// Creates a "zero-value LiveMap", per RTLM4.
@@ -91,13 +97,15 @@ internal final class DefaultLiveMap: LiveMap {
9197
semantics: WireEnum<ObjectsMapSemantics>? = nil,
9298
delegate: LiveMapObjectPoolDelegate?,
9399
coreSDK: CoreSDK,
100+
logger: AblyPlugin.Logger,
94101
) -> Self {
95102
.init(
96103
data: [:],
97104
objectID: objectID,
98105
semantics: semantics,
99106
delegate: delegate,
100107
coreSDK: coreSDK,
108+
logger: logger,
101109
)
102110
}
103111

@@ -231,6 +239,7 @@ internal final class DefaultLiveMap: LiveMap {
231239
objectsPool: &objectsPool,
232240
mapDelegate: delegate.referenced,
233241
coreSDK: coreSDK,
242+
logger: logger,
234243
)
235244
}
236245
}
@@ -252,6 +261,7 @@ internal final class DefaultLiveMap: LiveMap {
252261
objectsPool: &objectsPool,
253262
mapDelegate: delegate.referenced,
254263
coreSDK: coreSDK,
264+
logger: logger,
255265
)
256266
}
257267
}
@@ -289,6 +299,7 @@ internal final class DefaultLiveMap: LiveMap {
289299
objectsPool: inout ObjectsPool,
290300
mapDelegate: LiveMapObjectPoolDelegate?,
291301
coreSDK: CoreSDK,
302+
logger: AblyPlugin.Logger,
292303
) {
293304
// RTLM6a: Replace the private siteTimeserials with the value from ObjectState.siteTimeserials
294305
liveObject.siteTimeserials = state.siteTimeserials
@@ -321,6 +332,7 @@ internal final class DefaultLiveMap: LiveMap {
321332
objectsPool: &objectsPool,
322333
mapDelegate: mapDelegate,
323334
coreSDK: coreSDK,
335+
logger: logger,
324336
)
325337
}
326338
}
@@ -338,6 +350,7 @@ internal final class DefaultLiveMap: LiveMap {
338350
objectsPool: inout ObjectsPool,
339351
mapDelegate: LiveMapObjectPoolDelegate?,
340352
coreSDK: CoreSDK,
353+
logger: AblyPlugin.Logger,
341354
) {
342355
// RTLM7a: If an entry exists in the private data for the specified key
343356
if let existingEntry = data[key] {
@@ -364,7 +377,7 @@ internal final class DefaultLiveMap: LiveMap {
364377
// RTLM7c: If the operation has a non-empty ObjectData.objectId attribute
365378
if let objectId = operationData.objectId, !objectId.isEmpty {
366379
// RTLM7c1: Create a zero-value LiveObject in the internal ObjectsPool per RTO6
367-
_ = objectsPool.createZeroValueObject(forObjectID: objectId, mapDelegate: mapDelegate, coreSDK: coreSDK)
380+
_ = objectsPool.createZeroValueObject(forObjectID: objectId, mapDelegate: mapDelegate, coreSDK: coreSDK, logger: logger)
368381
}
369382
}
370383

Sources/AblyLiveObjects/Internal/ObjectsPool.swift

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,23 +44,26 @@ internal struct ObjectsPool {
4444
internal init(
4545
rootDelegate: LiveMapObjectPoolDelegate?,
4646
rootCoreSDK: CoreSDK,
47+
logger: AblyPlugin.Logger,
4748
testsOnly_otherEntries otherEntries: [String: Entry]? = nil,
4849
) {
4950
self.init(
5051
rootDelegate: rootDelegate,
5152
rootCoreSDK: rootCoreSDK,
53+
logger: logger,
5254
otherEntries: otherEntries,
5355
)
5456
}
5557

5658
private init(
5759
rootDelegate: LiveMapObjectPoolDelegate?,
5860
rootCoreSDK: CoreSDK,
61+
logger: AblyPlugin.Logger,
5962
otherEntries: [String: Entry]?
6063
) {
6164
entries = otherEntries ?? [:]
6265
// TODO: What initial root entry to use? https://github.com/ably/specification/pull/333/files#r2152312933
63-
entries[Self.rootKey] = .map(.createZeroValued(objectID: Self.rootKey, delegate: rootDelegate, coreSDK: rootCoreSDK))
66+
entries[Self.rootKey] = .map(.createZeroValued(objectID: Self.rootKey, delegate: rootDelegate, coreSDK: rootCoreSDK, logger: logger))
6467
}
6568

6669
// MARK: - Typed root
@@ -87,8 +90,9 @@ internal struct ObjectsPool {
8790
/// - objectID: The ID of the object to create
8891
/// - mapDelegate: The delegate to use for any created LiveMap
8992
/// - coreSDK: The CoreSDK to use for any created LiveObject
93+
/// - logger: The logger to use for any created LiveObject
9094
/// - Returns: The existing or newly created object
91-
internal mutating func createZeroValueObject(forObjectID objectID: String, mapDelegate: LiveMapObjectPoolDelegate?, coreSDK: CoreSDK) -> Entry? {
95+
internal mutating func createZeroValueObject(forObjectID objectID: String, mapDelegate: LiveMapObjectPoolDelegate?, coreSDK: CoreSDK, logger: AblyPlugin.Logger) -> Entry? {
9296
// RTO6a: If an object with objectId exists in ObjectsPool, do not create a new object
9397
if let existingEntry = entries[objectID] {
9498
return existingEntry
@@ -106,9 +110,9 @@ internal struct ObjectsPool {
106110
let entry: Entry
107111
switch typeString {
108112
case "map":
109-
entry = .map(.createZeroValued(objectID: objectID, delegate: mapDelegate, coreSDK: coreSDK))
113+
entry = .map(.createZeroValued(objectID: objectID, delegate: mapDelegate, coreSDK: coreSDK, logger: logger))
110114
case "counter":
111-
entry = .counter(.createZeroValued(objectID: objectID, coreSDK: coreSDK))
115+
entry = .counter(.createZeroValued(objectID: objectID, coreSDK: coreSDK, logger: logger))
112116
default:
113117
return nil
114118
}
@@ -159,14 +163,14 @@ internal struct ObjectsPool {
159163
if objectState.counter != nil {
160164
// RTO5c1b1a: If ObjectState.counter is present, create a zero-value LiveCounter,
161165
// set its private objectId equal to ObjectState.objectId and override its internal data per RTLC6
162-
let counter = DefaultLiveCounter.createZeroValued(objectID: objectState.objectId, coreSDK: coreSDK)
166+
let counter = DefaultLiveCounter.createZeroValued(objectID: objectState.objectId, coreSDK: coreSDK, logger: logger)
163167
counter.replaceData(using: objectState)
164168
newEntry = .counter(counter)
165169
} else if let objectsMap = objectState.map {
166170
// RTO5c1b1b: If ObjectState.map is present, create a zero-value LiveMap,
167171
// set its private objectId equal to ObjectState.objectId, set its private semantics
168172
// equal to ObjectState.map.semantics and override its internal data per RTLM6
169-
let map = DefaultLiveMap.createZeroValued(objectID: objectState.objectId, semantics: objectsMap.semantics, delegate: mapDelegate, coreSDK: coreSDK)
173+
let map = DefaultLiveMap.createZeroValued(objectID: objectState.objectId, semantics: objectsMap.semantics, delegate: mapDelegate, coreSDK: coreSDK, logger: logger)
170174
map.replaceData(using: objectState, objectsPool: &self)
171175
newEntry = .map(map)
172176
} else {

Tests/AblyLiveObjectsTests/DefaultLiveCounterTests.swift

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ struct DefaultLiveCounterTests {
99
// @spec RTLC5b
1010
@Test(arguments: [.detached, .failed] as [ARTRealtimeChannelState])
1111
func valueThrowsIfChannelIsDetachedOrFailed(channelState: ARTRealtimeChannelState) async throws {
12-
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: channelState))
12+
let logger = TestLogger()
13+
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: channelState), logger: logger)
1314

1415
#expect {
1516
_ = try counter.value
@@ -25,7 +26,8 @@ struct DefaultLiveCounterTests {
2526
// @spec RTLC5c
2627
@Test
2728
func valueReturnsCurrentDataWhenChannelIsValid() throws {
28-
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attached))
29+
let logger = TestLogger()
30+
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attached), logger: logger)
2931

3032
// Set some test data
3133
counter.replaceData(using: TestFactories.counterObjectState(count: 42))
@@ -39,7 +41,8 @@ struct DefaultLiveCounterTests {
3941
// @spec RTLC6a
4042
@Test
4143
func replacesSiteTimeserials() {
42-
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching))
44+
let logger = TestLogger()
45+
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching), logger: logger)
4346
let state = TestFactories.counterObjectState(
4447
siteTimeserials: ["site1": "ts1"], // Test value
4548
)
@@ -52,7 +55,8 @@ struct DefaultLiveCounterTests {
5255
// @spec RTLC6b - Tests the case without createOp, as RTLC6d2 takes precedence when createOp exists
5356
@Test
5457
func setsCreateOperationIsMergedToFalse() {
55-
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching))
58+
let logger = TestLogger()
59+
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching), logger: logger)
5660
let state = TestFactories.counterObjectState(
5761
createOp: nil, // Test value - must be nil to test RTLC6b
5862
)
@@ -63,7 +67,8 @@ struct DefaultLiveCounterTests {
6367
// @specOneOf(1/4) RTLC6c - count but no createOp
6468
@Test
6569
func setsDataToCounterCount() throws {
66-
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching))
70+
let logger = TestLogger()
71+
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching), logger: logger)
6772
let state = TestFactories.counterObjectState(
6873
count: 42, // Test value
6974
)
@@ -74,7 +79,8 @@ struct DefaultLiveCounterTests {
7479
// @specOneOf(2/4) RTLC6c - no count, no createOp
7580
@Test
7681
func setsDataToZeroWhenCounterCountDoesNotExist() throws {
77-
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching))
82+
let logger = TestLogger()
83+
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching), logger: logger)
7884
counter.replaceData(using: TestFactories.counterObjectState(
7985
count: nil, // Test value - must be nil
8086
))
@@ -88,7 +94,8 @@ struct DefaultLiveCounterTests {
8894
// @specOneOf(3/4) RTLC6c - count and createOp
8995
@Test
9096
func setsDataToCounterCountThenAddsCreateOpCounterCount() throws {
91-
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching))
97+
let logger = TestLogger()
98+
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching), logger: logger)
9299
let state = TestFactories.counterObjectState(
93100
createOp: TestFactories.counterCreateOperation(count: 10), // Test value - must exist
94101
count: 5, // Test value - must exist
@@ -101,7 +108,8 @@ struct DefaultLiveCounterTests {
101108
// @specOneOf(4/4) RTLC6c - no count but createOp
102109
@Test
103110
func doesNotModifyDataWhenCreateOpCounterCountDoesNotExist() throws {
104-
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching))
111+
let logger = TestLogger()
112+
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching), logger: logger)
105113
let state = TestFactories.counterObjectState(
106114
createOp: TestFactories.objectOperation(
107115
action: .known(.counterCreate),
@@ -116,7 +124,8 @@ struct DefaultLiveCounterTests {
116124
// @spec RTLC6d2
117125
@Test
118126
func setsCreateOperationIsMergedToTrue() {
119-
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching))
127+
let logger = TestLogger()
128+
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching), logger: logger)
120129
let state = TestFactories.counterObjectState(
121130
createOp: TestFactories.objectOperation( // Test value - must be non-nil
122131
action: .known(.counterCreate),

0 commit comments

Comments
 (0)