fix: improve debounce task cancellation handling

- Add cancelPendingSync() method for explicit cleanup
- Use [weak self] capture to prevent potential retain issues
- Check Task.isCancelled before and after sleep
- Catch CancellationError from Task.sleep for immediate cancellation response
- Extract debounceInterval as constant

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-01-17 22:19:55 -06:00
parent aa18ed13d7
commit 64e54b3b11

View File

@@ -16,9 +16,16 @@ actor ItineraryItemService {
private var debounceTask: Task<Void, Never>?
private let maxRetries = 3
private let debounceInterval: Duration = .seconds(1.5)
private init() {}
/// Cancel any pending debounce task (for cleanup)
func cancelPendingSync() {
debounceTask?.cancel()
debounceTask = nil
}
// MARK: - CRUD Operations
/// Fetch all items for a trip
@@ -45,16 +52,25 @@ actor ItineraryItemService {
func updateItem(_ item: ItineraryItem) async {
pendingUpdates[item.id] = item
// Cancel existing debounce
// Cancel existing debounce task
debounceTask?.cancel()
// Start new debounce
debounceTask = Task {
try? await Task.sleep(for: .seconds(1.5))
// Start new debounce task with proper cancellation handling
debounceTask = Task { [weak self] in
// Check cancellation before sleeping
guard !Task.isCancelled else { return }
await flushPendingUpdates()
do {
try await Task.sleep(for: self?.debounceInterval ?? .seconds(1.5))
} catch {
// Task was cancelled during sleep
return
}
// Check cancellation after sleeping (belt and suspenders)
guard !Task.isCancelled else { return }
await self?.flushPendingUpdates()
}
}