commit fa22f91fc24578e27a065075b8ce09ea075c9de8
parent da5eacca4a39307d777fd5e29038e7dd513d9c05
Author: Michael Camilleri <[email protected]>
Date: Fri, 8 May 2026 21:29:08 +0900
Add more instrumentation to push notifications
Diffstat:
1 file changed, 33 insertions(+), 0 deletions(-)
diff --git a/Crossmate/Sync/SyncEngine.swift b/Crossmate/Sync/SyncEngine.swift
@@ -410,9 +410,42 @@ actor SyncEngine {
} catch {
results.append(("sharedZones", describe(error)))
}
+ // CKSyncEngine creates a CKDatabaseSubscription per scope on first
+ // start. If subscription creation silently failed, no push will ever
+ // fire for that scope — surface what's actually present so a missing
+ // entry is visible from the diagnostics view rather than diagnosed
+ // by elimination.
+ results.append(await probeSubscriptions(database: container.privateCloudDatabase, label: "privateSubs"))
+ results.append(await probeSubscriptions(database: container.sharedCloudDatabase, label: "sharedSubs"))
return results
}
+ private func probeSubscriptions(
+ database: CKDatabase,
+ label: String
+ ) async -> (String, String) {
+ do {
+ let subs = try await database.allSubscriptions()
+ if subs.isEmpty {
+ return (label, "0 subscriptions — pushes will not fire")
+ }
+ let descriptions = subs.map { sub -> String in
+ let kind: String
+ switch sub {
+ case is CKDatabaseSubscription: kind = "database"
+ case is CKQuerySubscription: kind = "query"
+ case is CKRecordZoneSubscription: kind = "zone"
+ default: kind = "other(\(type(of: sub)))"
+ }
+ let silent = sub.notificationInfo?.shouldSendContentAvailable == true ? "silent" : "alert-only"
+ return "\(kind):\(sub.subscriptionID)[\(silent)]"
+ }
+ return (label, "\(subs.count): [\(descriptions.joined(separator: ", "))]")
+ } catch {
+ return (label, describe(error))
+ }
+ }
+
/// Fetches a single record by ID for the in-app record editor. Bypasses
/// CKSyncEngine's tracked changes — caller is responsible for triggering a
/// reconciling fetch if the record corresponds to a tracked local entity.