feat(sync): add pagination, cancellation, and network restoration
- 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>
This commit is contained in:
27
SportsTime/Core/Services/SyncCancellationToken.swift
Normal file
27
SportsTime/Core/Services/SyncCancellationToken.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// 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 }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user