Skip to content

Commit 2e034b6

Browse files
committed
1 parent e72164c commit 2e034b6

6 files changed

Lines changed: 47 additions & 17 deletions

File tree

‎Sources/SQLiteData/CloudKit/CloudKit+StructuredQueries.swift‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
if isTesting {
5959
queryOutput._recordChangeTag =
6060
coder
61-
.decodeObject(of: NSNumber.self, forKey: "_recordChangeTag")?.intValue
61+
.decodeObject(of: NSString.self, forKey: "_recordChangeTag") as String?
6262
queryOutput._modificationDate =
6363
coder
6464
.decodeObject(of: NSDate.self, forKey: "_modificationDate") as Date?
@@ -111,7 +111,7 @@
111111
if isTesting {
112112
queryOutput._recordChangeTag =
113113
coder
114-
.decodeObject(of: NSNumber.self, forKey: "_recordChangeTag")?.intValue
114+
.decodeObject(of: NSString.self, forKey: "_recordChangeTag") as String?
115115
queryOutput._modificationDate =
116116
coder
117117
.decodeObject(of: NSDate.self, forKey: "_modificationDate") as Date?
@@ -397,7 +397,7 @@
397397
private struct Unbindable: Error {}
398398

399399
extension CKRecord {
400-
package var _recordChangeTag: Int? {
400+
package var _recordChangeTag: String? {
401401
get { self[#function] }
402402
set { self[#function] = newValue }
403403
}

‎Sources/SQLiteData/CloudKit/Internal/MockCloudDatabase.swift‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
let clock: AnyClock<Duration>
1616

1717
package struct State {
18-
private var lastRecordChangeTag = 0
18+
private var changeTagCounter = 0
1919
package var storage: [CKRecordZone.ID: Zone] = [:]
2020
var assets: [AssetID: Data] = [:]
2121
var deletedRecords: [(CKRecord.ID, CKRecord.RecordType)] = []
@@ -24,9 +24,9 @@
2424
package var rateLimitDuration: Duration
2525
fileprivate var requestTimestamps: [AnyClock<Duration>.Instant] = []
2626
package var fetchedRecordIDs: [CKRecord.ID] = []
27-
mutating func nextRecordChangeTag() -> Int {
28-
lastRecordChangeTag += 1
29-
return lastRecordChangeTag
27+
mutating func nextRecordChangeTag() -> String {
28+
defer { changeTagCounter += 1 }
29+
return String(changeTagCounter, radix: 36)
3030
}
3131
init(
3232
quota: Int = .max,

‎Sources/SQLiteData/CloudKit/Internal/MockSyncEngine.swift‎

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,18 @@
4545
}
4646

4747
modifications = state.withState { syncEngineState in
48-
let currentChangeTag = syncEngineState.changeTag
48+
let currentChangeTag = syncEngineState.currentChangeTag
4949
return database.state.withValue { dbState in
5050
zoneIDs.reduce(into: [CKRecord]()) { accum, zoneID in
5151
accum += ((dbState.storage[zoneID]?.records.values).map { Array($0) } ?? [])
5252
.map { $0.copy() as! CKRecord }
5353
.filter {
54-
precondition(
55-
$0._recordChangeTag != nil,
56-
"Records stored in database should have their 'recordChangeTag' assigned."
57-
)
58-
return $0._recordChangeTag! > currentChangeTag
54+
guard let changeTag = $0._recordChangeTag else {
55+
fatalError(
56+
"Records stored in database should have their 'recordChangeTag' assigned."
57+
)
58+
}
59+
return changeTag.isNewerChangeTag(than: currentChangeTag)
5960
}
6061
}
6162
}
@@ -75,7 +76,11 @@
7576
else { return }
7677

7778
state.withState {
78-
$0.changeTag = modifications.compactMap(\._recordChangeTag).max() ?? $0.changeTag
79+
for changeTag in modifications.compactMap(\._recordChangeTag) {
80+
if changeTag.isNewerChangeTag(than: $0.currentChangeTag) {
81+
$0.currentChangeTag = changeTag
82+
}
83+
}
7984
}
8085

8186
await parentSyncEngine.handleEvent(
@@ -134,7 +139,7 @@
134139
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
135140
package final class MockSyncEngineState: CKSyncEngineStateProtocol {
136141
package struct State: Sendable {
137-
package var changeTag = 0
142+
package var currentChangeTag: String?
138143
package var hasPendingUntrackedChanges = false
139144
package var pendingDatabaseChanges:
140145
OrderedDictionary<CKRecordZone.ID, CKSyncEngine.PendingDatabaseChange> = [:]
@@ -513,4 +518,11 @@
513518
}
514519
}
515520
}
521+
522+
extension String {
523+
package func isNewerChangeTag(than other: String?) -> Bool {
524+
guard let other else { return true }
525+
return self.count != other.count ? self.count > other.count : self > other
526+
}
527+
}
516528
#endif

‎Tests/SQLiteDataTests/CloudKitTests/CloudKitTests.swift‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,7 @@
888888
let record = try syncEngine.private.database.record(for: RemindersList.recordID(for: 1))
889889
record.setValue("Work", forKey: "title", at: now)
890890
// NB: Manually setting '_recordChangeTag' simulates another device saving a record.
891-
record._recordChangeTag = .random(in: 9999 ... .max)
891+
record._recordChangeTag = "zz"
892892
try await syncEngine.modifyRecords(scope: .private, saving: [record]).notify()
893893

894894
assertQuery(Reminder.all, database: userDatabase.database) {

‎Tests/SQLiteDataTests/CloudKitTests/MockSyncEngineTests.swift‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,24 @@
7676
try await syncEngine.processPendingRecordZoneChanges(scope: .private)
7777
#expect(!syncEngine.private.state.hasPendingUntrackedChanges)
7878
}
79+
80+
@Test func isNewerChangeTag() {
81+
#expect("0".isNewerChangeTag(than: nil))
82+
83+
#expect(!"0".isNewerChangeTag(than: "0"))
84+
#expect(!"z".isNewerChangeTag(than: "z"))
85+
86+
#expect("1".isNewerChangeTag(than: "0"))
87+
#expect(!"0".isNewerChangeTag(than: "1"))
88+
#expect("a".isNewerChangeTag(than: "9"))
89+
#expect(!"9".isNewerChangeTag(than: "a"))
90+
#expect("z".isNewerChangeTag(than: "a"))
91+
92+
#expect("10".isNewerChangeTag(than: "z"))
93+
#expect(!"z".isNewerChangeTag(than: "10"))
94+
#expect("100".isNewerChangeTag(than: "zz"))
95+
#expect(!"zz".isNewerChangeTag(than: "100"))
96+
}
7997
}
8098
}
8199
#endif

‎Tests/SQLiteDataTests/CloudKitTests/NextRecordZoneChangeBatchTests.swift‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@
312312
recordType: "remindersLists",
313313
parent: nil,
314314
share: nil,
315-
recordChangeTag: 3,
315+
recordChangeTag: "2",
316316
id: 1,
317317
id🗓️: 0,
318318
title: "Personal 3",

0 commit comments

Comments
 (0)