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)