Skip to content

Commit d9b2896

Browse files
Alda/backoff retry fix (#180)
* Add backoff retry for http requests with invalid status code (i.e., >= 400). * Added datafile download tests when backoff retry is enabled via status code 400 and internal error. * Added tests for event dispatch with backoff retry triggered by internal error and status code 400. * Removed status code 400 backoff retry test for datafile manager and event dispatcher. This is a little redundant and takes a lot of time. Also bumped up the timeout for the backoff retry tests. * Fixed event error check in get all events -- this was causing an exception to be thrown. * Decreased retries. A total of three tries should suffice. * Use a strong reference to self since we are doing a recursive call and the referencing object (the network service manager) does not necessary have a strong reference to the HTTPRequestManager. This was causing the recursion to not complete and, the call back for the datafile download and event dispatch during a backoff retry never returned the callback. * Bumped the wait time for the event dispatcher backoff retry. * Removed the strong reference for the http request manager blocks. Resolved the recursion failure by added url parameters to the http request request manager so that the network service can create and own the object. Fixed the corresponding tests for the http request manager. * Fixed the event data store error chck. * Changed the network service to own the http request manager. * Cleaned up the datafile manager tests. * Improved logic for response and error checks for backoff retry per Kelly's suggestion.
1 parent 57bbdb7 commit d9b2896

File tree

7 files changed

+244
-156
lines changed

7 files changed

+244
-156
lines changed

OptimizelySDKCore/OptimizelySDKCore/OPTLYHTTPRequestManager.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,46 +26,49 @@ typedef void (^OPTLYHTTPRequestManagerResponse)(NSData * _Nullable data, NSURLRe
2626

2727
@interface OPTLYHTTPRequestManager : NSObject
2828

29-
@property (nonatomic, strong, nonnull) NSURL *url;
30-
31-
/// Network service must be initialized with a URL
32-
- (nullable id)initWithURL:(nonnull NSURL *)url;
33-
3429
/**
3530
* GET data from the URL inititialized
3631
*
32+
* @param url The url to make the GET request.
3733
* @param completion The completion block of type OPTLYHTTPRequestManagerResponse
3834
*/
39-
- (void)GETWithCompletion:(nullable OPTLYHTTPRequestManagerResponse)completion;
35+
- (void)GETWithURL:(nonnull NSURL *)url
36+
completion:(nullable OPTLYHTTPRequestManagerResponse)completion;
4037

4138
/**
4239
* GET data from the URL inititialized with the option of doing an exponential backoff and retry
4340
*
41+
* @param url The url to make the GET request.
4442
* @param backoffRetryInterval The backoff retry time interval for the exponential backoff (in ms)
4543
* @param retries The total number of backoff retry attempts
4644
* @param completion The completion block of type OPTLYHTTPRequestManagerResponse
4745
*/
4846
- (void)GETWithBackoffRetryInterval:(NSInteger)backoffRetryInterval
47+
url:(nonnull NSURL *)url
4948
retries:(NSInteger)retries
5049
completionHandler:(nullable OPTLYHTTPRequestManagerResponse)completion;
5150
/**
5251
* GET data with parameters
5352
*
53+
* @param url The url to make the GET request.
5454
* @param parameters Dictionary of GET request parameter values
5555
* @param completion The completion block of type OPTLYHTTPRequestManagerResponse
5656
*/
5757
- (void)GETWithParameters:(nullable NSDictionary *)parameters
58+
url:(nonnull NSURL *)url
5859
completionHandler:(nullable OPTLYHTTPRequestManagerResponse)completion;
5960

6061
/**
6162
* GET data with parameters with the option of doing an exponential backoff and retry
6263
*
64+
* @param url The url to make the GET request.
6365
* @param parameters Dictionary of GET request parameter values
6466
* @param backoffRetryInterval The backoff retry time interval the exponential backoff (in ms)
6567
* @param retries The total number of backoff retry attempts
6668
* @param completion The completion block of type OPTLYHTTPRequestManagerResponse
6769
*/
6870
- (void)GETWithParameters:(nullable NSDictionary *)parameters
71+
url:(nonnull NSURL *)url
6972
backoffRetryInterval:(NSInteger)backoffRetryInterval
7073
retries:(NSInteger)retries
7174
completionHandler:(nullable OPTLYHTTPRequestManagerResponse)completion;
@@ -76,10 +79,12 @@ typedef void (^OPTLYHTTPRequestManagerResponse)(NSData * _Nullable data, NSURLRe
7679
* "If-Modified-Since" field, an entity will not be returned from the server; instead,
7780
* a 304 (not modified) response will be returned without any message-body.
7881
*
82+
* @param url The url to make the GET request.
7983
* @param lastModifiedDate - The date since the URL request was last modified
8084
* @param completion - The completion block of type OPTLYHTTPRequestManagerResponse
8185
*/
8286
- (void)GETIfModifiedSince:(nonnull NSString *)lastModifiedDate
87+
url:(nonnull NSURL *)url
8388
completionHandler:(nullable OPTLYHTTPRequestManagerResponse)completion;
8489

8590
/**
@@ -88,34 +93,40 @@ typedef void (^OPTLYHTTPRequestManagerResponse)(NSData * _Nullable data, NSURLRe
8893
* "If-Modified-Since" field, an entity will not be returned from the server; instead,
8994
* a 304 (not modified) response will be returned without any message-body.
9095
*
96+
* @param url The url to make the GET request.
9197
* @param lastModifiedDate The date since the URL request was last modified
9298
* @param backoffRetryInterval The backoff retry time interval the exponential backoff (in ms)
9399
* @param retries The total number of backoff retry attempts
94100
* @param completion The completion block of type OPTLYHTTPRequestManagerResponse
95101
*/
96102
- (void)GETIfModifiedSince:(nonnull NSString *)lastModifiedDate
103+
url:(nonnull NSURL *)url
97104
backoffRetryInterval:(NSInteger)backoffRetryInterval
98105
retries:(NSInteger)retries
99106
completionHandler:(nullable OPTLYHTTPRequestManagerResponse)completion;
100107

101108
/**
102109
* POST data with parameters
103110
*
111+
* @param url The url to make the POST request.
104112
* @param parameters Dictionary of POST request parameter values
105113
* @param completion The completion block of type OPTLYHTTPRequestManagerResponse
106114
*/
107115
- (void)POSTWithParameters:(nonnull NSDictionary *)parameters
116+
url:(nonnull NSURL *)url
108117
completionHandler:(nullable OPTLYHTTPRequestManagerResponse)completion;
109118

110119
/**
111120
* POST data with parameters with an exponential backoff and retry attempt
112121
*
122+
* @param url The url to make the POST request.
113123
* @param parameters Dictionary of POST request parameter values
114124
* @param backoffRetryInterval The backoff retry time interval the exponential backoff (in ms)
115125
* @param retries The total number of backoff retry attempts
116126
* @param completion The completion block of type OPTLYHTTPRequestManagerResponse
117127
*/
118128
- (void)POSTWithParameters:(nonnull NSDictionary *)parameters
129+
url:(nonnull NSURL *)url
119130
backoffRetryInterval:(NSInteger)backoffRetryInterval
120131
retries:(NSInteger)retries
121132
completionHandler:(nullable OPTLYHTTPRequestManagerResponse)completion;

OptimizelySDKCore/OptimizelySDKCore/OPTLYHTTPRequestManager.m

Lines changed: 89 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,6 @@ - (id)init
4242
return self;
4343
}
4444

45-
- (id)initWithURL:(NSURL *)url
46-
{
47-
if (self = [super init]) {
48-
_url = url;
49-
}
50-
return self;
51-
}
52-
5345
// Create global serial GCD queue for NSURL tasks
5446
dispatch_queue_t networkTasksQueue()
5547
{
@@ -62,29 +54,33 @@ dispatch_queue_t networkTasksQueue()
6254
}
6355

6456
# pragma mark - GET
65-
- (void)GETWithCompletion:(OPTLYHTTPRequestManagerResponse)completion {
66-
[self GETWithParameters:nil completionHandler:completion];
57+
- (void)GETWithURL:(NSURL *)url
58+
completion:(OPTLYHTTPRequestManagerResponse)completion {
59+
[self GETWithParameters:nil url:url completionHandler:completion];
6760
}
6861

6962
- (void)GETWithBackoffRetryInterval:(NSInteger)backoffRetryInterval
63+
url:(NSURL *)url
7064
retries:(NSInteger)retries
7165
completionHandler:(OPTLYHTTPRequestManagerResponse)completion
7266
{
7367
// TODO: Wrap this in a TEST preprocessor definition
7468
self.delaysTest = [NSMutableArray new];
7569

7670
[self GETWithParameters:nil
71+
url:url
7772
backoffRetryInterval:backoffRetryInterval
7873
retries:retries
7974
completionHandler:completion];
8075
}
8176

8277
# pragma mark - GET (with parameters)
8378
- (void)GETWithParameters:(NSDictionary *)parameters
79+
url:(NSURL *)url
8480
completionHandler:(OPTLYHTTPRequestManagerResponse)completion
8581
{
8682
NSURLSession *ephemeralSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration]];
87-
NSURL *urlWithParameterQuery = [self buildQueryURL:self.url withParameters:parameters];
83+
NSURL *urlWithParameterQuery = [self buildQueryURL:url withParameters:parameters];
8884
NSURLSessionDataTask *downloadTask = [ephemeralSession dataTaskWithURL:urlWithParameterQuery
8985
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
9086
if (completion) {
@@ -96,6 +92,7 @@ - (void)GETWithParameters:(NSDictionary *)parameters
9692
}
9793

9894
- (void)GETWithParameters:(NSDictionary *)parameters
95+
url:(NSURL *)url
9996
backoffRetryInterval:(NSInteger)backoffRetryInterval
10097
retries:(NSInteger)retries
10198
completionHandler:(OPTLYHTTPRequestManagerResponse)completion
@@ -104,6 +101,7 @@ - (void)GETWithParameters:(NSDictionary *)parameters
104101
self.delaysTest = [NSMutableArray new];
105102

106103
[self GETWithParameters:parameters
104+
url:url
107105
backoffRetryInterval:backoffRetryInterval
108106
retries:retries
109107
completionHandler:completion
@@ -112,6 +110,7 @@ - (void)GETWithParameters:(NSDictionary *)parameters
112110
}
113111

114112
- (void)GETWithParameters:(NSDictionary *)parameters
113+
url:(NSURL *)url
115114
backoffRetryInterval:(NSInteger)backoffRetryInterval
116115
retries:(NSInteger)retries
117116
completionHandler:(OPTLYHTTPRequestManagerResponse)completion
@@ -141,32 +140,36 @@ - (void)GETWithParameters:(NSDictionary *)parameters
141140
}
142141

143142
__weak typeof(self) weakSelf = self;
144-
[self GETWithParameters:parameters completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
145-
if (error) {
146-
dispatch_time_t delayTime = [weakSelf backoffDelay:backoffRetryAttempt
147-
backoffRetryInterval:backoffRetryInterval];
148-
dispatch_after(delayTime, networkTasksQueue(), ^(void){
149-
150-
[weakSelf GETWithParameters:parameters
151-
backoffRetryInterval:backoffRetryInterval
152-
retries:retries
153-
completionHandler:completion
154-
backoffRetryAttempt:backoffRetryAttempt+1
155-
error:error];
156-
});
157-
} else {
158-
if (completion) {
159-
completion(data, response, error);
160-
}
161-
}
162-
}];
143+
[self GETWithParameters:parameters
144+
url:url
145+
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
146+
if (error) {
147+
dispatch_time_t delayTime = [weakSelf backoffDelay:backoffRetryAttempt
148+
backoffRetryInterval:backoffRetryInterval];
149+
dispatch_after(delayTime, networkTasksQueue(), ^(void){
150+
151+
[weakSelf GETWithParameters:parameters
152+
url:url
153+
backoffRetryInterval:backoffRetryInterval
154+
retries:retries
155+
completionHandler:completion
156+
backoffRetryAttempt:backoffRetryAttempt+1
157+
error:error];
158+
});
159+
} else {
160+
if (completion) {
161+
completion(data, response, error);
162+
}
163+
}
164+
}];
163165
}
164166

