Hi there,
First thanks for all the work on BGContinuedProcessingTask! It looks really promising.
I have a question / issue around the behavior when a BGContinuedProcessingTask expires. Here is my setup.
- I have an app who's responsible for uploading large files in the field (AKA wifi is not expected)
- For a given file, it can likely fail due to network conditions
- I'm using Multipart upload though so I can retry a file to pick up where it left off.
- I use one taskIdentifier per file, and when the file fails, I can retry the task and have it continue where it left off (I am reusing the taskIdentifier here for retries, let me know if I shouldn't be doing that)
Here is the behavior I am seeing
- I start an upload, it seems to be uploading normally
- I turn on airplane mode to simulate expiration of the task
- the task fails as expected after ~30 seconds, and I see the failure in my home screen.
- I have callbacks in the task to put my app in the proper state on expiration / failure
- I turn back on airplane mode and I retry the task, the way I do this is I do NOT re-register, I simply re-submit the task with the same TaskIdentifier.
What I would have expected is that the failure task is REPLACED with the new task and new progress. Instead what I see is TWO ContinuedBackgroundProcessingTasks, one in the failure state and one in progress.
My question is
- How can I make retries reuse the same task notification item?
- OR if that's not possible, how do I programmatically clear the task failure? I've tried cancelTask but that doesn't seem to clear it.
I use one taskIdentifier per file, and when the file fails, I can retry the task and have it continue where it left off.
This is not what I would do. The problem here is that you're not going to be able to start new tasks once you enter the background, so you're not going to be able to retry once you enter the background. I would use the background task to handle the "whole" operation, including retries.
(I am reusing the taskIdentifier here for retries, let me know if I shouldn't be doing that.)
Yeah, don't do that. The problem is that you don't really "know" when we're "done" with any particular task ID, which means you don't know when it's "safe" to reuse that ID. These task IDs will never be user visible, so I'd just append a value to the string to force uniqueness.
Case in point on the "done" front:
What I would have expected is that the failure task is REPLACED with the new task and new progress. Instead what I see is TWO ContinuedBackgroundProcessingTasks, one in the failure state and one in progress.
The system isn't "done" tracking any particular task until it clears its UI, but that interface is managed independently of your app.
OR if that's not possible, how do I programmatically clear the task failure?
I think you're thinking about this the wrong way. If you don't want a task to be marked as "failed"... the solution is to "not" fail the task. Putting that another way, the "success" argument to "setTaskCompleted(success:)" is actually you telling the system what to do with the task you're completing, NOT communicating some higher level concept of what the task actually "did". As a more concrete example, if the user cancels a task in your app UI, you should pass in "success=true". The task may have "failed" but there's no reason to bother the user with "extra" UI for that.
I've tried cancelTask but that doesn't seem to clear it.
So, there are actually two issues here:
-
Task cancellation applies to tasks that are "scheduled", not tasks that are actively running. Tasks that are actively running can stop using setTaskCompleted(success:). In practice, that means it's really only useful with BGContinuedProcessingTask if you're using BGContinuedProcessingTaskRequest.SubmissionStrategy.queue and submitting enough tasks that they're actively queueing.
-
Task cancellation doesn't really apply to failed tasks, as they've already completed as far as the scheduling system is concerned. I can see why you might want to clear them, but I'm not sure how that would work in the current API.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware