FaceGroupAnalyzer: `insertOrUpdateAssets` does not honour `Task` cancellation and returns successfully long after the task was cancelled

insertOrUpdateAssets(_:) is async throws and returns an AsyncSequence, so by the Swift Concurrency contract I expected it to observe cancellation of the enclosing Task and throw CancellationError. It does not. The call runs to completion and returns successfully, with the full result set, as though the cancellation had never happened.

In my measurement the cancel was delivered at 2.7 s and the call returned successfully at 19.0 s, having processed all 150 assets and reported 550 faces.

The practical consequence for an app is that a "Stop" button cannot stop work that is already in flight. The only way to get responsive cancellation is to slice the work into many small calls and check Task.checkCancellation() between them — which means the batch size, which should be tuned for throughput, ends up being dictated by how long a user is willing to wait after pressing Stop. For me that is the difference between a batch of 150 (≈19 s to react) and a batch of 25 (≈3 s).

The store is left in a consistent state, which is good: the assets processed before cancellation remain, and state correctly becomes .stale. So this is specifically about the cancellation signal being ignored, not about data integrity.

One detail worth knowing when reproducing this

insertOrUpdateAssets is declared nonisolated(nonsending), so it executes on the caller's executor. My first attempt at this reproducer used a plain Task { } created from @MainActor top-level code — which inherits main-actor isolation — and the detection therefore ran on the main actor and starved the very code that was supposed to cancel it: a Task.sleep(2.5s) on the main actor did not resume until the 19-second call had already finished, so the cancel was not even delivered until 19.0 s.

The attached reproducer uses Task.detached to avoid that confound, and the cancel is correctly delivered at 2.7 s. I mention it because anyone reproducing this from a @MainActor context will see a different and misleading timeline.

Feedback: FB24174707

FaceGroupAnalyzer: `insertOrUpdateAssets` does not honour `Task` cancellation and returns successfully long after the task was cancelled
 
 
Q