165167
# pragma mark - GET (if modified)
166168
- (void)GETIfModifiedSince:(NSString *)lastModifiedDate
169+
url:(NSURL *)url
167170
completionHandler:(OPTLYHTTPRequestManagerResponse)completion
168171
{
169-
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[self url]];
172+
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
170173
[request setValue:lastModifiedDate forHTTPHeaderField:@"If-Modified-Since"];
171174

172175
NSURLSession *ephemeralSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration]];
@@ -180,6 +183,7 @@ - (void)GETIfModifiedSince:(NSString *)lastModifiedDate
180183
}
181184

182185
- (void)GETIfModifiedSince:(NSString *)lastModifiedDate
186+
url:(NSURL *)url
183187
backoffRetryInterval:(NSInteger)backoffRetryInterval
184188
retries:(NSInteger)retries
185189
completionHandler:(OPTLYHTTPRequestManagerResponse)completion
@@ -188,6 +192,7 @@ - (void)GETIfModifiedSince:(NSString *)lastModifiedDate
188192
self.delaysTest = [NSMutableArray new];
189193

190194
[self GETIfModifiedSince:lastModifiedDate
195+
url:url
191196
backoffRetryInterval:backoffRetryInterval
192197
retries:retries
193198
completionHandler:completion
@@ -196,6 +201,7 @@ - (void)GETIfModifiedSince:(NSString *)lastModifiedDate
196201
}
197202

