4545static NSMutableDictionary *fileUploadProgress;
4646static NSString *fileUploadProgressString;
4747static NSMutableDictionary *pendingUploads;
48+ static NSOperationQueue *sendNowQueue;
4849
4950static NSDictionary *_requestHheaders;
5051
@@ -139,6 +140,11 @@ - (id)initWithHttpMethod:(NSString *)httpMethod
139140 engine = [LPNetworkFactory engineWithHostName: [LPConstantsState sharedState ].apiHostName
140141 customHeaderFields: _requestHheaders];
141142 }
143+
144+ if (!sendNowQueue) {
145+ sendNowQueue = [NSOperationQueue new ];
146+ sendNowQueue.maxConcurrentOperationCount = 1 ;
147+ }
142148 }
143149 return self;
144150}
@@ -284,126 +290,124 @@ - (void)sendNow:(BOOL)async
284290 NSLog (@" Leanplum: Cannot send request. accessKey is not set" );
285291 return ;
286292 }
287-
293+
288294 [self sendEventually ];
289295
290- NSArray *requestsToSend = [[LPRequestStorage sharedStorage ] popAllRequests ];
291-
292- if (requestsToSend.count == 0 ) {
293- return ;
294- }
295-
296- NSString *requestData = [LeanplumRequest jsonEncodeUnsentRequests: requestsToSend];
297-
298- LPConstantsState *constants = [LPConstantsState sharedState ];
299- NSMutableDictionary *multiRequestArgs = [NSMutableDictionary dictionaryWithObjectsAndKeys:
300- requestData, LP_PARAM_DATA,
301- constants.sdkVersion, LP_PARAM_SDK_VERSION,
302- constants.client, LP_PARAM_CLIENT,
303- LP_METHOD_MULTI, LP_PARAM_ACTION,
304- [NSString stringWithFormat: @" %f " , [[NSDate date ] timeIntervalSince1970 ]], LP_PARAM_TIME, nil ];
305- [self attachApiKeys: multiRequestArgs];
306- int timeout = async ? constants.networkTimeoutSeconds : constants.syncNetworkTimeoutSeconds ;
307- id <LPNetworkOperationProtocol> op = [engine operationWithPath: constants.apiServlet
308- params: multiRequestArgs
309- httpMethod: _httpMethod
310- ssl: constants.apiSSL
311- timeoutSeconds: timeout];
312- __block BOOL finished = NO ;
313-
314- // Schedule timeout.
315- [LPTimerBlocks scheduledTimerWithTimeInterval: timeout block: ^() {
316- if (finished) {
296+ void (^operationBlock)() = ^void () {
297+ NSArray *requestsToSend = [[LPRequestStorage sharedStorage ] popAllRequests ];
298+
299+ if (requestsToSend.count == 0 ) {
317300 return ;
318301 }
319- finished = YES ;
320- LP_TRY
321- NSLog (@" Leanplum: Request %@ timed out" , _apiMethod);
322- [op cancel ];
323- [LeanplumRequest pushUnsentRequests: requestsToSend];
324- if (_error != nil ) {
325- _error ([NSError errorWithDomain: @" Leanplum" code: 1
326- userInfo: @{NSLocalizedDescriptionKey : @" Request timed out" }]);
327- }
328- LP_END_TRY
329- } repeats: NO ];
330302
331- [op addCompletionHandler: ^(id <LPNetworkOperationProtocol> operation, id json) {
332- if (finished) {
333- return ;
334- }
335- finished = YES ;
336- LP_TRY
303+ NSString *requestData = [LeanplumRequest jsonEncodeUnsentRequests: requestsToSend];
304+
305+ LPConstantsState *constants = [LPConstantsState sharedState ];
306+ NSMutableDictionary *multiRequestArgs = [NSMutableDictionary dictionaryWithObjectsAndKeys:
307+ requestData, LP_PARAM_DATA,
308+ constants.sdkVersion, LP_PARAM_SDK_VERSION,
309+ constants.client, LP_PARAM_CLIENT,
310+ LP_METHOD_MULTI, LP_PARAM_ACTION,
311+ [NSString stringWithFormat: @" %f " , [[NSDate date ] timeIntervalSince1970 ]], LP_PARAM_TIME, nil ];
312+ [self attachApiKeys: multiRequestArgs];
313+ int timeout = async ? constants.networkTimeoutSeconds : constants.syncNetworkTimeoutSeconds ;
314+ id <LPNetworkOperationProtocol> op = [engine operationWithPath: constants.apiServlet
315+ params: multiRequestArgs
316+ httpMethod: _httpMethod
317+ ssl: constants.apiSSL
318+ timeoutSeconds: timeout];
319+ __block BOOL finished = NO ;
320+
321+ // Schedule timeout.
322+ [LPTimerBlocks scheduledTimerWithTimeInterval: timeout block: ^() {
323+ if (finished) {
324+ return ;
325+ }
326+ finished = YES ;
327+ LP_TRY
328+ NSLog (@" Leanplum: Request %@ timed out" , _apiMethod);
329+ [op cancel ];
330+ [LeanplumRequest pushUnsentRequests: requestsToSend];
331+ if (_error != nil ) {
332+ _error ([NSError errorWithDomain: @" Leanplum" code: 1
333+ userInfo: @{NSLocalizedDescriptionKey : @" Request timed out" }]);
334+ }
335+ LP_END_TRY
336+ } repeats: NO ];
337337
338- // Handle errors that don't return an HTTP error code.
339- NSUInteger numResponses = [LPResponse numResponsesInDictionary: json];
340- for (NSUInteger i = 0 ; i < numResponses; i++) {
341- NSDictionary *response = [LPResponse getResponseAt: i fromDictionary: json];
342- if (![LPResponse isResponseSuccess: response]) {
343- NSString *errorMessage = [LPResponse getResponseError: response];
344- if (!errorMessage) {
345- errorMessage = @" API error" ;
346- } else {
347- errorMessage = [NSString stringWithFormat: @" API error: %@ " , errorMessage];
348- }
349- NSLog (@" Leanplum: %@ " , errorMessage);
350- if (i == numResponses - 1 ) {
351- if (_error != nil ) {
352- _error ([NSError errorWithDomain: @" Leanplum" code: 2
353- userInfo: @{NSLocalizedDescriptionKey : errorMessage}]);
338+ [op addCompletionHandler: ^(id <LPNetworkOperationProtocol> operation, id json) {
339+ if (finished) {
340+ return ;
341+ }
342+ finished = YES ;
343+ LP_TRY
344+
345+ // Handle errors that don't return an HTTP error code.
346+ NSUInteger numResponses = [LPResponse numResponsesInDictionary: json];
347+ for (NSUInteger i = 0 ; i < numResponses; i++) {
348+ NSDictionary *response = [LPResponse getResponseAt: i fromDictionary: json];
349+ if (![LPResponse isResponseSuccess: response]) {
350+ NSString *errorMessage = [LPResponse getResponseError: response];
351+ if (!errorMessage) {
352+ errorMessage = @" API error" ;
353+ } else {
354+ errorMessage = [NSString stringWithFormat: @" API error: %@ " , errorMessage];
355+ }
356+ NSLog (@" Leanplum: %@ " , errorMessage);
357+ if (i == numResponses - 1 ) {
358+ if (_error != nil ) {
359+ _error ([NSError errorWithDomain: @" Leanplum" code: 2
360+ userInfo: @{NSLocalizedDescriptionKey : errorMessage}]);
361+ }
362+ return ;
354363 }
355- return ;
356364 }
357365 }
358- }
359- LP_END_TRY
360- if (_response != nil ) {
361- _response (operation, json);
362- }
363- } errorHandler: ^(id <LPNetworkOperationProtocol> completedOperation, NSError *err) {
364- if (finished) {
365- return ;
366- }
367- finished = YES ;
368- LP_TRY
369- NSInteger httpStatusCode = completedOperation.HTTPStatusCode ;
370- if (httpStatusCode == 408
371- || (httpStatusCode >= 500 && httpStatusCode < 600 )
372- || err.code == NSURLErrorBadServerResponse
373- || err.code == NSURLErrorCannotConnectToHost
374- || err.code == NSURLErrorDNSLookupFailed
375- || err.code == NSURLErrorNotConnectedToInternet
376- || err.code == NSURLErrorTimedOut) {
377- NSLog (@" Leanplum: %@ " , err);
378- [LeanplumRequest pushUnsentRequests: requestsToSend];
379- } else {
380- id errorResponse = completedOperation.responseJSON ;
381- NSString *errorMessage = [LPResponse getResponseError: [LPResponse getLastResponse: errorResponse]];
382- if (errorMessage && [errorMessage hasPrefix: @" App not found" ]) {
383- errorMessage = @" No app matching the provided app ID was found." ;
384- constants.isInPermanentFailureState = YES ;
385- } else if (errorMessage && [errorMessage hasPrefix: @" Invalid access key" ]) {
386- errorMessage = @" The access key you provided is not valid for this app." ;
387- constants.isInPermanentFailureState = YES ;
388- } else if (errorMessage && [errorMessage hasPrefix: @" Development mode requested but not permitted" ]) {
389- errorMessage = @" A call to [Leanplum setAppIdForDevelopmentMode] with your production key was made, which is not permitted." ;
390- constants.isInPermanentFailureState = YES ;
366+ LP_END_TRY
367+ if (_response != nil ) {
368+ _response (operation, json);
391369 }
392- if (errorMessage) {
393- NSLog (@" Leanplum: %@ " , errorMessage);
394- } else {
370+ } errorHandler: ^(id <LPNetworkOperationProtocol> completedOperation, NSError *err) {
371+ if (finished) {
372+ return ;
373+ }
374+ finished = YES ;
375+ LP_TRY
376+ NSInteger httpStatusCode = completedOperation.HTTPStatusCode ;
377+ if (httpStatusCode == 408
378+ || (httpStatusCode >= 500 && httpStatusCode < 600 )
379+ || err.code == NSURLErrorBadServerResponse
380+ || err.code == NSURLErrorCannotConnectToHost
381+ || err.code == NSURLErrorDNSLookupFailed
382+ || err.code == NSURLErrorNotConnectedToInternet
383+ || err.code == NSURLErrorTimedOut) {
395384 NSLog (@" Leanplum: %@ " , err);
385+ [LeanplumRequest pushUnsentRequests: requestsToSend];
386+ } else {
387+ id errorResponse = completedOperation.responseJSON ;
388+ NSString *errorMessage = [LPResponse getResponseError: [LPResponse getLastResponse: errorResponse]];
389+ if (errorMessage && [errorMessage hasPrefix: @" App not found" ]) {
390+ errorMessage = @" No app matching the provided app ID was found." ;
391+ constants.isInPermanentFailureState = YES ;
392+ } else if (errorMessage && [errorMessage hasPrefix: @" Invalid access key" ]) {
393+ errorMessage = @" The access key you provided is not valid for this app." ;
394+ constants.isInPermanentFailureState = YES ;
395+ } else if (errorMessage && [errorMessage hasPrefix: @" Development mode requested but not permitted" ]) {
396+ errorMessage = @" A call to [Leanplum setAppIdForDevelopmentMode] with your production key was made, which is not permitted." ;
397+ constants.isInPermanentFailureState = YES ;
398+ }
399+ if (errorMessage) {
400+ NSLog (@" Leanplum: %@ " , errorMessage);
401+ } else {
402+ NSLog (@" Leanplum: %@ " , err);
403+ }
396404 }
397- }
398- if (_error != nil ) {
399- _error (err);
400- }
401- LP_END_TRY
402- }];
405+ if (_error != nil ) {
406+ _error (err);
407+ }
408+ LP_END_TRY
409+ }];
403410
404- if (async) {
405- [engine enqueueOperation: op];
406- } else {
407411 // Execute synchronously. Don't block for more than 'timeout' seconds.
408412 dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
409413 [engine runSynchronously: op];
@@ -412,6 +416,12 @@ - (void)sendNow:(BOOL)async
412416 while (!finished && [[NSDate date ] timeIntervalSince1970 ] - startTime < timeout) {
413417 [NSThread sleepForTimeInterval: 0.1 ];
414418 }
419+ };
420+
421+ if (async) {
422+ [sendNowQueue addOperationWithBlock: operationBlock];
423+ } else {
424+ operationBlock ();
415425 }
416426}
417427
0 commit comments