@@ -308,55 +308,37 @@ - (void)sendRequests:(BOOL)async
308308{
309309 void (^operationBlock)() = ^void () {
310310 [LeanplumRequest generateUUID ];
311+ lastSentTime = [NSDate timeIntervalSinceReferenceDate ];
312+ dispatch_semaphore_t semaphore = dispatch_semaphore_create (0 );
311313
312314 // Simulate pop all requests.
313315 NSArray *requestsToSend = [LPEventDataManager eventsWithLimit: MAX_EVENTS_PER_API_CALL];
314- lastSentTime = [NSDate timeIntervalSinceReferenceDate ];
315-
316316 if (requestsToSend.count == 0 ) {
317317 return ;
318318 }
319319
320+ // Set up request operation.
320321 NSString *requestData = [LPJSON stringFromJSON: @{LP_PARAM_DATA:requestsToSend}];
322+ NSString *timestamp = [NSString stringWithFormat: @" %f " , [[NSDate date ] timeIntervalSince1970 ]];
321323 LPConstantsState *constants = [LPConstantsState sharedState ];
322- NSMutableDictionary *multiRequestArgs = [NSMutableDictionary dictionaryWithObjectsAndKeys:
323- requestData, LP_PARAM_DATA,
324- constants.sdkVersion, LP_PARAM_SDK_VERSION,
325- constants.client, LP_PARAM_CLIENT,
326- LP_METHOD_MULTI, LP_PARAM_ACTION,
327- [NSString stringWithFormat: @" %f " , [[NSDate date ] timeIntervalSince1970 ]], LP_PARAM_TIME, nil ];
324+ NSMutableDictionary *multiRequestArgs = [@{
325+ LP_PARAM_DATA: requestData,
326+ LP_PARAM_SDK_VERSION: constants.sdkVersion ,
327+ LP_PARAM_CLIENT: constants.client ,
328+ LP_PARAM_ACTION: LP_METHOD_MULTI,
329+ LP_PARAM_TIME: timestamp
330+ } mutableCopy];
328331 [self attachApiKeys: multiRequestArgs];
329332 int timeout = async ? constants.networkTimeoutSeconds : constants.syncNetworkTimeoutSeconds ;
330333 id <LPNetworkOperationProtocol> op = [engine operationWithPath: constants.apiServlet
331334 params: multiRequestArgs
332335 httpMethod: _httpMethod
333336 ssl: constants.apiSSL
334337 timeoutSeconds: timeout];
335- __block BOOL finished = NO ;
336-
337- // Schedule timeout.
338- [LPTimerBlocks scheduledTimerWithTimeInterval: timeout block: ^() {
339- if (finished) {
340- return ;
341- }
342- finished = YES ;
343- LP_TRY
344- NSLog (@" Leanplum: Request %@ timed out" , _apiMethod);
345- [op cancel ];
346- if (_error != nil ) {
347- _error ([NSError errorWithDomain: @" Leanplum" code: 1
348- userInfo: @{NSLocalizedDescriptionKey : @" Request timed out" }]);
349- }
350- LP_END_TRY
351- } repeats: NO ];
352338
339+ // Request callbacks.
353340 [op addCompletionHandler: ^(id <LPNetworkOperationProtocol> operation, id json) {
354- if (finished) {
355- return ;
356- }
357- finished = YES ;
358341 LP_TRY
359-
360342 // Handle errors that don't return an HTTP error code.
361343 NSUInteger numResponses = [LPResponse numResponsesInDictionary: json];
362344 for (NSUInteger i = 0 ; i < numResponses; i++) {
@@ -374,6 +356,7 @@ - (void)sendRequests:(BOOL)async
374356 _error ([NSError errorWithDomain: @" Leanplum" code: 2
375357 userInfo: @{NSLocalizedDescriptionKey : errorMessage}]);
376358 }
359+ dispatch_semaphore_signal (semaphore);
377360 return ;
378361 }
379362 }
@@ -386,15 +369,14 @@ - (void)sendRequests:(BOOL)async
386369 if (requestsToSend.count == MAX_EVENTS_PER_API_CALL) {
387370 [self sendRequests: async];
388371 }
372+ dispatch_semaphore_signal (semaphore);
389373 LP_END_TRY
374+
390375 if (_response != nil ) {
391376 _response (operation, json);
392377 }
378+
393379 } errorHandler: ^(id <LPNetworkOperationProtocol> completedOperation, NSError *err) {
394- if (finished) {
395- return ;
396- }
397- finished = YES ;
398380 LP_TRY
399381 NSInteger httpStatusCode = completedOperation.HTTPStatusCode ;
400382 if (httpStatusCode == 408
@@ -430,19 +412,30 @@ - (void)sendRequests:(BOOL)async
430412 if (_error != nil ) {
431413 _error (err);
432414 }
415+ dispatch_semaphore_signal (semaphore);
433416 LP_END_TRY
434417 }];
435418
436419 // Execute synchronously. Don't block for more than 'timeout' seconds.
437- dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
438- [engine runSynchronously: op];
439- });
440- NSTimeInterval startTime = [[NSDate date ] timeIntervalSince1970 ];
441- while (!finished && [[NSDate date ] timeIntervalSince1970 ] - startTime < timeout) {
442- [NSThread sleepForTimeInterval: 0.1 ];
420+ [engine enqueueOperation: op];
421+ dispatch_time_t dispatchTimeout = dispatch_time (DISPATCH_TIME_NOW, timeout*NSEC_PER_SEC);
422+ long status = dispatch_semaphore_wait (semaphore, dispatchTimeout);
423+
424+ // Request timed out.
425+ if (status != 0 ) {
426+ LP_TRY
427+ NSLog (@" Leanplum: Request %@ timed out" , _apiMethod);
428+ [op cancel ];
429+ if (_error != nil ) {
430+ _error ([NSError errorWithDomain: @" Leanplum" code: 1
431+ userInfo: @{NSLocalizedDescriptionKey : @" Request timed out" }]);
432+ }
433+ LP_END_TRY
443434 }
444435 };
445436
437+ // Send. operationBlock will run synchronously.
438+ // Adding to OperationQueue puts it in the background.
446439 if (async) {
447440 [sendNowQueue addOperationWithBlock: operationBlock];
448441 } else {
@@ -729,6 +722,11 @@ + (void)onNoPendingDownloads:(LeanplumVariablesChangedBlock)block
729722 noPendingDownloadsBlock = block;
730723}
731724
725+ + (NSOperationQueue *)sendNowQueue
726+ {
727+ return sendNowQueue;
728+ }
729+
732730@end
733731
734732@implementation LPResponse
0 commit comments