mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			150 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Matlab
		
	
		
		
			
		
	
	
			150 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Matlab
		
	
| 
											5 years ago
										 | // | ||
|  | //  Copyright (c) 2018 Open Whisper Systems. All rights reserved. | ||
|  | // | ||
|  | 
 | ||
|  | #import "OWSFailedMessagesJob.h" | ||
|  | #import "OWSPrimaryStorage.h" | ||
|  | #import "TSMessage.h" | ||
|  | #import "TSOutgoingMessage.h" | ||
|  | #import <YapDatabase/YapDatabase.h> | ||
|  | #import <YapDatabase/YapDatabaseQuery.h> | ||
|  | #import <YapDatabase/YapDatabaseSecondaryIndex.h> | ||
|  | #import <SignalUtilitiesKit/SignalUtilitiesKit-Swift.h> | ||
|  | 
 | ||
|  | NS_ASSUME_NONNULL_BEGIN | ||
|  | 
 | ||
|  | static NSString *const OWSFailedMessagesJobMessageStateColumn = @"message_state"; | ||
|  | static NSString *const OWSFailedMessagesJobMessageStateIndex = @"index_outoing_messages_on_message_state"; | ||
|  | 
 | ||
|  | @interface OWSFailedMessagesJob () | ||
|  | 
 | ||
|  | @property (nonatomic, readonly) OWSPrimaryStorage *primaryStorage; | ||
|  | 
 | ||
|  | @end | ||
|  | 
 | ||
|  | #pragma mark - | ||
|  | 
 | ||
|  | @implementation OWSFailedMessagesJob | ||
|  | 
 | ||
|  | - (instancetype)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage | ||
|  | { | ||
|  |     self = [super init]; | ||
|  |     if (!self) { | ||
|  |         return self; | ||
|  |     } | ||
|  | 
 | ||
|  |     _primaryStorage = primaryStorage; | ||
|  | 
 | ||
|  |     return self; | ||
|  | } | ||
|  | 
 | ||
|  | - (NSArray<NSString *> *)fetchAttemptingOutMessageIdsWithTransaction: | ||
|  |     (YapDatabaseReadWriteTransaction *_Nonnull)transaction | ||
|  | { | ||
|  |     OWSAssertDebug(transaction); | ||
|  | 
 | ||
|  |     NSMutableArray<NSString *> *messageIds = [NSMutableArray new]; | ||
|  | 
 | ||
|  |     NSString *formattedString = [NSString | ||
|  |         stringWithFormat:@"WHERE %@ == %d", OWSFailedMessagesJobMessageStateColumn, (int)TSOutgoingMessageStateSending]; | ||
|  |     YapDatabaseQuery *query = [YapDatabaseQuery queryWithFormat:formattedString]; | ||
|  |     [[transaction ext:OWSFailedMessagesJobMessageStateIndex] | ||
|  |         enumerateKeysMatchingQuery:query | ||
|  |                         usingBlock:^void(NSString *collection, NSString *key, BOOL *stop) { | ||
|  |                             if (key == nil) { return; } | ||
|  |                             [messageIds addObject:key]; | ||
|  |                         }]; | ||
|  | 
 | ||
|  |     return [messageIds copy]; | ||
|  | } | ||
|  | 
 | ||
