multiPartUploadProgress and multiPartUploadCompleted blocks are not called when resuming multipartUploadTasks in iOS 18
zamzamfp opened this issue · 7 comments
Describe the bug
We have implemented the suggested solution for resuming uploads from this GitHub comment, by calling transferUtility.enumerateToAssign(blocks: blocks)
and it was working fine. There was a delay, as mentioned in this issue, but the progress and completion callbacks were being called successfully on iOS 17.5.1 using Xcode 15.4.
However, since upgrading to iOS 18 (and also in iOS 17.6.1), I’ve noticed a problem. Although the upload resumes and completes as expected—seeing it in the debug logs and also confirming its upload on the S3 bucket—the progress and completion blocks are not triggered. This means that there’s no way to update the UI with upload progress or completion status. This is a big problem for us as we are uploading large files around 10GB, so we rely on being able to resume uploads in case the app was terminated.
To Reproduce
Steps to reproduce the behavior:
- Start a multipartUpload
- terminate the app while uploading
- open the app again
Observed Behavior
The upload does continue, and successfully finishes, but the multiPartUploadProgress and multiPartUploadCompleted blocks are not getting triggered.
Expected Behavior
Getting call back in multiPartUploadProgress and multiPartUploadCompleted blocks
Code Snippet
we are initiating transferUtility with a unique key transferUtility= AWSS3TransferUtility.s3TransferUtility(forKey: )
let blocks = AWSS3TransferUtilityBlocks(uploadProgress: nil,
multiPartUploadProgress: {(task, progress) in
print("upload task progress \(progress)")
},
downloadProgress: nil,
uploadCompleted: nil,
multiPartUploadCompleted: { (task, error) -> Void in
if let error {
print("upload task failed \(error)")
} else {
print("upload task completed")
}
},
downloadCompleted: nil)
transferUtility.enumerateToAssign(blocks: blocks)
Areas of the SDK you are using (AWSMobileClient, Cognito, Pinpoint, IoT, etc)?
S3
transferUtility
uploadUsingMultiPart
enumerateToAssign
Environment(please complete the following information):
- SDK Version: latest 2.37.1
- Dependency Manager: SwiftPackage
- Xcode Version: 15.4 and also 16
Device Information (please complete the following information):
- iOS Version: 18.0
Relevant Console Output
Note that all the tests was done on a real device.
Where the resume is successfully triggering the logs are
Found MultiPartUpload [873F5AE6-8D14-4D0D-881F-9302F2ACF9B4] with Multipart ID [fKnjKPRgvMtf6uzZs5GOZMRWz4bZfh_DDuhGSZH2xaUxYSbETH7l_K8PKRSS4FrMtKIQynEa.LWhx5Ecumw2Hmbfdp7L2TTJmeaYWV0WeATyBdc2lPA5rbhku0ayRMN_1kib1Atqu.H7hxFXpxcvFdq_aYuOibyYYLv2heh9aEg-] and status [1]
Found MultiPartUpload SubTask [873F5AE6-8D14-4D0D-881F-9302F2ACF9B4] with taskNumber [1] and status [1]
Found MultiPartUpload SubTask [873F5AE6-8D14-4D0D-881F-9302F2ACF9B4] with taskNumber [2] and status [3]
...
Iterating through task Identifier [9]
Iterating through task Identifier [5]
Iterating through task Identifier [1]
....
Moving Task[13] to progress for Multipart[fKnjKPRgvMtf6uzZs5GOZMRWz4bZfh_DDuhGSZH2xaUxYSbETH7l_K8PKRSS4FrMtKIQynEa.LWhx5Ecumw2Hmbfdp7L2TTJmeaYWV0WeATyBdc2lPA5rbhku0ayRMN_1kib1Atqu.H7hxFXpxcvFdq_aYuOibyYYLv2heh9aEg-]
Moving Task[18] to progress for Multipart[fKnjKPRgvMtf6uzZs5GOZMRWz4bZfh_DDuhGSZH2xaUxYSbETH7l_K8PKRSS4FrMtKIQynEa.LWhx5Ecumw2Hmbfdp7L2TTJmeaYWV0WeATyBdc2lPA5rbhku0ayRMN_1kib1Atqu.H7hxFXpxcvFdq_aYuOibyYYLv2heh9aEg-]
Moving Task[14] to progress for Multipart[fKnjKPRgvMtf6uzZs5GOZMRWz4bZfh_DDuhGSZH2xaUxYSbETH7l_K8PKRSS4FrMtKIQynEa.LWhx5Ecumw2Hmbfdp7L2TTJmeaYWV0WeATyBdc2lPA5rbhku0ayRMN_1kib1Atqu.H7hxFXpxcvFdq_aYuOibyYYLv2heh9aEg-]
...
Subtask for multipart upload is suspended: 21
Subtask for multipart upload is suspended: 17
Thread:<NSThread: 0x303ba78c0>{number = 9, name = (null)}: didCompleteWithError called for task 5
Unable to find information for task 5 in taskDictionary
Transfer Utility Task not found in taskDictionary ( 5)
Thread:<NSThread: 0x303ba78c0>{number = 9, name = (null)}: didCompleteWithError called for task 1
...
Total 54297248, ProgressSoFar 6291456
upload task progress in reattachHandlers ### <NSProgress: 0x3000a8180> : Parent: 0x0 (portion: 0) / Fraction completed: 0.1352 / Completed: 7340032 of 54297248
Total 54297248, ProgressSoFar 7340032
Total 54297248, ProgressSoFar 8388608
Total 54297248, ProgressSoFar 9437184
Total 54297248, ProgressSoFar 10485760
/// From my print
upload task progress ### <NSProgress: 0x3000a8180> : Parent: 0x0 (portion: 0) / Fraction completed: 0.1931 / Completed: 10485760 of 54297248
upload task progress ### <NSProgress: 0x3000a8180> : Parent: 0x0 (portion: 0) / Fraction completed: 0.1931 / Completed: 10485760 of 54297248
....
Completed Multipart Transfer: fKnjKPRgvMtf6uzZs5GOZMRWz4bZfh_DDuhGSZH2xaUxYSbETH7l_K8PKRSS4FrMtKIQynEa.LWhx5Ecumw2Hmbfdp7L2TTJmeaYWV0WeATyBdc2lPA5rbhku0ayRMN_1kib1Atqu.H7hxFXpxcvFdq_aYuOibyYYLv2heh9aEg-
// From my print
upload task completed
When running the same code on and iOS 18.0 device and the call backs are not triggered
Found MultiPartUpload SubTask [2284AB91-6249-4E3C-AD7C-47AF841A329C] with taskNumber [3] and status [3]
Found MultiPartUpload SubTask [2284AB91-6249-4E3C-AD7C-47AF841A329C] with taskNumber [4] and status [3]
Found MultiPartUpload SubTask [2284AB91-6249-4E3C-AD7C-47AF841A329C] with taskNumber [5] and status [3]
Found MultiPartUpload SubTask [2284AB91-6249-4E3C-AD7C-47AF841A329C] with taskNumber [6] and status [3]
Found MultiPartUpload SubTask [2284AB91-6249-4E3C-AD7C-47AF841A329C] with taskNumber [7] and status [3]
...
Found MultiPartUpload SubTask [2284AB91-6249-4E3C-AD7C-47AF841A329C] with taskNumber [13] and status [3]
Transfer Utility Task not found in taskDictionary ( 1)
Found MultiPartUpload SubTask [2284AB91-6249-4E3C-AD7C-47AF841A329C] with taskNumber [14] and status [3]
Found MultiPartUpload SubTask [2284AB91-6249-4E3C-AD7C-47AF841A329C] with taskNumber [15] and status [3]
Found MultiPartUpload SubTask [2284AB91-6249-4E3C-AD7C-47AF841A329C] with taskNumber [16] and status [3]
Found MultiPartUpload SubTask [2284AB91-6249-4E3C-AD7C-47AF841A329C] with taskNumber [17] and status [3]
...
Completed Multipart Transfer: yWSNDwkhDHEQv088LVp2ZhgcljP_JpHXtIq4736R7wPZdK7LTEL7MXgKBKDwSkxf2vz3XVgaxy3cE8aSeemBKdBDwyhSUa.wfkyvy000yAEUhnuzNO6rMnRog3upJu0IOPiTDOJLj.TtHwX6fpye7b.2jPTZk9GgWSi4MRChNhs-
So everything seems to be the same and the upload does finish successfully but the progress and completion blocks are not getting triggered.
@zamzamfp Thanks for submitting the issue. We'll work on reproducing it and investigate further.
Hi @phantumcode, any updates on this would be much appreciated.
Hi @zamzamfp, sorry for the delay in our response.
I was able to reproduce this issue. What's happening is that the Transfer Utility is attempting to assign the callbacks before it has finished (or even started) recovering and linking the old upload tasks, so they are ignored.
In order to fix this, you should call AWSS3TransferUtility.enumerateToAssign(blocks:)
only after the Transfer Utility has finished setting everything up. You mentioned you're using a unique key, so that means you have a AWSS3TransferUtility.register(with:forKey:)
invocation in your application.
You can also provide a completionHandler
to this method, which will be invoked once the Utility is ready and all the tasks are linked. So for example, you could do something like this:
let transferUtilityKey = //...
AWSS3TransferUtility.register(
with: configuration,
forKey: transferUtilityKey
) { _ in
guard let transferUtility = AWSS3TransferUtility.s3TransferUtility(forKey: transferUtilityKey) else {
print("Unable to register Transfer Utility")
return
}
let blocks = AWSS3TransferUtilityBlocks(
// ...
)
transferUtility.enumerateToAssign(blocks: blocks)
}
As a side note, I observed the same behaviour when running on an iOS 17.5 simulator as well, so it's not an iOS 18 specific issue. I guess it really depends on how fast the device is and where in your app life cycle you're actually calling AWSS3TransferUtility.enumerateToAssign(blocks:)
.
But regardless, the best practice would be to call it from the completionHandler
block as shown above.
Good to know that this works for you now :)
Regarding Amplify Storage, you can manually pause and resume tasks, if that's what you're asking. See our documentation for upload tasks and download tasks.