From 037753832ce2efbcb4c309ff8e4f4b28987254c3 Mon Sep 17 00:00:00 2001 From: rzen Date: Thu, 16 Jul 2026 20:29:37 -0400 Subject: [PATCH] Never block reconcile on per-file downloads; request evicted files up front MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On a first attach (new Mac, reinstall) the whole tree is evicted and the bounded per-file wait (~30s, serial) left the UI empty for hours. Reconcile now fires all download requests immediately, sweeps the files that are already current, and parks evicted paths as unreadable (keeping their cache entities) — the metadata observer imports each file the moment bird materializes it. --- Workouts/Sync/SyncEngine.swift | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Workouts/Sync/SyncEngine.swift b/Workouts/Sync/SyncEngine.swift index 5075923..3a3000a 100644 --- a/Workouts/Sync/SyncEngine.swift +++ b/Workouts/Sync/SyncEngine.swift @@ -779,12 +779,25 @@ final class SyncEngine { let tombstoned = await tombstones.listStubIDs() let dataFiles = await store.list().filter { !$0.hasPrefix("Stubs/") } + // Fire download requests for every evicted file up front so bird + // materializes them in parallel while this pass sweeps the current ones. + await store.downloadEvictedFiles(inSubdirectory: nil) + var liveRoutineIDs = Set() var liveWorkoutIDs = Set() var liveScheduleIDs = Set() var unreadablePaths = Set() for path in dataFiles { + // Never block on a per-file download here: on a first attach (a new + // Mac, a reinstall) the whole tree is evicted and the bounded wait + // is ~30s per file, serially — hours of empty UI. Skip it like an + // unreadable path (the prune below keeps its cache entity) and let + // the metadata observer import it the moment it materializes. + if await store.isEvicted(path) { + unreadablePaths.insert(path) + continue + } let data: Data do { data = try await store.readData(from: path)