Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion FirebaseMessaging/Sources/FIRMessagingPendingTopicsList.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ NS_ASSUME_NONNULL_BEGIN
@property(nonatomic, readonly, strong, nullable) NSDate *archiveDate;
@property(nonatomic, readonly) NSUInteger numberOfBatches;

- (instancetype)init NS_DESIGNATED_INITIALIZER;
- (instancetype)init;
- (void)addOperationForTopic:(NSString *)topic
withAction:(FIRMessagingTopicAction)action
completion:(nullable FIRMessagingTopicOperationCompletion)completion;
Expand Down
91 changes: 47 additions & 44 deletions FirebaseMessaging/Sources/FIRMessagingPendingTopicsList.m
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,22 @@ @interface FIRMessagingPendingTopicsList ()

@property(nonatomic, strong) FIRMessagingTopicBatch *currentBatch;
@property(nonatomic, strong) NSMutableSet<NSString *> *topicsInFlight;
@property(nonatomic, readonly) dispatch_queue_t commandQueue;

@end

@implementation FIRMessagingPendingTopicsList

- (instancetype)init {
return
[self initWithCommandQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)];
}

- (instancetype)initWithCommandQueue:(dispatch_queue_t)queue {
if (self = [super init]) {
_topicBatches = [NSMutableArray array];
_topicsInFlight = [NSMutableSet set];
_commandQueue = queue;
}
return self;
}
Expand Down Expand Up @@ -179,7 +186,7 @@ - (void)addOperationForTopic:(NSString *)topic
if (self.currentBatch == lastBatch && !topicExistedBefore) {
// Add this topic to our ongoing operations
FIRMessaging_WEAKIFY(self);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
dispatch_async(self.commandQueue, ^{
FIRMessaging_STRONGIFY(self);
[self resumeOperationsIfNeeded];
});
Expand Down Expand Up @@ -223,49 +230,45 @@ - (void)beginUpdateForCurrentBatchTopic:(NSString *)topic {
[self.topicsInFlight addObject:topic];
}
FIRMessaging_WEAKIFY(self);
[self.delegate
pendingTopicsList:self
requestedUpdateForTopic:topic
action:self.currentBatch.action
completion:^(NSError *error) {
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
FIRMessaging_STRONGIFY(self);
@synchronized(self) {
[self.topicsInFlight removeObject:topic];

BOOL recoverableError = [self subscriptionErrorIsRecoverable:error];
if (!error || !recoverableError) {
// Notify our handlers and remove the topic from our batch
NSMutableArray *handlers = self.currentBatch.topicHandlers[topic];
if (handlers.count) {
dispatch_async(dispatch_get_main_queue(), ^{
for (FIRMessagingTopicOperationCompletion handler in handlers) {
handler(error);
}
[handlers removeAllObjects];
});
}
[self.currentBatch.topics removeObject:topic];
[self.currentBatch.topicHandlers removeObjectForKey:topic];
if (self.currentBatch.topics.count == 0) {
// All topic updates successfully finished in this batch, move on
// to the next batch
[self.topicBatches removeObject:self.currentBatch];
self.currentBatch = nil;
}
[self.delegate pendingTopicsListDidUpdate:self];
FIRMessaging_WEAKIFY(self);
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),
^{
FIRMessaging_STRONGIFY(self);
[self resumeOperationsIfNeeded];
});
}
}
});
}];
[self.delegate pendingTopicsList:self
requestedUpdateForTopic:topic
action:self.currentBatch.action
completion:^(NSError *error) {
dispatch_async(self.commandQueue, ^{
FIRMessaging_STRONGIFY(self);
@synchronized(self) {
[self.topicsInFlight removeObject:topic];

BOOL recoverableError = [self subscriptionErrorIsRecoverable:error];
if (!error || !recoverableError) {
// Notify our handlers and remove the topic from our batch
NSMutableArray *handlers = self.currentBatch.topicHandlers[topic];
if (handlers.count) {
dispatch_async(dispatch_get_main_queue(), ^{
for (FIRMessagingTopicOperationCompletion handler in handlers) {
handler(error);
}
[handlers removeAllObjects];
});
}
[self.currentBatch.topics removeObject:topic];
[self.currentBatch.topicHandlers removeObjectForKey:topic];
if (self.currentBatch.topics.count == 0) {
// All topic updates successfully finished in this batch, move on
// to the next batch
[self.topicBatches removeObject:self.currentBatch];
self.currentBatch = nil;
}
[self.delegate pendingTopicsListDidUpdate:self];
FIRMessaging_WEAKIFY(self);
dispatch_async(self.commandQueue, ^{
FIRMessaging_STRONGIFY(self);
[self resumeOperationsIfNeeded];
});
}
}
});
}];
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
#import "FirebaseMessaging/Sources/FIRMessagingPendingTopicsList.h"
#import "FirebaseMessaging/Sources/FIRMessagingTopicsCommon.h"

@interface FIRMessagingPendingTopicsList (Testing)
- (instancetype)initWithCommandQueue:(dispatch_queue_t)queue;
@end

@interface FIRMessagingPendingTopicsListTest : XCTestCase

/// Using this delegate lets us prevent any topic operations from start, making it easy to measure
Expand Down Expand Up @@ -107,7 +111,8 @@ - (void)testAddTopicsWithDifferentActions {
}

- (void)testBatchSizeReductionAfterSuccessfulTopicUpdate {
FIRMessagingPendingTopicsList *pendingTopics = [[FIRMessagingPendingTopicsList alloc] init];
FIRMessagingPendingTopicsList *pendingTopics = [[FIRMessagingPendingTopicsList alloc]
initWithCommandQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)];
pendingTopics.delegate = self.alwaysReadyDelegate;

XCTestExpectation *allOperationsCompleted =
Expand Down Expand Up @@ -145,7 +150,8 @@ - (void)testBatchSizeReductionAfterSuccessfulTopicUpdate {
}

- (void)testCompletionOfTopicUpdatesInSameThread {
FIRMessagingPendingTopicsList *pendingTopics = [[FIRMessagingPendingTopicsList alloc] init];
FIRMessagingPendingTopicsList *pendingTopics = [[FIRMessagingPendingTopicsList alloc]
initWithCommandQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)];
pendingTopics.delegate = self.alwaysReadyDelegate;

XCTestExpectation *allOperationsSucceededed =
Expand Down Expand Up @@ -181,7 +187,8 @@ - (void)testCompletionOfTopicUpdatesInSameThread {
}

- (void)testAddingTopicToCurrentBatchWhileCurrentBatchTopicsInFlight {
FIRMessagingPendingTopicsList *pendingTopics = [[FIRMessagingPendingTopicsList alloc] init];
FIRMessagingPendingTopicsList *pendingTopics = [[FIRMessagingPendingTopicsList alloc]
initWithCommandQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)];
pendingTopics.delegate = self.alwaysReadyDelegate;

NSString *initialTopic = @"/topics/0";
Expand Down
Loading