NSURLSessionDataTask timeout subsequent requests failing
Asked Answered
B

4

11

I am creating a NSMutableRequest:

self.req = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10.0];

The timeout is set to be 10 seconds because I don't want the user to wait too long to get a feedback. After that I create a NSURLSessionDataTask:

NSURLSessionDataTask *task = [self.session dataTaskWithRequest:self.req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    NSHTTPURLResponse * httpResp = (NSHTTPURLResponse *)response;
    if (error) {
        // this is where I get the timeout
    } 
    else if (httpResp.statusCode < 200 || httpResp.statusCode >= 300) {
        // handling error and giving feedback
    } 
    else {
        NSError *serializationError = nil;
        NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&serializationError];
    }
    [task resume];
}

The problem is the server goes into Gateway Timeout and it takes a lot of time. I get the timeout error and I give a feedback to the user, but all the following API calls fail in the same way due to timeout error. The only way to stop it is to kill the app and start over. Is there something I should do to kill the task or the connection after a timeout error? If I don't set a timeout and I wait until I receive the error code from the server all the following calls work perfectly (But the user waits a lot!).

I tried to cancel the task:

NSURLSessionDataTask *task = [self.session dataTaskWithRequest:self.req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    NSHTTPURLResponse * httpResp = (NSHTTPURLResponse *)response;
    if (error) {
        // this is where I get the timeout
        [task cancel];
    } 
    ...
    [task resume];
}
Branham answered 15/7, 2015 at 10:30 Comment(4)
I guess, you might require to re-initialize the self.req if there is an error/timeout. Not sure about this though.Ganges
try calling the connections with POSTMAN app in chrome,and see if you still get the timeout error or notCluck
Are you Creating this task inside some block? Or some other thread, other than main thread?Gaona
@nicky Were you able to figure out the solution. Running into same situation . I get the server timeout error and enqueue all the requests and replay it but it always fails.Ptolemaeus
C
5

I didnt see you resume the task you started. You need to declare:

[task resume];

This line Resumes the task, if it is suspended.

Try to call the NSURLSession as follows:

[NSURLSession sharedSessison] instead of self.session

and invalidate the session by:

 [[NSURLSession sharedSession]invalidateAndCancel];

From Apple's Documentation:

When your app no longer needs a session, invalidate it by calling either invalidateAndCancel (to cancel outstanding tasks) or finishTasksAndInvalidate (to allow outstanding tasks to finish before invalidating the object).

    - (void)invalidateAndCancel

Once invalidated, references to the delegate and callback objects are broken. Session objects cannot be reused.

To allow outstanding tasks to run until completion, call finishTasksAndInvalidate instead.

  - (void)finishTasksAndInvalidate

This method returns immediately without waiting for tasks to finish. Once a session is invalidated, new tasks cannot be created in the session, but existing tasks continue until completion. After the last task finishes and the session makes the last delegate call, references to the delegate and callback objects are broken. Session objects cannot be reused.

To cancel all outstanding tasks, call invalidateAndCancel instead.

Cluck answered 15/7, 2015 at 13:5 Comment(2)
Yes, I forgot the resume here in the question. I am going to edit it. And the only method I can call on the task to invalidate it, is "cancel". I can't see the others. I tried but it doesn't solve the issue. ThanksBranham
how u r calling the cancel?Cluck
L
1

The problem that you are most probably encountering here is that your task is not cancelling or completing and is hence holding the session from accepting any more tasks. As per Apple's documentation

After you create a task, you start it by calling its resume method. The session then maintains a strong reference to the task until the request finishes or fails;

As T_77 suggested, try using [NSURLSession sharedSession]

Also one more thing I would try to do at this point of time is trying to find out if there is a retain cycle created between the session object and the task, using Instruments

One more thing that could be happening is that the request is not properly formed and is not executing or is hung. I had faced a similar issue once when I tried to load a URL onto a web view. The page was not loading and not throwing an error. Try verifying the url request also once.

Thanks, Suraj

Lorrianelorrie answered 24/7, 2015 at 10:42 Comment(0)
D
0

The most likely cause for a timeout is either that DNS resolved to an IP address that didn't exist, or that the server has crashed and needs rebooting. In any case, if one request fails with timeout, more requests are reasonably likely to fail with timeout as well.

You obviously need to write your application in such a way that it can survive when it's servers don't reply.

Delgado answered 17/7, 2015 at 15:1 Comment(1)
If I set the timeout to be 60 instead of 10 secs I get the "Gateway timeout" from the server and all the request I do after that works perfectly. The problem is when the timeout occurs before the answer from the server. All the following requests fail until I kill the app.Branham
E
0

You may set timeout in different way like following code

NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfiguration.timeoutIntervalForRequest = timeout;
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:nil delegateQueue:nil];
Effectuate answered 24/7, 2015 at 9:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.