Evacuate early message cache after memory warning
This commit is contained in:
parent
fb688abcb5
commit
ad64727ecc
@ -116,6 +116,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
BulkProfileFetch *bulkProfileFetch = [BulkProfileFetch new];
|
||||
BulkUUIDLookup *bulkUUIDLookup = [BulkUUIDLookup new];
|
||||
id<VersionedProfiles> versionedProfiles = [VersionedProfilesImpl new];
|
||||
EarlyMessageManager *earlyMessageManager = [EarlyMessageManager new];
|
||||
|
||||
[Environment setShared:[[Environment alloc] initWithAudioSession:audioSession
|
||||
incomingContactSyncJobQueue:incomingContactSyncJobQueue
|
||||
@ -173,7 +174,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
messageFetcherJob:messageFetcherJob
|
||||
bulkProfileFetch:bulkProfileFetch
|
||||
bulkUUIDLookup:bulkUUIDLookup
|
||||
versionedProfiles:versionedProfiles]];
|
||||
versionedProfiles:versionedProfiles
|
||||
earlyMessageManager:earlyMessageManager]];
|
||||
|
||||
appSpecificSingletonBlock();
|
||||
|
||||
|
||||
@ -67,6 +67,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return SSKEnvironment.shared.tsAccountManager;
|
||||
}
|
||||
|
||||
+ (EarlyMessageManager *)earlyMessageManager
|
||||
{
|
||||
return SSKEnvironment.shared.earlyMessageManager;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
+ (void)processIncomingSentMessageTranscript:(OWSIncomingSentMessageTranscript *)transcript
|
||||
@ -234,7 +239,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
expirationStartedAt:transcript.expirationStartedAt
|
||||
transaction:transaction];
|
||||
|
||||
[OWSEarlyMessageManager applyPendingMessagesFor:outgoingMessage transaction:transaction];
|
||||
[self.earlyMessageManager applyPendingMessagesFor:outgoingMessage transaction:transaction];
|
||||
|
||||
if (outgoingMessage.isViewOnceMessage) {
|
||||
// To be extra-conservative, always mark
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc(OWSEarlyMessageManager)
|
||||
@objc
|
||||
public class EarlyMessageManager: NSObject {
|
||||
private struct MessageIdentifier: Hashable {
|
||||
let timestamp: UInt64
|
||||
@ -34,19 +34,42 @@ public class EarlyMessageManager: NSObject {
|
||||
private static let maxQueuedMessages = 100
|
||||
private static let maxEarlyEnvelopeSize = 1024
|
||||
|
||||
private static let serialQueue = DispatchQueue(label: "EarlyMessageManager")
|
||||
private static var pendingEnvelopes = OrderedDictionary<MessageIdentifier, [EarlyEnvelope]>()
|
||||
private static var pendingReceipts = OrderedDictionary<MessageIdentifier, [EarlyReceipt]>()
|
||||
private let serialQueue = DispatchQueue(label: "EarlyMessageManager")
|
||||
private var pendingEnvelopes = OrderedDictionary<MessageIdentifier, [EarlyEnvelope]>()
|
||||
private var pendingReceipts = OrderedDictionary<MessageIdentifier, [EarlyReceipt]>()
|
||||
|
||||
public override init() {
|
||||
super.init()
|
||||
|
||||
SwiftSingletons.register(self)
|
||||
|
||||
// Listen for memory warnings to evacuate the caches
|
||||
NotificationCenter.default.addObserver(
|
||||
self,
|
||||
selector: #selector(didReceiveMemoryWarning),
|
||||
name: UIApplication.didReceiveMemoryWarningNotification,
|
||||
object: nil
|
||||
)
|
||||
}
|
||||
|
||||
@objc
|
||||
public static func recordEarlyEnvelope(
|
||||
func didReceiveMemoryWarning() {
|
||||
Logger.error("Dropping all early messages due to memory warning.")
|
||||
serialQueue.sync {
|
||||
pendingEnvelopes = OrderedDictionary()
|
||||
pendingReceipts = OrderedDictionary()
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
public func recordEarlyEnvelope(
|
||||
_ envelope: SSKProtoEnvelope,
|
||||
plainTextData: Data?,
|
||||
wasReceivedByUD: Bool,
|
||||
associatedMessageTimestamp: UInt64,
|
||||
associatedMessageAuthor: SignalServiceAddress
|
||||
) {
|
||||
guard plainTextData?.count ?? 0 <= maxEarlyEnvelopeSize else {
|
||||
guard plainTextData?.count ?? 0 <= Self.maxEarlyEnvelopeSize else {
|
||||
return owsFailDebug("unexpectedly tried to record an excessively large early envelope")
|
||||
}
|
||||
|
||||
@ -54,7 +77,7 @@ public class EarlyMessageManager: NSObject {
|
||||
serialQueue.sync {
|
||||
var envelopes = pendingEnvelopes[identifier] ?? []
|
||||
|
||||
while envelopes.count >= maxQueuedPerMessage, let droppedEarlyEnvelope = envelopes.first {
|
||||
while envelopes.count >= Self.maxQueuedPerMessage, let droppedEarlyEnvelope = envelopes.first {
|
||||
envelopes.remove(at: 0)
|
||||
owsFailDebug("Dropping early envelope \(droppedEarlyEnvelope.envelope.timestamp) for message \(identifier) due to excessive early envelopes.")
|
||||
}
|
||||
@ -62,7 +85,7 @@ public class EarlyMessageManager: NSObject {
|
||||
envelopes.append(EarlyEnvelope(envelope: envelope, plainTextData: plainTextData, wasReceivedByUD: wasReceivedByUD))
|
||||
pendingEnvelopes[identifier] = envelopes
|
||||
|
||||
while pendingEnvelopes.count >= maxQueuedMessages, let droppedEarlyIdentifier = pendingEnvelopes.orderedKeys.first {
|
||||
while pendingEnvelopes.count >= Self.maxQueuedMessages, let droppedEarlyIdentifier = pendingEnvelopes.orderedKeys.first {
|
||||
pendingEnvelopes.remove(key: droppedEarlyIdentifier)
|
||||
owsFailDebug("Dropping all early envelopes for message \(droppedEarlyIdentifier) due to excessive early messages.")
|
||||
}
|
||||
@ -70,7 +93,7 @@ public class EarlyMessageManager: NSObject {
|
||||
}
|
||||
|
||||
@objc
|
||||
public static func recordEarlyReceiptForOutgoingMessage(
|
||||
public func recordEarlyReceiptForOutgoingMessage(
|
||||
type: SSKProtoReceiptMessageType,
|
||||
sender: SignalServiceAddress,
|
||||
timestamp: UInt64,
|
||||
@ -88,7 +111,7 @@ public class EarlyMessageManager: NSObject {
|
||||
}
|
||||
|
||||
@objc
|
||||
public static func recordEarlyReadReceiptFromLinkedDevice(
|
||||
public func recordEarlyReadReceiptFromLinkedDevice(
|
||||
timestamp: UInt64,
|
||||
associatedMessageTimestamp: UInt64,
|
||||
associatedMessageAuthor: SignalServiceAddress
|
||||
@ -100,7 +123,7 @@ public class EarlyMessageManager: NSObject {
|
||||
)
|
||||
}
|
||||
|
||||
private static func recordEarlyReceipt(
|
||||
private func recordEarlyReceipt(
|
||||
_ earlyReceipt: EarlyReceipt,
|
||||
associatedMessageTimestamp: UInt64,
|
||||
associatedMessageAuthor: SignalServiceAddress
|
||||
@ -109,7 +132,7 @@ public class EarlyMessageManager: NSObject {
|
||||
serialQueue.sync {
|
||||
var receipts = pendingReceipts[identifier] ?? []
|
||||
|
||||
while receipts.count >= maxQueuedPerMessage, let droppedEarlyReceipt = receipts.first {
|
||||
while receipts.count >= Self.maxQueuedPerMessage, let droppedEarlyReceipt = receipts.first {
|
||||
receipts.remove(at: 0)
|
||||
owsFailDebug("Dropping early receipt \(droppedEarlyReceipt) for message \(identifier) due to excessive early receipts.")
|
||||
}
|
||||
@ -117,7 +140,7 @@ public class EarlyMessageManager: NSObject {
|
||||
receipts.append(earlyReceipt)
|
||||
pendingReceipts[identifier] = receipts
|
||||
|
||||
while pendingReceipts.count >= maxQueuedMessages, let droppedEarlyIdentifier = pendingReceipts.orderedKeys.first {
|
||||
while pendingReceipts.count >= Self.maxQueuedMessages, let droppedEarlyIdentifier = pendingReceipts.orderedKeys.first {
|
||||
pendingReceipts.remove(key: droppedEarlyIdentifier)
|
||||
owsFailDebug("Dropping all early envelopes for message \(droppedEarlyIdentifier) due to excessive early messages.")
|
||||
}
|
||||
@ -125,7 +148,7 @@ public class EarlyMessageManager: NSObject {
|
||||
}
|
||||
|
||||
@objc
|
||||
public static func applyPendingMessages(for message: TSMessage, transaction: SDSAnyWriteTransaction) {
|
||||
public func applyPendingMessages(for message: TSMessage, transaction: SDSAnyWriteTransaction) {
|
||||
var earlyReceipts: [EarlyReceipt]?
|
||||
var earlyEnvelopes: [EarlyEnvelope]?
|
||||
|
||||
|
||||
@ -172,6 +172,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return SSKEnvironment.shared.groupsV2;
|
||||
}
|
||||
|
||||
- (EarlyMessageManager *)earlyMessageManager
|
||||
{
|
||||
return SSKEnvironment.shared.earlyMessageManager;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)startObserving
|
||||
@ -942,10 +947,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
for (NSNumber *nsEarlyTimestamp in earlyTimestamps) {
|
||||
UInt64 earlyTimestamp = [nsEarlyTimestamp unsignedLongLongValue];
|
||||
[OWSEarlyMessageManager recordEarlyReceiptForOutgoingMessageWithType:receiptMessage.unwrappedType
|
||||
sender:envelope.sourceAddress
|
||||
timestamp:envelope.timestamp
|
||||
associatedMessageTimestamp:earlyTimestamp];
|
||||
[self.earlyMessageManager recordEarlyReceiptForOutgoingMessageWithType:receiptMessage.unwrappedType
|
||||
sender:envelope.sourceAddress
|
||||
timestamp:envelope.timestamp
|
||||
associatedMessageTimestamp:earlyTimestamp];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1480,11 +1485,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
case OWSReactionProcessingResultInvalidReaction:
|
||||
break;
|
||||
case OWSReactionProcessingResultAssociatedMessageMissing:
|
||||
[OWSEarlyMessageManager recordEarlyEnvelope:envelope
|
||||
plainTextData:plaintextData
|
||||
wasReceivedByUD:wasReceivedByUD
|
||||
associatedMessageTimestamp:dataMessage.reaction.timestamp
|
||||
associatedMessageAuthor:dataMessage.reaction.authorAddress];
|
||||
[self.earlyMessageManager recordEarlyEnvelope:envelope
|
||||
plainTextData:plaintextData
|
||||
wasReceivedByUD:wasReceivedByUD
|
||||
associatedMessageTimestamp:dataMessage.reaction.timestamp
|
||||
associatedMessageAuthor:dataMessage.reaction.authorAddress];
|
||||
break;
|
||||
}
|
||||
} else if (dataMessage.delete != nil) {
|
||||
@ -1515,11 +1520,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
OWSLogError(@"Failed to remotely delete message: %llu", dataMessage.delete.targetSentTimestamp);
|
||||
break;
|
||||
case OWSRemoteDeleteProcessingResultDeletedMessageMissing:
|
||||
[OWSEarlyMessageManager recordEarlyEnvelope:envelope
|
||||
plainTextData:plaintextData
|
||||
wasReceivedByUD:wasReceivedByUD
|
||||
associatedMessageTimestamp:dataMessage.delete.targetSentTimestamp
|
||||
associatedMessageAuthor:envelope.sourceAddress];
|
||||
[self.earlyMessageManager recordEarlyEnvelope:envelope
|
||||
plainTextData:plaintextData
|
||||
wasReceivedByUD:wasReceivedByUD
|
||||
associatedMessageTimestamp:dataMessage.delete.targetSentTimestamp
|
||||
associatedMessageAuthor:envelope.sourceAddress];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@ -1577,9 +1582,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
readTimestamp:envelope.timestamp
|
||||
transaction:transaction];
|
||||
for (SSKProtoSyncMessageRead *readReceiptProto in earlyReceipts) {
|
||||
[OWSEarlyMessageManager recordEarlyReadReceiptFromLinkedDeviceWithTimestamp:envelope.timestamp
|
||||
associatedMessageTimestamp:readReceiptProto.timestamp
|
||||
associatedMessageAuthor:readReceiptProto.senderAddress];
|
||||
[self.earlyMessageManager
|
||||
recordEarlyReadReceiptFromLinkedDeviceWithTimestamp:envelope.timestamp
|
||||
associatedMessageTimestamp:readReceiptProto.timestamp
|
||||
associatedMessageAuthor:readReceiptProto.senderAddress];
|
||||
}
|
||||
} else if (syncMessage.verified) {
|
||||
OWSLogInfo(@"Received verification state for %@", syncMessage.verified.destinationAddress);
|
||||
@ -1603,11 +1609,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
case OWSViewOnceSyncMessageProcessingResultInvalidSyncMessage:
|
||||
break;
|
||||
case OWSViewOnceSyncMessageProcessingResultAssociatedMessageMissing:
|
||||
[OWSEarlyMessageManager recordEarlyEnvelope:envelope
|
||||
plainTextData:plaintextData
|
||||
wasReceivedByUD:wasReceivedByUD
|
||||
associatedMessageTimestamp:syncMessage.viewOnceOpen.timestamp
|
||||
associatedMessageAuthor:syncMessage.viewOnceOpen.senderAddress];
|
||||
[self.earlyMessageManager recordEarlyEnvelope:envelope
|
||||
plainTextData:plaintextData
|
||||
wasReceivedByUD:wasReceivedByUD
|
||||
associatedMessageTimestamp:syncMessage.viewOnceOpen.timestamp
|
||||
associatedMessageAuthor:syncMessage.viewOnceOpen.senderAddress];
|
||||
break;
|
||||
}
|
||||
} else if (syncMessage.configuration) {
|
||||
@ -1903,11 +1909,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
case OWSReactionProcessingResultInvalidReaction:
|
||||
break;
|
||||
case OWSReactionProcessingResultAssociatedMessageMissing:
|
||||
[OWSEarlyMessageManager recordEarlyEnvelope:envelope
|
||||
plainTextData:plaintextData
|
||||
wasReceivedByUD:wasReceivedByUD
|
||||
associatedMessageTimestamp:dataMessage.reaction.timestamp
|
||||
associatedMessageAuthor:dataMessage.reaction.authorAddress];
|
||||
[self.earlyMessageManager recordEarlyEnvelope:envelope
|
||||
plainTextData:plaintextData
|
||||
wasReceivedByUD:wasReceivedByUD
|
||||
associatedMessageTimestamp:dataMessage.reaction.timestamp
|
||||
associatedMessageAuthor:dataMessage.reaction.authorAddress];
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1929,11 +1935,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
OWSLogError(@"Failed to remotely delete message: %llu", dataMessage.delete.targetSentTimestamp);
|
||||
break;
|
||||
case OWSRemoteDeleteProcessingResultDeletedMessageMissing:
|
||||
[OWSEarlyMessageManager recordEarlyEnvelope:envelope
|
||||
plainTextData:plaintextData
|
||||
wasReceivedByUD:wasReceivedByUD
|
||||
associatedMessageTimestamp:dataMessage.delete.targetSentTimestamp
|
||||
associatedMessageAuthor:envelope.sourceAddress];
|
||||
[self.earlyMessageManager recordEarlyEnvelope:envelope
|
||||
plainTextData:plaintextData
|
||||
wasReceivedByUD:wasReceivedByUD
|
||||
associatedMessageTimestamp:dataMessage.delete.targetSentTimestamp
|
||||
associatedMessageAuthor:envelope.sourceAddress];
|
||||
break;
|
||||
}
|
||||
return nil;
|
||||
@ -2021,7 +2027,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
[incomingMessage anyInsertWithTransaction:transaction];
|
||||
|
||||
[OWSEarlyMessageManager applyPendingMessagesFor:incomingMessage transaction:transaction];
|
||||
[self.earlyMessageManager applyPendingMessagesFor:incomingMessage transaction:transaction];
|
||||
|
||||
// Any messages sent from the current user - from this device or another - should be automatically marked as read.
|
||||
if (envelope.sourceAddress.isLocalAddress) {
|
||||
|
||||
@ -8,6 +8,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@class BulkProfileFetch;
|
||||
@class BulkUUIDLookup;
|
||||
@class ContactsUpdater;
|
||||
@class EarlyMessageManager;
|
||||
@class GroupsV2MessageProcessor;
|
||||
@class MessageFetcherJob;
|
||||
@class MessageProcessing;
|
||||
@ -105,7 +106,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
messageFetcherJob:(MessageFetcherJob *)messageFetcherJob
|
||||
bulkProfileFetch:(BulkProfileFetch *)bulkProfileFetch
|
||||
bulkUUIDLookup:(BulkUUIDLookup *)bulkUUIDLookup
|
||||
versionedProfiles:(id<VersionedProfiles>)versionedProfiles NS_DESIGNATED_INITIALIZER;
|
||||
versionedProfiles:(id<VersionedProfiles>)versionedProfiles
|
||||
earlyMessageManager:(EarlyMessageManager *)earlyMessageManager NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@property (nonatomic, readonly, class) SSKEnvironment *shared;
|
||||
|
||||
@ -163,6 +165,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (nonatomic, readonly) BulkProfileFetch *bulkProfileFetch;
|
||||
@property (nonatomic, readonly) BulkUUIDLookup *bulkUUIDLookup;
|
||||
@property (nonatomic, readonly) id<VersionedProfiles> versionedProfiles;
|
||||
@property (nonatomic, readonly) EarlyMessageManager *earlyMessageManager;
|
||||
|
||||
@property (nonatomic, readonly, nullable) OWSPrimaryStorage *primaryStorage;
|
||||
|
||||
|
||||
@ -52,6 +52,7 @@ static SSKEnvironment *sharedSSKEnvironment;
|
||||
@property (nonatomic) BulkProfileFetch *bulkProfileFetch;
|
||||
@property (nonatomic) BulkUUIDLookup *bulkUUIDLookup;
|
||||
@property (nonatomic) id<VersionedProfiles> versionedProfiles;
|
||||
@property (nonatomic) EarlyMessageManager *earlyMessageManager;
|
||||
|
||||
@end
|
||||
|
||||
@ -109,6 +110,7 @@ static SSKEnvironment *sharedSSKEnvironment;
|
||||
bulkProfileFetch:(BulkProfileFetch *)bulkProfileFetch
|
||||
bulkUUIDLookup:(BulkUUIDLookup *)bulkUUIDLookup
|
||||
versionedProfiles:(id<VersionedProfiles>)versionedProfiles
|
||||
earlyMessageManager:(EarlyMessageManager *)earlyMessageManager
|
||||
{
|
||||
self = [super init];
|
||||
if (!self) {
|
||||
@ -160,6 +162,7 @@ static SSKEnvironment *sharedSSKEnvironment;
|
||||
OWSAssertDebug(bulkProfileFetch);
|
||||
OWSAssertDebug(versionedProfiles);
|
||||
OWSAssertDebug(bulkUUIDLookup);
|
||||
OWSAssertDebug(earlyMessageManager);
|
||||
|
||||
_contactsManager = contactsManager;
|
||||
_linkPreviewManager = linkPreviewManager;
|
||||
@ -207,6 +210,7 @@ static SSKEnvironment *sharedSSKEnvironment;
|
||||
_bulkProfileFetch = bulkProfileFetch;
|
||||
_versionedProfiles = versionedProfiles;
|
||||
_bulkUUIDLookup = bulkUUIDLookup;
|
||||
_earlyMessageManager = earlyMessageManager;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -108,6 +108,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
BulkProfileFetch *bulkProfileFetch = [BulkProfileFetch new];
|
||||
BulkUUIDLookup *bulkUUIDLookup = [BulkUUIDLookup new];
|
||||
id<VersionedProfiles> versionedProfiles = [MockVersionedProfiles new];
|
||||
EarlyMessageManager *earlyMessageManager = [EarlyMessageManager new];
|
||||
|
||||
self = [super initWithContactsManager:contactsManager
|
||||
linkPreviewManager:linkPreviewManager
|
||||
@ -154,7 +155,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
messageFetcherJob:messageFetcherJob
|
||||
bulkProfileFetch:bulkProfileFetch
|
||||
bulkUUIDLookup:bulkUUIDLookup
|
||||
versionedProfiles:versionedProfiles];
|
||||
versionedProfiles:versionedProfiles
|
||||
earlyMessageManager:earlyMessageManager];
|
||||
|
||||
if (!self) {
|
||||
return nil;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user