198203
- (void)GETIfModifiedSince:(NSString *)lastModifiedDate
204+
url:(NSURL *)url
199205
backoffRetryInterval:(NSInteger)backoffRetryInterval
200206
retries:(NSInteger)retries
201207
completionHandler:(OPTLYHTTPRequestManagerResponse)completion
@@ -224,33 +230,42 @@ - (void)GETIfModifiedSince:(NSString *)lastModifiedDate
224230
}
225231

226232
__weak typeof(self) weakSelf = self;
227-
[self GETIfModifiedSince:lastModifiedDate completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
228-
if (error) {
229-
dispatch_time_t delayTime = [weakSelf backoffDelay:backoffRetryAttempt
230-
backoffRetryInterval:backoffRetryInterval];
231-
dispatch_after(delayTime, networkTasksQueue(), ^(void){
232-
[weakSelf GETIfModifiedSince:lastModifiedDate
233-
backoffRetryInterval:backoffRetryInterval
234-
retries:retries
235-
completionHandler:completion
236-
backoffRetryAttempt:backoffRetryAttempt+1
237-
error:error];
238-
});
239-
} else {
240-
if (completion) {
241-
completion(data, response, error);
242-
}
243-
}
244-
}];
233+
[self GETIfModifiedSince:lastModifiedDate
234+
url:url
235+
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
236+
NSInteger statusCode = 503;
237+
if (response != nil && error == nil) {
238+
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
239+
statusCode = (long)[httpResponse statusCode];
240+
}
241+
if (error != nil || statusCode >= 400) {
242+
dispatch_time_t delayTime = [weakSelf backoffDelay:backoffRetryAttempt
243+
backoffRetryInterval:backoffRetryInterval];
244+
dispatch_after(delayTime, networkTasksQueue(), ^(void){
245+
[weakSelf GETIfModifiedSince:lastModifiedDate
246+
url:url
247+
backoffRetryInterval:backoffRetryInterval
248+
retries:retries
249+
completionHandler:completion
250+
backoffRetryAttempt:backoffRetryAttempt+1
251+
error:error];
252+
});
253+
} else {
254+
if (completion) {
255+
completion(data, response, error);
256+
}
257+
}
258+
}];
245259
}
246260

