Compare commits
2 Commits
master
...
charlesmch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a01f2bc58 | ||
|
|
3073c98ca0 |
@ -157,6 +157,8 @@ typedef NS_ENUM(NSInteger, TSGroupMetaMessage) {
|
||||
// This isn't a perfect arrangement, but in practice this will prevent
|
||||
// data loss and will resolve all known issues.
|
||||
- (void)updateWithMessageState:(TSOutgoingMessageState)messageState;
|
||||
- (void)updateWithMessageState:(TSOutgoingMessageState)messageState
|
||||
transaction:(YapDatabaseReadWriteTransaction *)transaction;
|
||||
- (void)updateWithSendingError:(NSError *)error;
|
||||
- (void)updateWithHasSyncedTranscript:(BOOL)hasSyncedTranscript;
|
||||
- (void)updateWithCustomMessage:(NSString *)customMessage transaction:(YapDatabaseReadWriteTransaction *)transaction;
|
||||
|
||||
@ -257,13 +257,21 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
|
||||
- (void)updateWithMessageState:(TSOutgoingMessageState)messageState
|
||||
{
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self applyChangeToSelfAndLatestOutgoingMessage:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message setMessageState:messageState];
|
||||
}];
|
||||
[self updateWithMessageState:messageState transaction:transaction];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)updateWithMessageState:(TSOutgoingMessageState)messageState
|
||||
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
OWSAssert(transaction);
|
||||
|
||||
[self applyChangeToSelfAndLatestOutgoingMessage:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message setMessageState:messageState];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)updateWithHasSyncedTranscript:(BOOL)hasSyncedTranscript
|
||||
{
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
|
||||
@ -1,38 +1,39 @@
|
||||
// Created by Michael Kirk on 9/23/16.
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class TSStorageManager;
|
||||
@class TSMessage;
|
||||
@class TSThread;
|
||||
@class YapDatabaseReadTransaction;
|
||||
@class YapDatabaseReadWriteTransaction;
|
||||
|
||||
@interface OWSDisappearingMessagesFinder : NSObject
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
- (instancetype)initWithStorageManager:(TSStorageManager *)storageManager NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
+ (instancetype)defaultInstance;
|
||||
|
||||
- (void)enumerateExpiredMessagesWithBlock:(void (^_Nonnull)(TSMessage *message))block;
|
||||
- (void)enumerateUnstartedExpiringMessagesInThread:(TSThread *)thread block:(void (^_Nonnull)(TSMessage *message))block;
|
||||
- (void)enumerateExpiredMessagesWithBlock:(void (^_Nonnull)(TSMessage *message))block
|
||||
transaction:(YapDatabaseReadWriteTransaction *_Nonnull)transaction;
|
||||
- (void)enumerateUnstartedExpiringMessagesInThread:(TSThread *)thread
|
||||
block:(void (^_Nonnull)(TSMessage *message))block
|
||||
transaction:(YapDatabaseReadWriteTransaction *_Nonnull)transaction;
|
||||
|
||||
/**
|
||||
* @return
|
||||
* uint64_t millisecond timestamp wrapped in a number. Retrieve with `unsignedLongLongvalue`.
|
||||
* or nil if there are no upcoming expired messages
|
||||
*/
|
||||
- (nullable NSNumber *)nextExpirationTimestamp;
|
||||
- (nullable NSNumber *)nextExpirationTimestampWithTransaction:(YapDatabaseReadTransaction *_Nonnull)transaction;
|
||||
|
||||
/**
|
||||
* Database extensions required for class to work.
|
||||
*/
|
||||
- (void)asyncRegisterDatabaseExtensions;
|
||||
+ (void)asyncRegisterDatabaseExtensions:(TSStorageManager *)storageManager;
|
||||
|
||||
/**
|
||||
* Only use the sync version for testing, generally we'll want to register extensions async
|
||||
*/
|
||||
- (void)blockingRegisterDatabaseExtensions;
|
||||
+ (void)blockingRegisterDatabaseExtensions:(TSStorageManager *)storageManager;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
// Created by Michael Kirk on 9/23/16.
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSDisappearingMessagesFinder.h"
|
||||
#import "NSDate+millisecondTimeStamp.h"
|
||||
@ -17,40 +18,13 @@ static NSString *const OWSDisappearingMessageFinderThreadIdColumn = @"thread_id"
|
||||
static NSString *const OWSDisappearingMessageFinderExpiresAtColumn = @"expires_at";
|
||||
static NSString *const OWSDisappearingMessageFinderExpiresAtIndex = @"index_messages_on_expires_at_and_thread_id_v2";
|
||||
|
||||
@interface OWSDisappearingMessagesFinder ()
|
||||
|
||||
@property (nonatomic, readonly) TSStorageManager *storageManager;
|
||||
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OWSDisappearingMessagesFinder
|
||||
|
||||
- (instancetype)initWithStorageManager:(TSStorageManager *)storageManager
|
||||
{
|
||||
self = [super init];
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
_storageManager = storageManager;
|
||||
_dbConnection = [storageManager newDatabaseConnection];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)defaultInstance
|
||||
{
|
||||
static OWSDisappearingMessagesFinder *defaultInstance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
defaultInstance = [[self alloc] initWithStorageManager:[TSStorageManager sharedManager]];
|
||||
});
|
||||
return defaultInstance;
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)fetchUnstartedExpiringMessageIdsInThread:(TSThread *)thread
|
||||
transaction:(YapDatabaseReadWriteTransaction *_Nonnull)transaction
|
||||
{
|
||||
OWSAssert(transaction);
|
||||
|
||||
NSMutableArray<NSString *> *messageIds = [NSMutableArray new];
|
||||
NSString *formattedString = [NSString stringWithFormat:@"WHERE %@ = 0 AND %@ = \"%@\"",
|
||||
OWSDisappearingMessageFinderExpiresAtColumn,
|
||||
@ -58,19 +32,19 @@ static NSString *const OWSDisappearingMessageFinderExpiresAtIndex = @"index_mess
|
||||
thread.uniqueId];
|
||||
|
||||
YapDatabaseQuery *query = [YapDatabaseQuery queryWithFormat:formattedString];
|
||||
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
[[transaction ext:OWSDisappearingMessageFinderExpiresAtIndex]
|
||||
enumerateKeysMatchingQuery:query
|
||||
usingBlock:^void(NSString *collection, NSString *key, BOOL *stop) {
|
||||
[messageIds addObject:key];
|
||||
}];
|
||||
}];
|
||||
[[transaction ext:OWSDisappearingMessageFinderExpiresAtIndex]
|
||||
enumerateKeysMatchingQuery:query
|
||||
usingBlock:^void(NSString *collection, NSString *key, BOOL *stop) {
|
||||
[messageIds addObject:key];
|
||||
}];
|
||||
|
||||
return [messageIds copy];
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)fetchExpiredMessageIds
|
||||
- (NSArray<NSString *> *)fetchExpiredMessageIdsWithTransaction:(YapDatabaseReadWriteTransaction *_Nonnull)transaction
|
||||
{
|
||||
OWSAssert(transaction);
|
||||
|
||||
NSMutableArray<NSString *> *messageIds = [NSMutableArray new];
|
||||
|
||||
uint64_t now = [NSDate ows_millisecondTimeStamp];
|
||||
@ -80,33 +54,31 @@ static NSString *const OWSDisappearingMessageFinderExpiresAtIndex = @"index_mess
|
||||
OWSDisappearingMessageFinderExpiresAtColumn,
|
||||
now];
|
||||
YapDatabaseQuery *query = [YapDatabaseQuery queryWithFormat:formattedString];
|
||||
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
[[transaction ext:OWSDisappearingMessageFinderExpiresAtIndex]
|
||||
enumerateKeysMatchingQuery:query
|
||||
usingBlock:^void(NSString *collection, NSString *key, BOOL *stop) {
|
||||
[messageIds addObject:key];
|
||||
}];
|
||||
}];
|
||||
[[transaction ext:OWSDisappearingMessageFinderExpiresAtIndex]
|
||||
enumerateKeysMatchingQuery:query
|
||||
usingBlock:^void(NSString *collection, NSString *key, BOOL *stop) {
|
||||
[messageIds addObject:key];
|
||||
}];
|
||||
|
||||
return [messageIds copy];
|
||||
}
|
||||
|
||||
- (nullable NSNumber *)nextExpirationTimestamp
|
||||
- (nullable NSNumber *)nextExpirationTimestampWithTransaction:(YapDatabaseReadTransaction *_Nonnull)transaction
|
||||
{
|
||||
OWSAssert(transaction);
|
||||
|
||||
NSString *formattedString = [NSString stringWithFormat:@"WHERE %@ > 0 ORDER BY %@ ASC",
|
||||
OWSDisappearingMessageFinderExpiresAtColumn,
|
||||
OWSDisappearingMessageFinderExpiresAtColumn];
|
||||
YapDatabaseQuery *query = [YapDatabaseQuery queryWithFormat:formattedString];
|
||||
|
||||
__block TSMessage *firstMessage;
|
||||
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
[[transaction ext:OWSDisappearingMessageFinderExpiresAtIndex]
|
||||
enumerateKeysAndObjectsMatchingQuery:query
|
||||
usingBlock:^void(NSString *collection, NSString *key, id object, BOOL *stop) {
|
||||
firstMessage = (TSMessage *)object;
|
||||
*stop = YES;
|
||||
}];
|
||||
}];
|
||||
[[transaction ext:OWSDisappearingMessageFinderExpiresAtIndex]
|
||||
enumerateKeysAndObjectsMatchingQuery:query
|
||||
usingBlock:^void(NSString *collection, NSString *key, id object, BOOL *stop) {
|
||||
firstMessage = (TSMessage *)object;
|
||||
*stop = YES;
|
||||
}];
|
||||
|
||||
if (firstMessage && firstMessage.expiresAt > 0) {
|
||||
return [NSNumber numberWithUnsignedLongLong:firstMessage.expiresAt];
|
||||
@ -115,10 +87,15 @@ static NSString *const OWSDisappearingMessageFinderExpiresAtIndex = @"index_mess
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)enumerateUnstartedExpiringMessagesInThread:(TSThread *)thread block:(void (^_Nonnull)(TSMessage *message))block
|
||||
- (void)enumerateUnstartedExpiringMessagesInThread:(TSThread *)thread
|
||||
block:(void (^_Nonnull)(TSMessage *message))block
|
||||
transaction:(YapDatabaseReadWriteTransaction *_Nonnull)transaction
|
||||
{
|
||||
for (NSString *expiringMessageId in [self fetchUnstartedExpiringMessageIdsInThread:thread]) {
|
||||
TSMessage *_Nullable message = [TSMessage fetchObjectWithUniqueID:expiringMessageId];
|
||||
OWSAssert(transaction);
|
||||
|
||||
for (NSString *expiringMessageId in
|
||||
[self fetchUnstartedExpiringMessageIdsInThread:thread transaction:transaction]) {
|
||||
TSMessage *_Nullable message = [TSMessage fetchObjectWithUniqueID:expiringMessageId transaction:transaction];
|
||||
if ([message isKindOfClass:[TSMessage class]]) {
|
||||
block(message);
|
||||
} else {
|
||||
@ -132,23 +109,30 @@ static NSString *const OWSDisappearingMessageFinderExpiresAtIndex = @"index_mess
|
||||
* We don't want to instantiate potentially many messages at once.
|
||||
*/
|
||||
- (NSArray<TSMessage *> *)fetchUnstartedExpiringMessagesInThread:(TSThread *)thread
|
||||
transaction:(YapDatabaseReadWriteTransaction *_Nonnull)transaction
|
||||
{
|
||||
OWSAssert(transaction);
|
||||
|
||||
NSMutableArray<TSMessage *> *messages = [NSMutableArray new];
|
||||
[self enumerateUnstartedExpiringMessagesInThread:thread
|
||||
block:^(TSMessage *_Nonnull message) {
|
||||
[messages addObject:message];
|
||||
}];
|
||||
}
|
||||
transaction:transaction];
|
||||
|
||||
return [messages copy];
|
||||
}
|
||||
|
||||
|
||||
- (void)enumerateExpiredMessagesWithBlock:(void (^_Nonnull)(TSMessage *message))block
|
||||
transaction:(YapDatabaseReadWriteTransaction *_Nonnull)transaction
|
||||
{
|
||||
OWSAssert(transaction);
|
||||
|
||||
// Since we can't directly mutate the enumerated expired messages, we store only their ids in hopes of saving a
|
||||
// little memory and then enumerate the (larger) TSMessage objects one at a time.
|
||||
for (NSString *expiredMessageId in [self fetchExpiredMessageIds]) {
|
||||
TSMessage *_Nullable message = [TSMessage fetchObjectWithUniqueID:expiredMessageId];
|
||||
for (NSString *expiredMessageId in [self fetchExpiredMessageIdsWithTransaction:transaction]) {
|
||||
TSMessage *_Nullable message = [TSMessage fetchObjectWithUniqueID:expiredMessageId transaction:transaction];
|
||||
if ([message isKindOfClass:[TSMessage class]]) {
|
||||
block(message);
|
||||
} else {
|
||||
@ -161,19 +145,22 @@ static NSString *const OWSDisappearingMessageFinderExpiresAtIndex = @"index_mess
|
||||
* Don't use this in production. Useful for testing.
|
||||
* We don't want to instantiate potentially many messages at once.
|
||||
*/
|
||||
- (NSArray<TSMessage *> *)fetchExpiredMessages
|
||||
- (NSArray<TSMessage *> *)fetchExpiredMessagesWithTransaction:(YapDatabaseReadWriteTransaction *_Nonnull)transaction
|
||||
{
|
||||
OWSAssert(transaction);
|
||||
|
||||
NSMutableArray<TSMessage *> *messages = [NSMutableArray new];
|
||||
[self enumerateExpiredMessagesWithBlock:^(TSMessage *_Nonnull message) {
|
||||
[messages addObject:message];
|
||||
}];
|
||||
}
|
||||
transaction:transaction];
|
||||
|
||||
return [messages copy];
|
||||
}
|
||||
|
||||
#pragma mark - YapDatabaseExtension
|
||||
|
||||
- (YapDatabaseSecondaryIndex *)indexDatabaseExtension
|
||||
+ (YapDatabaseSecondaryIndex *)indexDatabaseExtension
|
||||
{
|
||||
YapDatabaseSecondaryIndexSetup *setup = [YapDatabaseSecondaryIndexSetup new];
|
||||
[setup addColumn:OWSDisappearingMessageFinderExpiresAtColumn withType:YapDatabaseSecondaryIndexTypeInteger];
|
||||
@ -202,23 +189,23 @@ static NSString *const OWSDisappearingMessageFinderExpiresAtIndex = @"index_mess
|
||||
}
|
||||
|
||||
// Useful for tests, don't use in app startup path because it's slow.
|
||||
- (void)blockingRegisterDatabaseExtensions
|
||||
+ (void)blockingRegisterDatabaseExtensions:(TSStorageManager *)storageManager
|
||||
{
|
||||
[self.storageManager.database registerExtension:[self indexDatabaseExtension]
|
||||
withName:OWSDisappearingMessageFinderExpiresAtIndex];
|
||||
[storageManager.database registerExtension:[self indexDatabaseExtension]
|
||||
withName:OWSDisappearingMessageFinderExpiresAtIndex];
|
||||
}
|
||||
|
||||
- (void)asyncRegisterDatabaseExtensions
|
||||
+ (void)asyncRegisterDatabaseExtensions:(TSStorageManager *)storageManager
|
||||
{
|
||||
[self.storageManager.database asyncRegisterExtension:[self indexDatabaseExtension]
|
||||
withName:OWSDisappearingMessageFinderExpiresAtIndex
|
||||
completionBlock:^(BOOL ready) {
|
||||
if (ready) {
|
||||
DDLogDebug(@"%@ completed registering extension async.", self.tag);
|
||||
} else {
|
||||
DDLogError(@"%@ failed registering extension async.", self.tag);
|
||||
}
|
||||
}];
|
||||
[storageManager.database asyncRegisterExtension:[self indexDatabaseExtension]
|
||||
withName:OWSDisappearingMessageFinderExpiresAtIndex
|
||||
completionBlock:^(BOOL ready) {
|
||||
if (ready) {
|
||||
DDLogDebug(@"%@ completed registering extension async.", self.tag);
|
||||
} else {
|
||||
DDLogError(@"%@ failed registering extension async.", self.tag);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Logging
|
||||
|
||||
@ -17,6 +17,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSDisappearingMessagesJob ()
|
||||
|
||||
// This property should only be accessed on the serialQueue.
|
||||
@property (nonatomic, readonly) TSStorageManager *storageManager;
|
||||
|
||||
// This property should only be accessed on the serialQueue.
|
||||
@property (nonatomic, readonly) OWSDisappearingMessagesFinder *disappearingMessagesFinder;
|
||||
|
||||
@ -48,7 +51,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return self;
|
||||
}
|
||||
|
||||
_disappearingMessagesFinder = [[OWSDisappearingMessagesFinder alloc] initWithStorageManager:storageManager];
|
||||
_storageManager = storageManager;
|
||||
_disappearingMessagesFinder = [OWSDisappearingMessagesFinder new];
|
||||
|
||||
OWSSingletonAssert();
|
||||
|
||||
@ -84,16 +88,20 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
uint64_t now = [NSDate ows_millisecondTimeStamp];
|
||||
|
||||
__block uint expirationCount = 0;
|
||||
[self.disappearingMessagesFinder enumerateExpiredMessagesWithBlock:^(TSMessage *message) {
|
||||
// sanity check
|
||||
if (message.expiresAt > now) {
|
||||
DDLogError(@"%@ Refusing to remove message which doesn't expire until: %lld", self.tag, message.expiresAt);
|
||||
return;
|
||||
}
|
||||
[self.storageManager.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
[self.disappearingMessagesFinder enumerateExpiredMessagesWithBlock:^(TSMessage *message) {
|
||||
// sanity check
|
||||
if (message.expiresAt > now) {
|
||||
DDLogError(
|
||||
@"%@ Refusing to remove message which doesn't expire until: %lld", self.tag, message.expiresAt);
|
||||
return;
|
||||
}
|
||||
|
||||
DDLogDebug(@"%@ Removing message which expired at: %lld", self.tag, message.expiresAt);
|
||||
[message remove];
|
||||
expirationCount++;
|
||||
DDLogDebug(@"%@ Removing message which expired at: %lld", self.tag, message.expiresAt);
|
||||
[message removeWithTransaction:transaction];
|
||||
expirationCount++;
|
||||
}
|
||||
transaction:transaction];
|
||||
}];
|
||||
|
||||
DDLogDebug(@"%@ Removed %u expired messages", self.tag, expirationCount);
|
||||
@ -106,7 +114,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
[self run];
|
||||
|
||||
uint64_t now = [NSDate ows_millisecondTimeStamp];
|
||||
NSNumber *nextExpirationTimestampNumber = [self.disappearingMessagesFinder nextExpirationTimestamp];
|
||||
__block NSNumber *nextExpirationTimestampNumber;
|
||||
[self.storageManager.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
nextExpirationTimestampNumber =
|
||||
[self.disappearingMessagesFinder nextExpirationTimestampWithTransaction:transaction];
|
||||
}];
|
||||
if (!nextExpirationTimestampNumber) {
|
||||
// In theory we could kill the loop here. It should resume when the next expiring message is saved,
|
||||
// But this is a safeguard for any race conditions that exist while running the job as a new message is saved.
|
||||
@ -142,15 +154,19 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
[self setExpirationForMessage:message expirationStartedAt:[NSDate ows_millisecondTimeStamp]];
|
||||
}
|
||||
|
||||
+ (void)setExpirationForMessage:(TSMessage *)message expirationStartedAt:(uint64_t)expirationStartedAt
|
||||
{
|
||||
dispatch_async(self.serialQueue, ^{
|
||||
[[self sharedJob] setExpirationForMessage:message expirationStartedAt:expirationStartedAt];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)setExpirationForMessage:(TSMessage *)message expirationStartedAt:(uint64_t)expirationStartedAt
|
||||
{
|
||||
[self.storageManager.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
[self setExpirationForMessage:message expirationStartedAt:expirationStartedAt transaction:transaction];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)setExpirationForMessage:(TSMessage *)message
|
||||
expirationStartedAt:(uint64_t)expirationStartedAt
|
||||
transaction:(YapDatabaseReadWriteTransaction *_Nonnull)transaction
|
||||
{
|
||||
OWSAssert(transaction);
|
||||
|
||||
if (!message.isExpiringMessage) {
|
||||
return;
|
||||
}
|
||||
@ -161,7 +177,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
// Don't clobber if multiple actions simultaneously triggered expiration.
|
||||
if (message.expireStartedAt == 0 || message.expireStartedAt > expirationStartedAt) {
|
||||
message.expireStartedAt = expirationStartedAt;
|
||||
[message save];
|
||||
[message saveWithTransaction:transaction];
|
||||
}
|
||||
|
||||
// Necessary that the async expiration run happens *after* the message is saved with expiration configuration.
|
||||
@ -178,16 +194,22 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (void)setExpirationsForThread:(TSThread *)thread
|
||||
{
|
||||
uint64_t now = [NSDate ows_millisecondTimeStamp];
|
||||
[self.disappearingMessagesFinder
|
||||
enumerateUnstartedExpiringMessagesInThread:thread
|
||||
block:^(TSMessage *_Nonnull message) {
|
||||
DDLogWarn(@"%@ Starting expiring message which should have already "
|
||||
@"been started.",
|
||||
self.tag);
|
||||
// specify "now" in case D.M. have since been disabled, but we have
|
||||
// existing unstarted expiring messages that still need to expire.
|
||||
[self setExpirationForMessage:message expirationStartedAt:now];
|
||||
}];
|
||||
[self.storageManager.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
[self.disappearingMessagesFinder
|
||||
enumerateUnstartedExpiringMessagesInThread:thread
|
||||
block:^(TSMessage *_Nonnull message) {
|
||||
DDLogWarn(
|
||||
@"%@ Starting expiring message which should have already "
|
||||
@"been started.",
|
||||
self.tag);
|
||||
// specify "now" in case D.M. have since been disabled, but we have
|
||||
// existing unstarted expiring messages that still need to expire.
|
||||
[self setExpirationForMessage:message
|
||||
expirationStartedAt:now
|
||||
transaction:transaction];
|
||||
}
|
||||
transaction:transaction];
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)becomeConsistentWithConfigurationForMessage:(TSMessage *)message
|
||||
|
||||
@ -36,33 +36,36 @@ static NSString *const OWSFailedAttachmentDownloadsJobAttachmentStateIndex = @"i
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)fetchAttemptingOutAttachmentIds:(YapDatabaseConnection *)dbConnection
|
||||
- (NSArray<NSString *> *)fetchAttemptingOutAttachmentIdsWithTransaction:
|
||||
(YapDatabaseReadWriteTransaction *_Nonnull)transaction
|
||||
{
|
||||
OWSAssert(transaction);
|
||||
|
||||
NSMutableArray<NSString *> *attachmentIds = [NSMutableArray new];
|
||||
|
||||
NSString *formattedString = [NSString stringWithFormat:@"WHERE %@ != %d",
|
||||
OWSFailedAttachmentDownloadsJobAttachmentStateColumn,
|
||||
(int)TSAttachmentPointerStateFailed];
|
||||
YapDatabaseQuery *query = [YapDatabaseQuery queryWithFormat:formattedString];
|
||||
[dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
[[transaction ext:OWSFailedAttachmentDownloadsJobAttachmentStateIndex]
|
||||
enumerateKeysMatchingQuery:query
|
||||
usingBlock:^void(NSString *collection, NSString *key, BOOL *stop) {
|
||||
[attachmentIds addObject:key];
|
||||
}];
|
||||
}];
|
||||
[[transaction ext:OWSFailedAttachmentDownloadsJobAttachmentStateIndex]
|
||||
enumerateKeysMatchingQuery:query
|
||||
usingBlock:^void(NSString *collection, NSString *key, BOOL *stop) {
|
||||
[attachmentIds addObject:key];
|
||||
}];
|
||||
|
||||
return [attachmentIds copy];
|
||||
}
|
||||
|
||||
- (void)enumerateAttemptingOutAttachmentsWithBlock:(void (^_Nonnull)(TSAttachmentPointer *attachment))block
|
||||
transaction:(YapDatabaseReadWriteTransaction *_Nonnull)transaction
|
||||
{
|
||||
YapDatabaseConnection *dbConnection = [self.storageManager newDatabaseConnection];
|
||||
OWSAssert(transaction);
|
||||
|
||||
// Since we can't directly mutate the enumerated attachments, we store only their ids in hopes
|
||||
// of saving a little memory and then enumerate the (larger) TSAttachment objects one at a time.
|
||||
for (NSString *attachmentId in [self fetchAttemptingOutAttachmentIds:dbConnection]) {
|
||||
TSAttachmentPointer *_Nullable attachment = [TSAttachmentPointer fetchObjectWithUniqueID:attachmentId];
|
||||
for (NSString *attachmentId in [self fetchAttemptingOutAttachmentIdsWithTransaction:transaction]) {
|
||||
TSAttachmentPointer *_Nullable attachment =
|
||||
[TSAttachmentPointer fetchObjectWithUniqueID:attachmentId transaction:transaction];
|
||||
if ([attachment isKindOfClass:[TSAttachmentPointer class]]) {
|
||||
block(attachment);
|
||||
} else {
|
||||
@ -74,15 +77,19 @@ static NSString *const OWSFailedAttachmentDownloadsJobAttachmentStateIndex = @"i
|
||||
- (void)run
|
||||
{
|
||||
__block uint count = 0;
|
||||
[self enumerateAttemptingOutAttachmentsWithBlock:^(TSAttachmentPointer *attachment) {
|
||||
// sanity check
|
||||
if (attachment.state != TSAttachmentPointerStateFailed) {
|
||||
DDLogDebug(@"%@ marking attachment as failed", self.tag);
|
||||
attachment.state = TSAttachmentPointerStateFailed;
|
||||
[attachment save];
|
||||
count++;
|
||||
}
|
||||
}];
|
||||
[[self.storageManager newDatabaseConnection]
|
||||
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
[self enumerateAttemptingOutAttachmentsWithBlock:^(TSAttachmentPointer *attachment) {
|
||||
// sanity check
|
||||
if (attachment.state != TSAttachmentPointerStateFailed) {
|
||||
DDLogDebug(@"%@ marking attachment as failed", self.tag);
|
||||
attachment.state = TSAttachmentPointerStateFailed;
|
||||
[attachment saveWithTransaction:transaction];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
transaction:transaction];
|
||||
}];
|
||||
|
||||
DDLogDebug(@"%@ Marked %u attachments as unsent", self.tag, count);
|
||||
}
|
||||
|
||||
@ -37,33 +37,36 @@ static NSString *const OWSFailedMessagesJobMessageStateIndex = @"index_outoing_m
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)fetchAttemptingOutMessageIds:(YapDatabaseConnection *)dbConnection
|
||||
- (NSArray<NSString *> *)fetchAttemptingOutMessageIdsWithTransaction:
|
||||
(YapDatabaseReadWriteTransaction *_Nonnull)transaction
|
||||
{
|
||||
OWSAssert(transaction);
|
||||
|
||||
NSMutableArray<NSString *> *messageIds = [NSMutableArray new];
|
||||
|
||||
NSString *formattedString = [NSString stringWithFormat:@"WHERE %@ == %d",
|
||||
OWSFailedMessagesJobMessageStateColumn,
|
||||
(int)TSOutgoingMessageStateAttemptingOut];
|
||||
YapDatabaseQuery *query = [YapDatabaseQuery queryWithFormat:formattedString];
|
||||
[dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
[[transaction ext:OWSFailedMessagesJobMessageStateIndex]
|
||||
enumerateKeysMatchingQuery:query
|
||||
usingBlock:^void(NSString *collection, NSString *key, BOOL *stop) {
|
||||
[messageIds addObject:key];
|
||||
}];
|
||||
}];
|
||||
[[transaction ext:OWSFailedMessagesJobMessageStateIndex]
|
||||
enumerateKeysMatchingQuery:query
|
||||
usingBlock:^void(NSString *collection, NSString *key, BOOL *stop) {
|
||||
[messageIds addObject:key];
|
||||
}];
|
||||
|
||||
return [messageIds copy];
|
||||
}
|
||||
|
||||
- (void)enumerateAttemptingOutMessagesWithBlock:(void (^_Nonnull)(TSOutgoingMessage *message))block
|
||||
transaction:(YapDatabaseReadWriteTransaction *_Nonnull)transaction
|
||||
{
|
||||
YapDatabaseConnection *dbConnection = [self.storageManager newDatabaseConnection];
|
||||
OWSAssert(transaction);
|
||||
|
||||
// Since we can't directly mutate the enumerated "attempting out" expired messages, we store only their ids in hopes
|
||||
// of saving a little memory and then enumerate the (larger) TSMessage objects one at a time.
|
||||
for (NSString *expiredMessageId in [self fetchAttemptingOutMessageIds:dbConnection]) {
|
||||
TSOutgoingMessage *_Nullable message = [TSOutgoingMessage fetchObjectWithUniqueID:expiredMessageId];
|
||||
for (NSString *expiredMessageId in [self fetchAttemptingOutMessageIdsWithTransaction:transaction]) {
|
||||
TSOutgoingMessage *_Nullable message =
|
||||
[TSOutgoingMessage fetchObjectWithUniqueID:expiredMessageId transaction:transaction];
|
||||
if ([message isKindOfClass:[TSOutgoingMessage class]]) {
|
||||
block(message);
|
||||
} else {
|
||||
@ -75,18 +78,26 @@ static NSString *const OWSFailedMessagesJobMessageStateIndex = @"index_outoing_m
|
||||
- (void)run
|
||||
{
|
||||
__block uint count = 0;
|
||||
[self enumerateAttemptingOutMessagesWithBlock:^(TSOutgoingMessage *message) {
|
||||
// sanity check
|
||||
OWSAssert(message.messageState == TSOutgoingMessageStateAttemptingOut);
|
||||
if (message.messageState != TSOutgoingMessageStateAttemptingOut) {
|
||||
DDLogError(@"%@ Refusing to mark as unsent message with state: %d", self.tag, (int)message.messageState);
|
||||
return;
|
||||
}
|
||||
|
||||
DDLogDebug(@"%@ marking message as unsent", self.tag);
|
||||
[message updateWithMessageState:TSOutgoingMessageStateUnsent];
|
||||
count++;
|
||||
}];
|
||||
[[self.storageManager newDatabaseConnection]
|
||||
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
[self enumerateAttemptingOutMessagesWithBlock:^(TSOutgoingMessage *message) {
|
||||
// sanity check
|
||||
OWSAssert(message.messageState == TSOutgoingMessageStateAttemptingOut);
|
||||
if (message.messageState != TSOutgoingMessageStateAttemptingOut) {
|
||||
DDLogError(
|
||||
@"%@ Refusing to mark as unsent message with state: %d", self.tag, (int)message.messageState);
|
||||
return;
|
||||
}
|
||||
|
||||
DDLogDebug(@"%@ marking message as unsent: %@", self.tag, message.uniqueId);
|
||||
[message updateWithMessageState:TSOutgoingMessageStateUnsent transaction:transaction];
|
||||
OWSAssert(message.messageState == TSOutgoingMessageStateUnsent);
|
||||
|
||||
count++;
|
||||
}
|
||||
transaction:transaction];
|
||||
}];
|
||||
|
||||
DDLogDebug(@"%@ Marked %u messages as unsent", self.tag, count);
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ typedef enum {
|
||||
RPRecentCallTypeOutgoingIncomplete,
|
||||
RPRecentCallTypeIncomingIncomplete,
|
||||
RPRecentCallTypeMissedBecauseOfChangedIdentity,
|
||||
RPRecentCallTypeDeclined,
|
||||
} RPRecentCallType;
|
||||
|
||||
@interface TSCall : TSInteraction <OWSReadTracking>
|
||||
|
||||
@ -76,6 +76,9 @@ NSUInteger TSCallCurrentSchemaVersion = 1;
|
||||
return NSLocalizedString(@"INCOMING_INCOMPLETE_CALL", @"");
|
||||
case RPRecentCallTypeMissedBecauseOfChangedIdentity:
|
||||
return NSLocalizedString(@"INFO_MESSAGE_MISSED_CALL_DUE_TO_CHANGED_IDENITY", @"info message text shown in conversation view");
|
||||
case RPRecentCallTypeDeclined:
|
||||
return NSLocalizedString(@"INFO_MESSAGE_CALL_DECLINED",
|
||||
@"Message in conversation history that indicates a declined incoming call.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -206,8 +206,7 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass";
|
||||
[[OWSIncomingMessageFinder new] asyncRegisterExtension];
|
||||
[TSDatabaseView asyncRegisterSecondaryDevicesDatabaseView];
|
||||
[OWSReadReceipt asyncRegisterIndexOnSenderIdAndTimestampWithDatabase:self.database];
|
||||
OWSDisappearingMessagesFinder *finder = [[OWSDisappearingMessagesFinder alloc] initWithStorageManager:self];
|
||||
[finder asyncRegisterDatabaseExtensions];
|
||||
[OWSDisappearingMessagesFinder asyncRegisterDatabaseExtensions:self];
|
||||
OWSFailedMessagesJob *failedMessagesJob = [[OWSFailedMessagesJob alloc] initWithStorageManager:self];
|
||||
[failedMessagesJob asyncRegisterDatabaseExtensions];
|
||||
OWSFailedAttachmentDownloadsJob *failedAttachmentDownloadsMessagesJob =
|
||||
|
||||
Loading…
Reference in New Issue
Block a user