Is this problem related to specific iOS version?
How are you consuming the SDK? CocoaPods / Carthage / Prebuilt frameworks?
Cocoapods
Hello,
There is a serious issue when I upload data with the AWSS3TransferUtility. Since last week and I believe since the release of v.2.6.18 of aws-sdk, I have some failures in the uploading of data. Although all my data seem to be uploaded correctly as the completionHandler I have never returns an error:
transferUtility.uploadFile(URL(fileURLWithPath: datafile.path), bucket: bucket, key: key, contentType: contentType, expression: expression, completionHandler: self.completionBlockUpload).continueWith { (task) -> Any? in
if let error = task.error {
log.error("error in creating aws upload task", error: error)
}
if let uploadTask = task.result {
// Do something with uploadTask.
log.debug("aws upload task created successfully: \(uploadTask.sessionTask.currentRequest)")
}
return nil
}
completionBlockUpload = { (task, error) -> Void in
//Check for error or success
}
As you can see here, this is the way I give transferUtility the necessary data to upload a file. When I search in S3 after a while to find my files, some of them are not there despite the fact that the completionBlockUpload returns always the task and never the error.
Do you have any proposal on that?
hello @nick3389
Sorry to hear that you are having issues. I will look into this and get back to you.
@cbommas thank you very much! It is a very serious issue, as we lose data from a production application.
@cbommas Is it possible that this pull request caused this problem?
https://github.com/aws/aws-sdk-ios/pull/666/commits/344aa6567f4ad781b492eca08fb86ceb02c1bbae
Should we check now for the data too?? It is very curious as the error is nil in my case...
hello @nick3389
I looked into this and could not find any regression in the tests I ran to verify the functionality - I am seeing the callbacks being called as normal. The PR you are referencing adds additional diagnostics in case of errors, but it hasn't cause any regression that I could find.
If you could provide the following info, it would be very helpful in debugging further
1) a code snippet that shows your error handling
2) confirm that the callback is being called for every request you are making
3) when you say, there were some failures, are these missing files? corrupted files? or updates that did not go through? further information on this would be good.
4) Also, confirm if you are seeing this behavior only in the latest version ( A good experiment to make would be to try the previous version of the SDK to check )
@cbommas
completionBlockUpload = { (task, error) -> Void in
if let error = error {
//do nothing and retry later to upload the file
} else {
//delete file
}
}
So imagine that I never get an error, the code goes into the else clause and I delete the file.
Yes it is called every time because I have setup logging and I see every result of an upload as I log a unique identifier for each request, so it is called 100%
The "failure" is that I expect to see my uploaded file in the S3 bucket but it isn't there. It's like the sdk telling me that the file has been uploaded but it hasn't. It's really really strange.
Yes I see this behaviour only in 2.6.18. I downgraded to 2.6.17 since Monday and the problem is gone. Also, bear in mind that this particular group of code I use, has remained the same for almost a year now without any such problem. And it happens to all the devices I tested it. The frequency of missing files is very frequent if I use v.2.6.18
@nick3389
I am continuing to dig into this. The 2 big changes in the 2.6.18 in the transfer utility were improved memory handling for multi-part transfers and improvements to general error handling.
One question: are you using multi-part transfers? Can you check if the errors are isolated to multi-part transfers (if you are using them?). This will help in my debugging.
@nick3389
I am pretty confident that I have found the problem. There is indeed a regression in 2.6.18, due to the improved error handling logic. The fix will be included in the next rev of the SDK.
If you need this fix before the next rev, here is what you would need to change locally.
On line 1619, add
uploadTask.error = error
On line 1766, add
downloadTask.error = error
If your current setup enables you to do this, I would appreciate it if you could try and let me know if it fixes the issue.
@cbommas I do not use multi-part transfers. I will try the fix you suggested in v.2.6.18 and I will get back after 3-4 days, so I have tested it a while. Really great if this works out.
@cbommas The fix seems to work. No missing file since I tried it.
@nick3389
Thank you for confirming.
@cbommas Any updates on the fix making it to a patch release?
@codebender
The fix has been completed and will be included in the next rev of the SDK, which will be released in the next few days. I will update this thread once the new release is out.
Hello @nick3389, @codebender,
The latest version of the SDK, 2.6.20 released on 6/1/2018, contains this fix. Please try it out and let me know how it goes.
@nick3389 hello, has this fixed your issue? thanks
@pablogeek Hi Pablo, yes it is fixed after the update in the sdk.
@cbommas my completion handler is not being called in AWSS3TransferUtility.uploadFile(). I am testing things in bad network condition.
@commando24 Can you move your question to a new issue so we can track it separately? That helps keep conversations more targeted, and makes it easier for future developers to search and find the answers they need.
Be sure to include all the requested information in the issue template (SDK version, iOS version, etc) as well as repro steps and if possible, a code snippet, to help us diagnose the problem.
@commando24 was that fixed?
@nick3389
I have solved this issue by removing return; statement from AWSS3TransferUtility.m file in following method:
#pragma mark - NSURLSessionTaskDelegate
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error {
...
//Check if the task was cancelled.
if (transferUtilityMultiPartUploadTask.cancelled) {
//Abort the request, so the server can clean up any partials.
[self callAbortMultiPartForUploadTask:transferUtilityMultiPartUploadTask];
//Add it to list of completed Tasks
[self.completedTaskDictionary setObject:transferUtilityMultiPartUploadTask forKey:transferUtilityMultiPartUploadTask.transferID];
//Clean up.
[self cleanupForMultiPartUploadTask:transferUtilityMultiPartUploadTask];
// return;
}
...
}
The return statement after Clean up were terminating the process of error handling and callback even if the Task consists an error.
Most helpful comment
@codebender
The fix has been completed and will be included in the next rev of the SDK, which will be released in the next few days. I will update this thread once the new release is out.