commit d537bc60350fdd2b614fb698f183cb1e5b7c59ee
parent 7434e62513449d783bce6112fbaee72a21a5f4a6
Author: Michael Camilleri <[email protected]>
Date: Wed, 13 May 2026 05:08:25 +0900
Parallelise refreshLibrary across database scopes
Pull-to-refresh ran five phases strictly back-to-back: private discovery,
shared discovery, private known-zone updates, shared known-zone updates, and a
final engine fetch. The four direct-fetch phases hit two independent CloudKit
databases, so the private and shared sides had no reason to wait for each other
— but the serial structure made the wall-time the sum of all four rather than
the slowest pair.
The two scope-specific pipelines now run concurrently via async let. Discovery
still completes before known-zone updates within a scope so any zone that
discovery just inserted is included in the same refresh — the known-zone list
is read from Core Data at the start of its phase, so overlapping the two within
a scope would leave new zones for the next pull. Engine fetch keeps its
position as the final step; it already parallelises private and shared
internally, so wrapping it would gain nothing.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Diffstat:
1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/Crossmate/Services/AppServices.swift b/Crossmate/Services/AppServices.swift
@@ -266,24 +266,28 @@ final class AppServices {
/// reality when the engine has been idle.
func refreshLibrary() async {
guard await ensureICloudSyncStarted() else { return }
- await syncMonitor.run("library refresh: private discovery") {
- _ = try await syncEngine.discoverNewZonesDirect(scope: .private)
- }
- await syncMonitor.run("library refresh: shared discovery") {
- _ = try await syncEngine.discoverNewZonesDirect(scope: .shared)
- }
- await syncMonitor.run("library refresh: private known-zone updates") {
- _ = try await syncEngine.fetchKnownZoneUpdatesDirect(scope: .private)
- }
- await syncMonitor.run("library refresh: shared known-zone updates") {
- _ = try await syncEngine.fetchKnownZoneUpdatesDirect(scope: .shared)
- }
+ // Private and shared hit different CloudKit databases, so their
+ // direct-fetch phases run as an independent pair. Within each
+ // scope, discovery still completes before known-zone updates so
+ // any zone discovery just added is included in the same refresh.
+ async let privatePhase: Void = refreshLibraryScope(.private, label: "private")
+ async let sharedPhase: Void = refreshLibraryScope(.shared, label: "shared")
+ _ = await (privatePhase, sharedPhase)
await syncMonitor.run("library refresh: engine fetch") {
try await syncEngine.fetchChanges(source: "library refresh")
}
await refreshSnapshot()
}
+ private func refreshLibraryScope(_ scope: CKDatabase.Scope, label: String) async {
+ await syncMonitor.run("library refresh: \(label) discovery") {
+ _ = try await self.syncEngine.discoverNewZonesDirect(scope: scope)
+ }
+ await syncMonitor.run("library refresh: \(label) known-zone updates") {
+ _ = try await self.syncEngine.fetchKnownZoneUpdatesDirect(scope: scope)
+ }
+ }
+
func syncOpenSharedPuzzle() async {
await movesUpdater.flush()
guard await ensureICloudSyncStarted() else { return }