commit 19772412fa3d29376a77791825f1805d4c59c688
parent c79ed4b81c9003a9eb97455360a6d8ead651e685
Author: Michael Camilleri <[email protected]>
Date: Thu, 23 Jul 2026 20:53:29 +0900
Use enumeration to find invalid Player records
Diffstat:
1 file changed, 29 insertions(+), 7 deletions(-)
diff --git a/Crossmate/Sync/SyncEngine.swift b/Crossmate/Sync/SyncEngine.swift
@@ -1068,13 +1068,7 @@ actor SyncEngine {
}
do {
- let records = try await queryRecords(
- type: "Player",
- database: container.privateCloudDatabase,
- zoneID: Archive.zoneID,
- predicate: NSPredicate(value: true),
- desiredKeys: []
- )
+ let records = try await chroniclePlayerRecords()
try await deleteRecords(
withIDs: records.map(\.recordID),
in: container.privateCloudDatabase
@@ -1089,6 +1083,34 @@ actor SyncEngine {
}
}
+ /// Enumerates the zone's change history rather than issuing a CKQuery.
+ /// Production does not have a queryable `recordName` index for Player, but
+ /// a zone-change fetch needs no schema index and is already the mechanism
+ /// used by the storage audit.
+ private func chroniclePlayerRecords() async throws -> [CKRecord] {
+ let database = container.privateCloudDatabase
+ var records: [CKRecord] = []
+ var token: CKServerChangeToken?
+ var moreComing = true
+
+ while moreComing {
+ let page = try await database.recordZoneChanges(
+ inZoneWith: Archive.zoneID,
+ since: token,
+ desiredKeys: []
+ )
+ token = page.changeToken
+ moreComing = page.moreComing
+ for result in page.modificationResultsByID.values {
+ let record = try result.get().record
+ if record.recordType == "Player" {
+ records.append(record)
+ }
+ }
+ }
+ return records
+ }
+
/// Pure classifier shared with tests so the migration cannot remove a
/// Player record from a live game zone.
nonisolated static func isChroniclePlayerRecordID(_ recordID: CKRecord.ID) -> Bool {