|  | - (void)enumerateAttemptingOutMessagesWithBlock:(void (^_Nonnull)(TSOutgoingMessage *message))block | ||
|  |                                     transaction:(YapDatabaseReadWriteTransaction *_Nonnull)transaction | ||
|  | { | ||
|  |     OWSAssertDebug(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 fetchAttemptingOutMessageIdsWithTransaction:transaction]) { | ||
|  |         TSOutgoingMessage *_Nullable message = | ||
|  |             [TSOutgoingMessage fetchObjectWithUniqueID:expiredMessageId transaction:transaction]; | ||
|  |         if ([message isKindOfClass:[TSOutgoingMessage class]]) { | ||
|  |             block(message); | ||
|  |         } else { | ||
|  |             OWSLogError(@"unexpected object: %@", message); | ||
|  |         } | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | - (void)run | ||
|  | { | ||
|  |     __block uint count = 0; | ||
|  | 
 | ||
|  |     [LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { | ||
|  |         [self enumerateAttemptingOutMessagesWithBlock:^(TSOutgoingMessage *message) { | ||
|  |             // sanity check | ||
|  |             OWSAssertDebug(message.messageState == TSOutgoingMessageStateSending); | ||
|  |             if (message.messageState != TSOutgoingMessageStateSending) { | ||
|  |                 OWSLogError(@"Refusing to mark as unsent message with state: %d", (int)message.messageState); | ||
|  |                 return; | ||
|  |             } | ||
|  | 
 | ||
|  |             OWSLogDebug(@"marking message as unsent: %@", message.uniqueId); | ||
|  |             [message updateWithAllSendingRecipientsMarkedAsFailedWithTansaction:transaction]; | ||
|  |             OWSAssertDebug(message.messageState == TSOutgoingMessageStateFailed); | ||
|  | 
 | ||
|  |             count++; | ||
|  |         } | ||
|  |                                           transaction:transaction]; | ||
|  |     }]; | ||
|  | 
 | ||
|  |     OWSLogDebug(@"Marked %u messages as unsent", count); | ||
|  | } | ||
|  | 
 | ||
|  | #pragma mark - YapDatabaseExtension | ||
|  | 
 | ||
|  | + (YapDatabaseSecondaryIndex *)indexDatabaseExtension | ||
|  | { | ||
|  |     YapDatabaseSecondaryIndexSetup *setup = [YapDatabaseSecondaryIndexSetup new]; | ||
|  |     [setup addColumn:OWSFailedMessagesJobMessageStateColumn withType:YapDatabaseSecondaryIndexTypeInteger]; | ||
|  | 
 | ||
|  |     YapDatabaseSecondaryIndexHandler *handler = | ||
|  |         [YapDatabaseSecondaryIndexHandler withObjectBlock:^(YapDatabaseReadTransaction *transaction, | ||
|  |             NSMutableDictionary *dict, | ||
|  |             NSString *collection, | ||
|  |             NSString *key, | ||
|  |             id object) { | ||
|  |             if (![object isKindOfClass:[TSOutgoingMessage class]]) { | ||
|  |                 return; | ||
|  |             } | ||
|  |             TSOutgoingMessage *message = (TSOutgoingMessage *)object; | ||
|  | 
 | ||
|  |             dict[OWSFailedMessagesJobMessageStateColumn] = @(message.messageState); | ||
|  |         }]; | ||
|  | 
 | ||
|  |     return [[YapDatabaseSecondaryIndex alloc] initWithSetup:setup handler:handler versionTag:nil]; | ||
|  | } | ||
|  | 
 | ||
|  | #ifdef DEBUG | ||
|  | // Useful for tests, don't use in app startup path because it's slow. | ||
|  | - (void)blockingRegisterDatabaseExtensions | ||
|  | { | ||
|  |     [self.primaryStorage registerExtension:[self.class indexDatabaseExtension] | ||
|  |                                   withName:OWSFailedMessagesJobMessageStateIndex]; | ||
|  | } | ||
|  | #endif | ||
|  | 
 | ||
|  | + (NSString *)databaseExtensionName | ||
|  | { | ||
|  |     return OWSFailedMessagesJobMessageStateIndex; | ||
|  | } | ||
|  | 
 | ||
|  | + (void)asyncRegisterDatabaseExtensionsWithPrimaryStorage:(OWSStorage *)storage | ||
|  | { | ||
|  |     [storage asyncRegisterExtension:[self indexDatabaseExtension] withName:OWSFailedMessagesJobMessageStateIndex]; | ||
|  | } | ||
|  | 
 | ||
|  | @end | ||
|  | 
 | ||
|  | NS_ASSUME_NONNULL_END |