Skip to content

Commit 0a2e72a

Browse files
Add logger to DefaultLiveCounter and DefaultLiveMap
All done by Cursor at my instruction.
1 parent 337c415 commit 0a2e72a

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
)
@@ -53,8 +56,9 @@ struct DefaultLiveCounterTests {
5356
@Test
5457
func setsCreateOperationIsMergedToFalse() {
5558
// Given: A counter whose createOperationIsMerged is true
59+
let logger = TestLogger()
5660
let counter = {
57-
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching))
61+
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching), logger: logger)
5862
// Test setup: Manipulate counter so that its createOperationIsMerged gets set to true (we need to do this since we want to later assert that it gets set to false, but the default is false).
5963
let state = TestFactories.counterObjectState(
6064
createOp: TestFactories.objectOperation(
@@ -80,7 +84,8 @@ struct DefaultLiveCounterTests {
8084
// @specOneOf(1/4) RTLC6c - count but no createOp
8185
@Test
8286
func setsDataToCounterCount() throws {
83-
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching))
87+
let logger = TestLogger()
88+
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching), logger: logger)
8489
let state = TestFactories.counterObjectState(
8590
count: 42, // Test value
8691
)
@@ -91,7 +96,8 @@ struct DefaultLiveCounterTests {
9196
// @specOneOf(2/4) RTLC6c - no count, no createOp
9297
@Test
9398
func setsDataToZeroWhenCounterCountDoesNotExist() throws {
94-
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching))
99+
let logger = TestLogger()
100+
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching), logger: logger)
95101
counter.replaceData(using: TestFactories.counterObjectState(
96102
count: nil, // Test value - must be nil
97103
))
@@ -105,7 +111,8 @@ struct DefaultLiveCounterTests {
105111
// @specOneOf(3/4) RTLC6c - count and createOp
106112
@Test
107113
func setsDataToCounterCountThenAddsCreateOpCounterCount() throws {
108-
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching))
114+
let logger = TestLogger()
115+
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching), logger: logger)
109116
let state = TestFactories.counterObjectState(
110117
createOp: TestFactories.counterCreateOperation(count: 10), // Test value - must exist
111118
count: 5, // Test value - must exist
@@ -118,7 +125,8 @@ struct DefaultLiveCounterTests {
118125
// @specOneOf(4/4) RTLC6c - no count but createOp
119126
@Test
120127
func doesNotModifyDataWhenCreateOpCounterCountDoesNotExist() throws {
121-
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching))
128+
let logger = TestLogger()
129+
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching), logger: logger)
122130
let state = TestFactories.counterObjectState(
123131
createOp: TestFactories.objectOperation(
124132
action: .known(.counterCreate),
@@ -133,7 +141,8 @@ struct DefaultLiveCounterTests {
133141
// @spec RTLC6d2
134142
@Test
135143
func setsCreateOperationIsMergedToTrue() {
136-
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching))
144+
let logger = TestLogger()
145+
let counter = DefaultLiveCounter.createZeroValued(objectID: "arbitrary", coreSDK: MockCoreSDK(channelState: .attaching), logger: logger)
137146
let state = TestFactories.counterObjectState(
138147
createOp: TestFactories.objectOperation( // Test value - must be non-nil
139148
action: .known(.counterCreate),

0 commit comments

Comments
 (0)