6 Replies
      Latest reply: Feb 16, 2017 2:13 AM by iosmarkjim RSS
      joedaniels29 Level 1 Level 1 (0 points)

        NSBackgroundURLSession (watchOS) executes my ~2mb upload multiple (sometimes >100)  times before the task is returned to my app as completed. 

        it appears like the tasks retry the request even before getting a response back from the server.

        How can I tune  my NSURLSessionUploadTasks to only retry on the background session to not send so many retrys so quickly?

        • Re: Tune NSURLSessionUploadTask retry for NSBackgroundURLSession (watchOS) to limit number of requests.
          eskimo Apple Staff Apple Staff (6,065 points)

          The fact that it’s retrying would indicate that the client thinks the request has failed.  Do you know why it might think that?

          Share and Enjoy

          Quinn “The Eskimo!”
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"

            • Re: Tune NSURLSessionUploadTask retry for NSBackgroundURLSession (watchOS) to limit number of requests.
              joedaniels29 Level 1 Level 1 (0 points)

              Well, I know for sure that they're not actually failing, because they go through.

              defining success as getting a 2xx response code, and failure as not getting that,

               

              A couple guesses:

              — maybe there's something wrong with the headers of the response that makes the client presume failure?

              — Maybe the API isn't threadsafe? I'm doing this work from a background thread

              — This is a large payload of the Recorded accelerometer data in JSON format from the watch. (not ideal, but its a requirement right now). Its sent direct from the watch.

              i've got my session configured like so:

                   s.discretionary = NO;

                  s.HTTPMaximumConnectionsPerHost = 1;

                  s.timeoutIntervalForRequest = 60 * 4;

              perhaps nsurlsessiond  on watchOS relays the request to  the connected iphone and starts the countdown immediately, and doesnt get a response back from the iphone in `timeoutIntervalForRequest` seconds?

                • Re: Tune NSURLSessionUploadTask retry for NSBackgroundURLSession (watchOS) to limit number of requests.
                  eskimo Apple Staff Apple Staff (6,065 points)

                  Maybe the API isn't threadsafe? I'm doing this work from a background thread

                  That’s unlikely to be an issue.  NSURLSession is, in general, thread safe.

                  maybe there's something wrong with the headers of the response that makes the client presume failure?

                  It’s possible, but it doesn’t seem very likely.  In general NSURLSession only concerns itself with headers directly related to the transfer (things like Content-Length).  Any custom headers just get passed through to the app.

                  One thing you could do here is test the same code in a test iPhone app.  If there was something wrong with how the server handles the transfer, I’d expect that to affect your test iPhone app in the same way.  I recommend you run this test two ways:

                  • With a standard NSURLSession

                  • With a background NSURLSession, which handles requests in a manner very similar to those being proxied from the match

                  If you see problems in one test but not the other, that’d be a very useful data point.

                  This is a large payload …

                  How large?

                  It’s certainly possible that timeouts could be the issue.  The one obvious gotcha in this space relates to the time it takes for a server to ingest an upload.  The request timeout (as set by timeoutIntervalForRequest or by the timeoutInterval property on the NSURLRequest itself) is based on data being moved on the ‘wire’.  If the client finishes an upload and the server takes a long time to ingest that upload and sends its response, the request timeout can fire.

                  When you look at this traffic on the wire, how big a gap do you see between the client sending the last of the body and the server replying with the beginning of the response?

                  Talking about traffic on the wire, can you post an overview of how a typical ‘failed’ request (that is, one that ends up being retried) appears on the wire.  Something like:

                  1. At time X, the client opens the TCP connection

                  2. At time X + n1, the client starts sending the HTTP request header

                  3. At time X + n2, the client starts sending the HTTP request body

                  4. At time X + n3, the client has finished sending the HTTP body

                  5. At time X + n4, the server starts sending the HTTP response header

                  6. At time X + n5, the server starts sending the HTTP response body

                  7. At time X + n6, the server has finished sending the HTTP response body

                  Also, do you see different behaviour if the watch does the upload itself.  You can test this by turning off your phone, so the watch can’t proxy the request through the phone.

                  Share and Enjoy

                  Quinn “The Eskimo!”
                  Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                  let myEmail = "eskimo" + "1" + "@apple.com"

                    • Re: Tune NSURLSessionUploadTask retry for NSBackgroundURLSession (watchOS) to limit number of requests.
                      iosmarkjim Level 1 Level 1 (0 points)

                      Hi I'm having the same problem as OP and this post is the only one where I can kind of get an idea of what's happening.

                      Like OP, I'm using a backround NSURLSession to upload files and it keeps retrying on large file uploads. I've observed that this happens when I wait for more than 60 seconds for the server to send a response back after uploading my files.

                       

                      From what I understand in your post, I should change either timoutInterval (NSURLRequest) or timeoutIntervalForRequest (NSURLSessionConfiguration) to greater than 60 seconds or until the server finishes sending a response back to the client. But I've set my sesssion configuration timoutIntervalForRequest and timeoutInterval for NSURLRequest to greater than 60 seconds and the session is still trying the upload task multiple times. It seems like the background NSURLSession is ignoring the timeout setting I've set in both session configuration and the NSURLRequest level. To be clear the server is sending the correct response for every upload request, it's just that it's taking more than 60 seconds and the session is resending another upload request again.

                       

                      I'm not using watchOS and I've also observed the same behaviour in iOS 8, 9 and 10.