- CloudKit pagination: fetchAllRecords() handles >400 record batches with cursor-based pagination (400 records per page) - Cancellation support: SyncCancellationToken protocol enables graceful sync termination when background tasks expire - Per-entity progress: SyncState now tracks timestamps per entity type so interrupted syncs resume where they left off - NetworkMonitor: NWPathMonitor integration triggers sync on network restoration with 2.5s debounce to handle WiFi↔cellular flapping - wasCancelled flag in SyncResult distinguishes partial from full syncs This addresses critical data sync issues: - CloudKit queries were limited to ~400 records but bundled data has ~5000 games - Background tasks could be killed mid-sync without saving progress - App had no awareness of network state changes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
28 lines
627 B
Swift
28 lines
627 B
Swift
//
|
|
// SyncCancellationToken.swift
|
|
// SportsTime
|
|
//
|
|
// Cancellation support for long-running sync operations.
|
|
//
|
|
|
|
import Foundation
|
|
import os
|
|
|
|
/// Protocol for cancellation tokens checked between sync pages
|
|
protocol SyncCancellationToken: Sendable {
|
|
var isCancelled: Bool { get }
|
|
}
|
|
|
|
/// Concrete cancellation token for background tasks
|
|
final class BackgroundTaskCancellationToken: SyncCancellationToken, @unchecked Sendable {
|
|
private let lock = OSAllocatedUnfairLock(initialState: false)
|
|
|
|
var isCancelled: Bool {
|
|
lock.withLock { $0 }
|
|
}
|
|
|
|
func cancel() {
|
|
lock.withLock { $0 = true }
|
|
}
|
|
}
|