diff --git a/Yattee/Services/CloudKit/CloudKitConflictResolver.swift b/Yattee/Services/CloudKit/CloudKitConflictResolver.swift index c62ffe1f..0e4f2a1c 100644 --- a/Yattee/Services/CloudKit/CloudKitConflictResolver.swift +++ b/Yattee/Services/CloudKit/CloudKitConflictResolver.swift @@ -341,6 +341,10 @@ actor CloudKitConflictResolver { /// - Last write wins based on updatedAt timestamp — the same rule /// `DataManager.upsertChannelNotificationSettings` applies on arrival, so a /// record that wins the upload is never refused by the other device. + /// - An exact tie keeps the server value and needs no deterministic + /// tiebreaker: unlike accounts and data contexts, no writer stamps these + /// settings with a fixed epoch date, so a tie is an accident of the clock + /// rather than something migration produces on every device. /// - Preserve server recordChangeTag func resolveChannelNotificationSettingsConflict( local: CKRecord, diff --git a/YatteeTests/CloudKitSyncTests.swift b/YatteeTests/CloudKitSyncTests.swift index a1917a14..c2840df8 100644 --- a/YatteeTests/CloudKitSyncTests.swift +++ b/YatteeTests/CloudKitSyncTests.swift @@ -197,7 +197,7 @@ struct CloudKitSyncTests { #expect(resolved["updatedAt"] as? Date == Date(timeIntervalSince1970: 2_000)) } - @Test("A local record that only repeats the server value leaves it untouched") + @Test("Equal timestamps keep the server value") @MainActor func equalTimestampsKeepServerValue() async throws { let mapper = CloudKitSyncTests.makeMapper()