Skip to content
This repository has been archived by the owner on Feb 19, 2020. It is now read-only.

Commit

Permalink
Merge pull request #483 from MatkovIvan/fix/wait-notification
Browse files Browse the repository at this point in the history
Track sender activity only for background task
  • Loading branch information
Benjamin Scholtysik (Reimold) authored Dec 7, 2017
2 parents dfb2a86 + f29296d commit 880181b
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 47 deletions.
80 changes: 39 additions & 41 deletions Classes/BITChannel.m
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@
@interface BITChannel ()

@property (nonatomic, weak, nullable) id appDidEnterBackgroundObserver;
@property (nonatomic, weak, nullable) id persistenceSuccessObserver;
@property (nonatomic, weak, nullable) id senderFinishSendingDataObserver;

@property (nonatomic, nonnull) dispatch_group_t senderGroup;

@end

Expand All @@ -61,8 +57,6 @@ - (instancetype)init {
dispatch_queue_t serialQueue = dispatch_queue_create(BITDataItemsOperationsQueue, DISPATCH_QUEUE_SERIAL);
_dataItemsOperations = serialQueue;

_senderGroup = dispatch_group_create();

[self registerObservers];
}
return self;
Expand Down Expand Up @@ -107,26 +101,6 @@ - (void) registerObservers {
queue:NSOperationQueue.mainQueue
usingBlock:notificationBlock];
}
if (nil == self.persistenceSuccessObserver) {
self.persistenceSuccessObserver =
[center addObserverForName:BITPersistenceSuccessNotification
object:nil
queue:nil
usingBlock:^(NSNotification __unused *notification) {
typeof(self) strongSelf = weakSelf;
dispatch_group_enter(strongSelf.senderGroup);
}];
}
if (nil == self.senderFinishSendingDataObserver) {
self.senderFinishSendingDataObserver =
[center addObserverForName:BITSenderFinishSendingDataNotification
object:nil
queue:nil
usingBlock:^(NSNotification __unused *notification) {
typeof(self) strongSelf = weakSelf;
dispatch_group_leave(strongSelf.senderGroup);
}];
}
}

- (void) unregisterObservers {
Expand All @@ -136,16 +110,6 @@ - (void) unregisterObservers {
[center removeObserver:appDidEnterBackgroundObserver];
self.appDidEnterBackgroundObserver = nil;
}
id persistenceSuccessObserver = self.persistenceSuccessObserver;
if (persistenceSuccessObserver) {
[center removeObserver:persistenceSuccessObserver];
self.persistenceSuccessObserver = nil;
}
id senderFinishSendingDataObserver = self.senderFinishSendingDataObserver;
if (senderFinishSendingDataObserver) {
[center removeObserver:senderFinishSendingDataObserver];
self.senderFinishSendingDataObserver = nil;
}
}

#pragma mark - Queue management
Expand Down Expand Up @@ -201,37 +165,71 @@ - (void)persistDataItemQueueWithBackgroundTask:(UIApplication *)application {
typeof(self) strongSelf = weakSelf;
[strongSelf persistDataItemQueue:&BITTelemetryEventBuffer];
});
[self createBackgroundTask:application withWaitingGroup:nil];
[self createBackgroundTaskWhileDataIsSending:application withWaitingGroup:nil];
}

