0

I have a highly asynchronous environment and many modules which may request a particular network resource (such as an access token and perhaps indirectly through transitive requests).

For instance many places in code could "simultaneously" do calls to send analytics:

// module 1
[Analytics sendAnalytics:module1Analytics];


// module 2
[Analytics sendAnalytics:module2Analytics];

...

Analytics requests require a valid access token and the sending code may contain special care for an expired access token that should be renewed

+(void)sendAnalaytics:(Analytics)analyticsPayload {
    //... setup code ...
    NSURLRequest *analyticsRequest = // Analytics NSURLRequest with a special access token
    // the network request to send the analytics
    [[MyNSURLSession dataTaskWithRequest:analyticsRequest completionHandler:^(NSData * __nullable data, NSURLResponse * __nullable response, NSError * __nullable error)){
       if (error == 401) {
          get new access token
          // re-send the same request
          [self sendAnalaytics:analyticsPayload];
       }
       // ....
}] resume];
}

I don't want to request the same resource simultaneously. I want to batch the call for the same resource if it is already running.

// batch this call to only happen once if already running
   NSURLRequest *accesstoken = ...
   ....

Also the access token should never be cached (using the "NSURLCache" et.al mechanisms. )

There are other request such as the "access token" request which should be batched together (for instance a request for an image). I need to optimize the network access so that I am not doing redundant requests.

Is there a builtin mechanism supplied by the NSURL loading system without resorting to collecting the requests myself?

Avba
  • 14,822
  • 20
  • 92
  • 192

1 Answers1

0

No. You'd have to add your own wrapper code around NSURLSession to do that.

You should probably have an analytics singleton class that handles merging multiple requests where needed, retries, etc. so that all the caller has to do is [MyAnalyticsClass updateAnalyticsWithParameters: @{...}] or whatever.

Then, in that call, you should check to see if there's a request in progress. If not, start the request immediately. If so, enqueue the new request. When the current request completes, look through the queue and decide which ones to send, which ones to merge, etc. and start the next one.

dgatwood
  • 10,129
  • 1
  • 28
  • 49