diff --git a/SignalServiceKit/src/Messages/OWSReadReceiptManager.m b/SignalServiceKit/src/Messages/OWSReadReceiptManager.m index 8b7f6a660..512fe25e5 100644 --- a/SignalServiceKit/src/Messages/OWSReadReceiptManager.m +++ b/SignalServiceKit/src/Messages/OWSReadReceiptManager.m @@ -210,17 +210,7 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE self.isProcessing = YES; - // Process read receipts every N seconds. - // - // We want a value high enough to allow us to effectively de-duplicate, - // read receipts without being so high that we risk not sending read - // receipts due to app exit. - const CGFloat kProcessingFrequencySeconds = 3.f; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kProcessingFrequencySeconds * NSEC_PER_SEC)), - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), - ^{ - [self process]; - }); + [self process]; } }); } @@ -231,9 +221,8 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE { DDLogVerbose(@"%@ Processing read receipts.", self.tag); - self.isProcessing = NO; - - NSArray *readReceiptsForLinkedDevices = [self.toLinkedDevicesReadReceiptMap allValues]; + NSArray *readReceiptsForLinkedDevices = + [self.toLinkedDevicesReadReceiptMap allValues]; [self.toLinkedDevicesReadReceiptMap removeAllObjects]; if (readReceiptsForLinkedDevices.count > 0) { OWSReadReceiptsForLinkedDevicesMessage *message = @@ -250,11 +239,12 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE }]; } - NSArray *readReceiptsToSend = [self.toLinkedDevicesReadReceiptMap allValues]; - [self.toLinkedDevicesReadReceiptMap removeAllObjects]; - if (self.toSenderReadReceiptMap.count > 0) { - for (NSString *recipientId in self.toSenderReadReceiptMap) { - NSSet *timestamps = self.toSenderReadReceiptMap[recipientId]; + NSDictionary *> *toSenderReadReceiptMap = + [self.toSenderReadReceiptMap copy]; + [self.toSenderReadReceiptMap removeAllObjects]; + if (toSenderReadReceiptMap.count > 0) { + for (NSString *recipientId in toSenderReadReceiptMap) { + NSSet *timestamps = toSenderReadReceiptMap[recipientId]; OWSAssert(timestamps.count > 0); TSThread *thread = [TSContactThread getOrCreateThreadWithContactId:recipientId]; @@ -264,8 +254,7 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE [self.messageSender sendMessage:message success:^{ - DDLogInfo( - @"%@ Successfully sent %zd read receipts to sender.", self.tag, readReceiptsToSend.count); + DDLogInfo(@"%@ Successfully sent %zd read receipts to sender.", self.tag, timestamps.count); } failure:^(NSError *error) { DDLogError(@"%@ Failed to send read receipts to sender with error: %@", self.tag, error); @@ -273,6 +262,25 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE } [self.toSenderReadReceiptMap removeAllObjects]; } + + BOOL didWork = (readReceiptsForLinkedDevices.count > 0 || toSenderReadReceiptMap.count > 0); + + if (didWork) { + // Wait N seconds before processing read receipts again. + // This allows time for a batch to accumulate. + // + // We want a value high enough to allow us to effectively de-duplicate, + // read receipts without being so high that we risk not sending read + // receipts due to app exit. + const CGFloat kProcessingFrequencySeconds = 3.f; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kProcessingFrequencySeconds * NSEC_PER_SEC)), + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), + ^{ + [self process]; + }); + } else { + self.isProcessing = NO; + } } }