mirror of
https://github.com/yattee/yattee.git
synced 2026-11-04 19:07:33 +00:00
Keep an automatic repair from ever reaching the server
A repair carries the timestamp of the selection it replaced, which is what stops it outranking a deliberate choice made elsewhere — but it also makes every ordering comparison read it as that choice. A fetch holding the selected account's tombstone and an older server context applied them in that order: the tombstone repaired the selection, and the older context then lost to it, so the "the server holds the stale copy" path marked the repair dirty and uploaded an automatic fallback under the deleted choice's timestamp, over an explicit choice. The stored context now remembers whether it is a repair, and a repair that wins an ordering pushes nothing back: the server's context stands remotely, the fallback stays local, and the next explicit choice on any device re-converges everyone. The bit is persisted with the context, or a relaunch would forget and publish it on the first stale record it read. Three more from the same trace: - The repair prefers a signed-in login on the same server, decided off statuses, and it commits — once the selection no longer names the deleted account there is nothing left for a later status to move. Foreground activation refreshes statuses ahead of it, but a deletion delivered by a silent push arrives outside that sequence, and a credential that reached this device over iCloud Keychain while it was in the background announces nothing. The refresh is now asked for by the repair itself, which closes every entry point rather than each fetch trigger having to remember one. - A device that meets a tombstone before the account it kills cannot record which instance that account lived on, and the account record arriving afterwards was discarded — with the only copy of that fact still in it. Every later repair of a context naming it then fell to local past a usable sibling. The association is kept as the record is dropped. - Removing an orphaned account deleted its credential before recording the deletion, so a crash in between brought the account back on the next launch as one nobody can sign into, owing no deletion to any device. The outbox goes first, here and in the sign-out and instance cascades; the scoped credential key needs only the account's ID, and the store is resolved through the instance before anything is removed.
This commit is contained in:
@@ -496,6 +496,11 @@ final class AccountSyncCoordinator {
|
||||
// tombstone ignores it locally and deletes it again server-side; the
|
||||
// window is bounded by fetch propagation, not by trust.
|
||||
guard !accountsManager.isDeleted(account.id) else {
|
||||
// The record is discarded, but not before it says where the account
|
||||
// lived: a device that met the tombstone first has no other source
|
||||
// for that, and a context repair without it lands on local past a
|
||||
// signed-in sibling on the same server.
|
||||
accountsManager.recordDeletedAccountInstance(account.instanceID, for: account.id)
|
||||
LoggingService.shared.logCloudKit("Ignoring resurrected account \(account.id) and re-deleting it")
|
||||
enqueueChanges?([.deleteRecord(recordID(for: .account(id: account.id)))])
|
||||
return
|
||||
@@ -868,8 +873,14 @@ final class AccountSyncCoordinator {
|
||||
|
||||
switch resolved.recordType {
|
||||
case RecordType.account:
|
||||
guard let account = try? mapper.toAccount(from: resolved),
|
||||
!accountsManager.isDeleted(account.id) else { return }
|
||||
guard let account = try? mapper.toAccount(from: resolved) else { return }
|
||||
// Dominated by a tombstone, so nothing of it becomes local state —
|
||||
// beyond the instance it lived on, which a later context repair has
|
||||
// no other way to learn.
|
||||
guard !accountsManager.isDeleted(account.id) else {
|
||||
accountsManager.recordDeletedAccountInstance(account.instanceID, for: account.id)
|
||||
return
|
||||
}
|
||||
accountsManager.applySyncedAccount(account)
|
||||
|
||||
case RecordType.dataContext:
|
||||
|
||||
Reference in New Issue
Block a user