247261

248262
# pragma mark - POST
249263
- (void)POSTWithParameters:(NSDictionary *)parameters
264+
url:(NSURL *)url
250265
completionHandler:(OPTLYHTTPRequestManagerResponse)completion
251266
{
252267
NSURLSession *ephemeralSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration]];
253-
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[self url]];
268+
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
254269
[request setHTTPMethod:kHTTPRequestMethodPost];
255270

256271
NSError *JSONSerializationError = nil;
@@ -277,6 +292,7 @@ - (void)POSTWithParameters:(NSDictionary *)parameters
277292
}
278293

279294
- (void)POSTWithParameters:(nonnull NSDictionary *)parameters
295+
url:(NSURL *)url
280296
backoffRetryInterval:(NSInteger)backoffRetryInterval
281297
retries:(NSInteger)retries
282298
completionHandler:(nullable OPTLYHTTPRequestManagerResponse)completion
@@ -285,6 +301,7 @@ - (void)POSTWithParameters:(nonnull NSDictionary *)parameters
285301
self.delaysTest = [NSMutableArray new];
286302

287303
[self POSTWithParameters:parameters
304+
url:url
288305
backoffRetryInterval:backoffRetryInterval
289306
retries:retries
290307
completionHandler:completion
@@ -293,6 +310,7 @@ - (void)POSTWithParameters:(nonnull NSDictionary *)parameters
293310
}
294311

