Merge branch 'mkirk/background-sending'

This commit is contained in:
Michael Kirk 2017-03-20 15:00:20 -04:00
commit 778d3dd2bc

View file

@ -56,6 +56,11 @@ NS_ASSUME_NONNULL_BEGIN
success:(void (^)())successHandler
failure:(void (^)(NSError *_Nonnull error))failureHandler NS_DESIGNATED_INITIALIZER;
#pragma mark - background task mgmt
- (void)startBackgroundTask;
- (void)endBackgroundTask;
@end
typedef NS_ENUM(NSInteger, OWSSendMessageOperationState) {
@ -83,7 +88,8 @@ NSUInteger const OWSSendMessageOperationMaxRetries = 4;
@property (nonatomic, readonly) OWSMessageSender *messageSender;
@property (nonatomic, readonly) void (^successHandler)();
@property (nonatomic, readonly) void (^failureHandler)(NSError *_Nonnull error);
@property (atomic) OWSSendMessageOperationState operationState;
@property (nonatomic) OWSSendMessageOperationState operationState;
@property (nonatomic) UIBackgroundTaskIdentifier backgroundTaskIdentifier;
@end
@ -100,6 +106,7 @@ NSUInteger const OWSSendMessageOperationMaxRetries = 4;
}
_operationState = OWSSendMessageOperationStateNew;
_backgroundTaskIdentifier = UIBackgroundTaskInvalid;
_message = message;
_messageSender = messageSender;
@ -131,6 +138,38 @@ NSUInteger const OWSSendMessageOperationMaxRetries = 4;
return self;
}
#pragma mark - background task mgmt
// We want to make sure to finish sending any in-flight messages when the app is backgrounded.
// We have to call `startBackgroundTask` *before* the task is enqueued, since we can't guarantee when the operation will
// be dequeued.
- (void)startBackgroundTask
{
AssertIsOnMainThread();
OWSAssert(self.backgroundTaskIdentifier == UIBackgroundTaskInvalid);
self.backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
DDLogWarn(@"%@ Timed out while in background trying to send message: %@", self.tag, self.message);
[self endBackgroundTask];
}];
}
- (void)endBackgroundTask
{
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier];
}
- (void)setBackgroundTaskIdentifier:(UIBackgroundTaskIdentifier)backgroundTaskIdentifier
{
AssertIsOnMainThread();
// Should only be sent once per operation
OWSAssert(_backgroundTaskIdentifier == UIBackgroundTaskInvalid);
OWSAssert(backgroundTaskIdentifier != UIBackgroundTaskInvalid);
_backgroundTaskIdentifier = backgroundTaskIdentifier;
}
#pragma mark - NSOperation overrides
- (BOOL)isExecuting
@ -145,6 +184,10 @@ NSUInteger const OWSSendMessageOperationMaxRetries = 4;
- (void)start
{
// Should call `startBackgroundTask` before enqueuing the operation
// to ensure we don't get suspended before the operation completes.
OWSAssert(self.backgroundTaskIdentifier != UIBackgroundTaskInvalid);
[self willChangeValueForKey:OWSSendMessageOperationKeyIsExecuting];
self.operationState = OWSSendMessageOperationStateExecuting;
[self didChangeValueForKey:OWSSendMessageOperationKeyIsExecuting];
@ -182,6 +225,8 @@ NSUInteger const OWSSendMessageOperationMaxRetries = 4;
self.operationState = OWSSendMessageOperationStateFinished;
[self didChangeValueForKey:OWSSendMessageOperationKeyIsExecuting];
[self didChangeValueForKey:OWSSendMessageOperationKeyIsFinished];
[self endBackgroundTask];
}
#pragma mark - Logging
@ -252,6 +297,10 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
messageSender:self
success:successHandler
failure:failureHandler];
// We call `startBackgroundTask` here to prevent our app from suspending while being backgrounded
// until the operation is completed - at which point the OWSSendMessageOperation ends it's background task.
[sendMessageOperation startBackgroundTask];
[self.sendingQueue addOperation:sendMessageOperation];
}