- (void)createBackgroundTask:(UIApplication *)application withWaitingGroup:(nullable dispatch_group_t)group {
- (void)createBackgroundTaskWhileDataIsSending:(UIApplication *)application
withWaitingGroup:(nullable dispatch_group_t)group {
if (application == nil) {
return;
}

// Queues needs for waiting consistently.
NSArray *queues = @[
self.dataItemsOperations, // For enqueue
self.persistence.persistenceQueue, // For persist
dispatch_get_main_queue() // For notification
];

// Tracking for sender activity.
// BITPersistenceSuccessNotification - start sending
// BITSenderFinishSendingDataNotification - finish sending
__block dispatch_group_t senderGroup = dispatch_group_create();
__block NSInteger senderCounter = 0;
__block id persistenceSuccessObserver = [[NSNotificationCenter defaultCenter]
addObserverForName:BITPersistenceSuccessNotification
object:nil
queue:nil
usingBlock:^(__unused NSNotification *notification) {
dispatch_group_enter(senderGroup);
senderCounter++;
if (persistenceSuccessObserver) {
[[NSNotificationCenter defaultCenter] removeObserver:persistenceSuccessObserver];
persistenceSuccessObserver = nil;
}
}];
__block id senderFinishSendingDataObserver = [[NSNotificationCenter defaultCenter]
addObserverForName:BITSenderFinishSendingDataNotification
object:nil
queue:nil
usingBlock:^(__unused NSNotification *notification) {
if (senderCounter > 0) {
dispatch_group_leave(senderGroup);
senderCounter--;
}
if (senderFinishSendingDataObserver) {
[[NSNotificationCenter defaultCenter] removeObserver:senderFinishSendingDataObserver];
senderFinishSendingDataObserver = nil;
}
}];

BITHockeyLogVerbose(@"BITChannel: Start background task");
__block UIBackgroundTaskIdentifier backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^{
BITHockeyLogVerbose(@"BITChannel: Background task is expired");
[application endBackgroundTask:backgroundTask];
backgroundTask = UIBackgroundTaskInvalid;
}];
__block NSUInteger i = 0;
__weak typeof(self) weakSelf = self;
__block __weak void (^weakWaitBlock)();
void (^waitBlock)();
weakWaitBlock = waitBlock = ^{
typeof(self) strongSelf = weakSelf;
if (i < queues.count) {
dispatch_queue_t queue = [queues objectAtIndex:i++];
BITHockeyLogVerbose(@"BITChannel: Waiting queue: %@", [[NSString alloc] initWithUTF8String:dispatch_queue_get_label(queue)]);
dispatch_async(queue, weakWaitBlock);
} else {
BITHockeyLogVerbose(@"BITChannel: Waiting sender");
dispatch_group_notify(strongSelf.senderGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_group_notify(senderGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (backgroundTask != UIBackgroundTaskInvalid) {
BITHockeyLogVerbose(@"BITChannel: Cancel background task");
[application endBackgroundTask:backgroundTask];
Expand Down
3 changes: 2 additions & 1 deletion Classes/BITChannelPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ FOUNDATION_EXPORT NSString *const BITChannelBlockedNotification;
/**
* Create background task for queues and group.
*/
- (void)createBackgroundTask:(UIApplication *)application withWaitingGroup:(nullable dispatch_group_t)group;
- (void)createBackgroundTaskWhileDataIsSending:(UIApplication *)application
withWaitingGroup:(nullable dispatch_group_t)group;

/**
* Adds the specified dictionary to the JSON Stream string.
Expand Down
16 changes: 11 additions & 5 deletions Classes/BITMetricsManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,9 @@ - (void)trackSessionWithState:(BITSessionState)state {
#pragma mark Events

- (void)trackEventWithName:(nonnull NSString *)eventName {
if (!eventName) { return; }
if (!eventName) {
return;
}
if (self.disabled) {
BITHockeyLogDebug(@"INFO: BITMetricsManager is disabled, therefore this tracking call was ignored.");
return;
Expand All @@ -198,12 +200,16 @@ - (void)trackEventWithName:(nonnull NSString *)eventName {
// If the app is running in the background.
UIApplication *application = [UIApplication sharedApplication];
if (application && application.applicationState == UIApplicationStateBackground) {
[self.channel createBackgroundTask:application withWaitingGroup:group];
[self.channel createBackgroundTaskWhileDataIsSending:application withWaitingGroup:group];
}
}

- (void)trackEventWithName:(nonnull NSString *)eventName properties:(nullable NSDictionary<NSString *, NSString *> *)properties measurements:(nullable NSDictionary<NSString *, NSNumber *> *)measurements {
if (!eventName) { return; }
- (void)trackEventWithName:(nonnull NSString *)eventName
properties:(nullable NSDictionary<NSString *, NSString *> *)properties
measurements:(nullable NSDictionary<NSString *, NSNumber *> *)measurements {
if (!eventName) {
return;
}
if (self.disabled) {
BITHockeyLogDebug(@"INFO: BITMetricsManager is disabled, therefore this tracking call was ignored.");
return;
Expand All @@ -223,7 +229,7 @@ - (void)trackEventWithName:(nonnull NSString *)eventName properties:(nullable NS
// If the app is running in the background.
UIApplication *application = [UIApplication sharedApplication];
if (application && application.applicationState == UIApplicationStateBackground) {
[self.channel createBackgroundTask:application withWaitingGroup:group];
[self.channel createBackgroundTaskWhileDataIsSending:application withWaitingGroup:group];
}
}

Expand Down

0 comments on commit 880181b

Please sign in to comment.