295312
- (void)POSTWithParameters:(NSDictionary *)parameters
313+
url:(NSURL *)url
296314
backoffRetryInterval:(NSInteger)backoffRetryInterval
297315
retries:(NSInteger)retries
298316
completionHandler:(OPTLYHTTPRequestManagerResponse)completion
@@ -321,24 +339,27 @@ - (void)POSTWithParameters:(NSDictionary *)parameters
321339
}
322340

323341
__weak typeof(self) weakSelf = self;
324-
[self POSTWithParameters:parameters completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
325-
if (error) {
326-
dispatch_time_t delayTime = [weakSelf backoffDelay:backoffRetryAttempt
327-
backoffRetryInterval:backoffRetryInterval];
328-
dispatch_after(delayTime, networkTasksQueue(), ^(void){
329-
[weakSelf POSTWithParameters:parameters
330-
backoffRetryInterval:backoffRetryInterval
331-
retries:retries
332-
completionHandler:completion
333-
backoffRetryAttempt:backoffRetryAttempt+1
334-
error:error];
335-
});
336-
} else {
337-
if (completion) {
338-
completion(data, response, error);
339-
}
340-
}
341-
}];
342+
[self POSTWithParameters:parameters
343+
url:url
344+
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
345+
if (error) {
346+
dispatch_time_t delayTime = [weakSelf backoffDelay:backoffRetryAttempt
347+
backoffRetryInterval:backoffRetryInterval];
348+
dispatch_after(delayTime, networkTasksQueue(), ^(void){
349+
[weakSelf POSTWithParameters:parameters
350+
url:url
351+
backoffRetryInterval:backoffRetryInterval
352+
retries:retries
353+
completionHandler:completion
354+
backoffRetryAttempt:backoffRetryAttempt+1
355+
error:error];
356+
});
357+
} else {
358+
if (completion) {
359+
completion(data, response, error);
360+
}
361+
}
362+
}];
342363
}
343364

344365
# pragma mark - Helper Methods

0 commit comments

Comments
 (0)