Browse Source

Remove unused code

pull/330/head
Niels Andriesse 2 years ago
parent
commit
4c4ec0c039
  1. 1
      SessionMessagingKit/Database/OWSPrimaryStorage.m
  2. 1
      SessionMessagingKit/Meta/SessionMessagingKit.h
  3. 57
      SessionMessagingKit/Utilities/SSKJobRecord.h
  4. 127
      SessionMessagingKit/Utilities/SSKJobRecord.m
  5. 108
      SessionMessagingKit/Utilities/SSKJobRecordFinder.swift
  6. 16
      Signal.xcodeproj/project.pbxproj
  7. 303
      SignalUtilitiesKit/JobQueue.swift

1
SessionMessagingKit/Database/OWSPrimaryStorage.m

@ -179,7 +179,6 @@ void VerifyRegistrationsForPrimaryStorage(OWSStorage *storage)
[OWSDisappearingMessagesFinder asyncRegisterDatabaseExtensions:self];
[OWSMediaGalleryFinder asyncRegisterDatabaseExtensionsWithPrimaryStorage:self];
[TSDatabaseView asyncRegisterLazyRestoreAttachmentsDatabaseView:self];
[SSKJobRecordFinder asyncRegisterDatabaseExtensionObjCWithStorage:self];
[self.database
flushExtensionRequestsWithCompletionQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

1
SessionMessagingKit/Meta/SessionMessagingKit.h

@ -34,7 +34,6 @@ FOUNDATION_EXPORT const unsigned char SessionMessagingKitVersionString[];
#import <SessionMessagingKit/ProtoUtils.h>
#import <SessionMessagingKit/SignalRecipient.h>
#import <SessionMessagingKit/SSKEnvironment.h>
#import <SessionMessagingKit/SSKJobRecord.h>
#import <SessionMessagingKit/TSAccountManager.h>
#import <SessionMessagingKit/TSAttachment.h>
#import <SessionMessagingKit/TSAttachmentPointer.h>

57
SessionMessagingKit/Utilities/SSKJobRecord.h

@ -1,57 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <SessionUtilitiesKit/TSYapDatabaseObject.h>
NS_ASSUME_NONNULL_BEGIN
extern NSErrorDomain const SSKJobRecordErrorDomain;
typedef NS_ERROR_ENUM(SSKJobRecordErrorDomain, JobRecordError){
JobRecordError_AssertionError = 100,
JobRecordError_IllegalStateTransition,
};
typedef NS_ENUM(NSUInteger, SSKJobRecordStatus) {
SSKJobRecordStatus_Unknown,
SSKJobRecordStatus_Ready,
SSKJobRecordStatus_Running,
SSKJobRecordStatus_PermanentlyFailed,
SSKJobRecordStatus_Obsolete
};
#pragma mark -
@interface SSKJobRecord : TSYapDatabaseObject
@property (nonatomic) NSUInteger failureCount;
@property (nonatomic) NSString *label;
- (instancetype)initWithLabel:(NSString *)label NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithUniqueId:(NSString *_Nullable)uniqueId NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
@property (readonly, nonatomic) SSKJobRecordStatus status;
@property (nonatomic, readonly) UInt64 sortId;
- (BOOL)saveAsStartedWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
error:(NSError **)outError NS_SWIFT_NAME(saveAsStarted(transaction:));
- (void)saveAsPermanentlyFailedWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
NS_SWIFT_NAME(saveAsPermanentlyFailed(transaction:));
- (void)saveAsObsoleteWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
NS_SWIFT_NAME(saveAsObsolete(transaction:));
- (BOOL)saveRunningAsReadyWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
error:(NSError **)outError NS_SWIFT_NAME(saveRunningAsReady(transaction:));
- (BOOL)addFailureWithWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
error:(NSError **)outError NS_SWIFT_NAME(addFailure(transaction:));
@end
NS_ASSUME_NONNULL_END

127
SessionMessagingKit/Utilities/SSKJobRecord.m

@ -1,127 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "SSKJobRecord.h"
#import <SessionMessagingKit/SessionMessagingKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
NSErrorDomain const SSKJobRecordErrorDomain = @"SignalServiceKit.JobRecord";
#pragma mark -
@interface SSKJobRecord ()
@property (nonatomic) SSKJobRecordStatus status;
@property (nonatomic) UInt64 sortId;
@end
@implementation SSKJobRecord
- (instancetype)initWithLabel:(NSString *)label
{
self = [super init];
if (!self) {
return self;
}
_status = SSKJobRecordStatus_Ready;
_label = label;
return self;
}
- (nullable instancetype)initWithCoder:(NSCoder *)coder
{
return [super initWithCoder:coder];
}
#pragma mark - TSYapDatabaseObject Overrides
+ (NSString *)collection
{
// To avoid a plethora of identical JobRecord subclasses, all job records share
// a common collection and JobQueue's distinguish their behavior by the job's
// `label`
return @"JobRecord";
}
- (void)saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{
if (self.sortId == 0) {
self.sortId = [SSKIncrementingIdFinder nextIdWithKey:self.class.collection transaction:transaction];
}
[super saveWithTransaction:transaction];
}
#pragma mark -
- (BOOL)saveAsStartedWithTransaction:(YapDatabaseReadWriteTransaction *)transaction error:(NSError **)outError
{
if (self.status != SSKJobRecordStatus_Ready) {
*outError =
[NSError errorWithDomain:SSKJobRecordErrorDomain code:JobRecordError_IllegalStateTransition userInfo:nil];
return NO;
}
self.status = SSKJobRecordStatus_Running;
[self saveWithTransaction:transaction];
return YES;
}
- (void)saveAsPermanentlyFailedWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{
self.status = SSKJobRecordStatus_PermanentlyFailed;
[self saveWithTransaction:transaction];
}
- (void)saveAsObsoleteWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{
self.status = SSKJobRecordStatus_Obsolete;
[self saveWithTransaction:transaction];
}
- (BOOL)saveRunningAsReadyWithTransaction:(YapDatabaseReadWriteTransaction *)transaction error:(NSError **)outError
{
switch (self.status) {
case SSKJobRecordStatus_Running: {
self.status = SSKJobRecordStatus_Ready;
[self saveWithTransaction:transaction];
return YES;
}
case SSKJobRecordStatus_Ready:
case SSKJobRecordStatus_PermanentlyFailed:
case SSKJobRecordStatus_Obsolete:
case SSKJobRecordStatus_Unknown: {
*outError = [NSError errorWithDomain:SSKJobRecordErrorDomain
code:JobRecordError_IllegalStateTransition
userInfo:nil];
return NO;
}
}
}
- (BOOL)addFailureWithWithTransaction:(YapDatabaseReadWriteTransaction *)transaction error:(NSError **)outError
{
switch (self.status) {
case SSKJobRecordStatus_Running: {
self.failureCount++;
[self saveWithTransaction:transaction];
return YES;
}
case SSKJobRecordStatus_Ready:
case SSKJobRecordStatus_PermanentlyFailed:
case SSKJobRecordStatus_Obsolete:
case SSKJobRecordStatus_Unknown: {
*outError = [NSError errorWithDomain:SSKJobRecordErrorDomain
code:JobRecordError_IllegalStateTransition
userInfo:nil];
return NO;
}
}
}
@end
NS_ASSUME_NONNULL_END

108
SessionMessagingKit/Utilities/SSKJobRecordFinder.swift

@ -1,108 +0,0 @@
@objc(SSKJobRecordFinder)
public class JobRecordFinder: NSObject, Finder {
public typealias ExtensionType = YapDatabaseSecondaryIndex
public typealias TransactionType = YapDatabaseSecondaryIndexTransaction
public enum JobRecordField: String {
case status, label, sortId
}
public func getNextReady(label: String, transaction: YapDatabaseReadTransaction) -> SSKJobRecord? {
var result: SSKJobRecord?
self.enumerateJobRecords(label: label, status: .ready, transaction: transaction) { jobRecord, stopPointer in
result = jobRecord
stopPointer.pointee = true
}
return result
}
public func allRecords(label: String, status: SSKJobRecordStatus, transaction: YapDatabaseReadTransaction) -> [SSKJobRecord] {
var result: [SSKJobRecord] = []
self.enumerateJobRecords(label: label, status: status, transaction: transaction) { jobRecord, _ in
result.append(jobRecord)
}
return result
}
public func enumerateJobRecords(label: String, status: SSKJobRecordStatus, transaction: YapDatabaseReadTransaction, block: @escaping (SSKJobRecord, UnsafeMutablePointer<ObjCBool>) -> Void) {
let queryFormat = String(format: "WHERE %@ = ? AND %@ = ? ORDER BY %@", JobRecordField.status.rawValue, JobRecordField.label.rawValue, JobRecordField.sortId.rawValue)
let query = YapDatabaseQuery(string: queryFormat, parameters: [status.rawValue, label])
self.ext(transaction: transaction).enumerateKeysAndObjects(matching: query) { _, _, object, stopPointer in
guard let jobRecord = object as? SSKJobRecord else {
owsFailDebug("expecting jobRecord but found: \(object)")
return
}
block(jobRecord, stopPointer)
}
}
public static var dbExtensionName: String {
return "SecondaryIndexJobRecord"
}
@objc
public class func asyncRegisterDatabaseExtensionObjC(storage: OWSStorage) {
asyncRegisterDatabaseExtension(storage: storage)
}
public static var dbExtensionConfig: YapDatabaseSecondaryIndex {
let setup = YapDatabaseSecondaryIndexSetup()
setup.addColumn(JobRecordField.sortId.rawValue, with: .integer)
setup.addColumn(JobRecordField.status.rawValue, with: .integer)
setup.addColumn(JobRecordField.label.rawValue, with: .text)
let block: YapDatabaseSecondaryIndexWithObjectBlock = { transaction, dict, collection, key, object in
guard let jobRecord = object as? SSKJobRecord else {
return
}
dict[JobRecordField.sortId.rawValue] = jobRecord.sortId
dict[JobRecordField.status.rawValue] = jobRecord.status.rawValue
dict[JobRecordField.label.rawValue] = jobRecord.label
}
let handler = YapDatabaseSecondaryIndexHandler.withObjectBlock(block)
let options = YapDatabaseSecondaryIndexOptions()
let whitelist = YapWhitelistBlacklist(whitelist: Set([SSKJobRecord.collection()]))
options.allowedCollections = whitelist
return YapDatabaseSecondaryIndex.init(setup: setup, handler: handler, versionTag: "2", options: options)
}
}
protocol Finder {
associatedtype ExtensionType: YapDatabaseExtension
associatedtype TransactionType: YapDatabaseExtensionTransaction
static var dbExtensionName: String { get }
static var dbExtensionConfig: ExtensionType { get }
func ext(transaction: YapDatabaseReadTransaction) -> TransactionType
static func asyncRegisterDatabaseExtension(storage: OWSStorage)
static func testingOnly_ensureDatabaseExtensionRegistered(storage: OWSStorage)
}
extension Finder {
public func ext(transaction: YapDatabaseReadTransaction) -> TransactionType {
return transaction.ext(type(of: self).dbExtensionName) as! TransactionType
}
public static func asyncRegisterDatabaseExtension(storage: OWSStorage) {
storage.asyncRegister(dbExtensionConfig, withName: dbExtensionName)
}
// Only for testing.
public static func testingOnly_ensureDatabaseExtensionRegistered(storage: OWSStorage) {
guard storage.registeredExtension(dbExtensionName) == nil else {
return
}
storage.register(dbExtensionConfig, withName: dbExtensionName)
}
}

16
Signal.xcodeproj/project.pbxproj

@ -489,7 +489,6 @@
C33FDD23255A582000E217F9 /* FeatureFlags.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB69255A580F00E217F9 /* FeatureFlags.swift */; };
C33FDD32255A582000E217F9 /* OWSOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB78255A581000E217F9 /* OWSOperation.m */; };
C33FDD3A255A582000E217F9 /* Notification+Loki.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB80255A581100E217F9 /* Notification+Loki.swift */; };
C33FDD41255A582000E217F9 /* JobQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB87255A581100E217F9 /* JobQueue.swift */; };
C33FDD45255A582000E217F9 /* Storage+SessionManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB8B255A581200E217F9 /* Storage+SessionManagement.swift */; };
C33FDD49255A582000E217F9 /* ParamParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB8F255A581200E217F9 /* ParamParser.swift */; };
C33FDD53255A582000E217F9 /* OWSPrimaryStorage+keyFromIntLong.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB99255A581300E217F9 /* OWSPrimaryStorage+keyFromIntLong.m */; };
@ -686,9 +685,6 @@
C396DAF42518408B00FF6DC5 /* Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = C396DAED2518408B00FF6DC5 /* Parser.swift */; };
C396DAF52518408B00FF6DC5 /* CSV.swift in Sources */ = {isa = PBXBuildFile; fileRef = C396DAEE2518408B00FF6DC5 /* CSV.swift */; };
C3A3A08F256E1728004D228D /* FullTextSearchFinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB7F255A581100E217F9 /* FullTextSearchFinder.swift */; };
C3A3A099256E17B2004D228D /* SSKJobRecordFinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3A3A098256E17B2004D228D /* SSKJobRecordFinder.swift */; };
C3A3A0AA256E17E6004D228D /* SSKJobRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDACD255A580200E217F9 /* SSKJobRecord.m */; };
C3A3A0B3256E17F2004D228D /* SSKJobRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDB4F255A580D00E217F9 /* SSKJobRecord.h */; settings = {ATTRIBUTES = (Public, ); }; };
C3A3A0EC256E1949004D228D /* OWSRecipientIdentity.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBEC255A581B00E217F9 /* OWSRecipientIdentity.m */; };
C3A3A0F5256E194C004D228D /* OWSRecipientIdentity.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDAA0255A57FF00E217F9 /* OWSRecipientIdentity.h */; settings = {ATTRIBUTES = (Public, ); }; };
C3A3A0FE256E1A3C004D228D /* TSDatabaseSecondaryIndexes.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB20255A580900E217F9 /* TSDatabaseSecondaryIndexes.m */; };
@ -1379,7 +1375,6 @@
C33FDAC2255A580200E217F9 /* TSAttachment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachment.m; sourceTree = "<group>"; };
C33FDAC3255A580200E217F9 /* OWSDispatch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDispatch.m; sourceTree = "<group>"; };
C33FDAC4255A580200E217F9 /* TSAttachmentStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachmentStream.m; sourceTree = "<group>"; };
C33FDACD255A580200E217F9 /* SSKJobRecord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSKJobRecord.m; sourceTree = "<group>"; };
C33FDACF255A580300E217F9 /* OWSAttachmentDownloads.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSAttachmentDownloads.h; sourceTree = "<group>"; };
C33FDAD3255A580300E217F9 /* TSThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSThread.h; sourceTree = "<group>"; };
C33FDAD5255A580300E217F9 /* TSQuotedMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSQuotedMessage.h; sourceTree = "<group>"; };
@ -1438,7 +1433,6 @@
C33FDB48255A580C00E217F9 /* TSOutgoingMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSOutgoingMessage.h; sourceTree = "<group>"; };
C33FDB49255A580C00E217F9 /* WeakTimer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WeakTimer.swift; sourceTree = "<group>"; };
C33FDB4C255A580D00E217F9 /* AppVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppVersion.h; sourceTree = "<group>"; };
C33FDB4F255A580D00E217F9 /* SSKJobRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSKJobRecord.h; sourceTree = "<group>"; };
C33FDB51255A580D00E217F9 /* NSUserDefaults+OWS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSUserDefaults+OWS.h"; sourceTree = "<group>"; };
C33FDB54255A580D00E217F9 /* DataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataSource.h; sourceTree = "<group>"; };
C33FDB56255A580D00E217F9 /* TSOutgoingMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSOutgoingMessage.m; sourceTree = "<group>"; };
@ -1466,7 +1460,6 @@
C33FDB81255A581100E217F9 /* UIImage+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+OWS.m"; sourceTree = "<group>"; };
C33FDB83255A581100E217F9 /* TSQuotedMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSQuotedMessage.m; sourceTree = "<group>"; };
C33FDB85255A581100E217F9 /* AppContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppContext.m; sourceTree = "<group>"; };
C33FDB87255A581100E217F9 /* JobQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JobQueue.swift; sourceTree = "<group>"; };
C33FDB88255A581200E217F9 /* TSAccountManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAccountManager.m; sourceTree = "<group>"; };
C33FDB8A255A581200E217F9 /* AppContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppContext.h; sourceTree = "<group>"; };
C33FDB8B255A581200E217F9 /* Storage+SessionManagement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Storage+SessionManagement.swift"; sourceTree = "<group>"; };
@ -1721,7 +1714,6 @@
C396DAED2518408B00FF6DC5 /* Parser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Parser.swift; sourceTree = "<group>"; };
C396DAEE2518408B00FF6DC5 /* CSV.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSV.swift; sourceTree = "<group>"; };
C39DD28724F3318C008590FC /* Colors.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Colors.xcassets; sourceTree = "<group>"; };
C3A3A098256E17B2004D228D /* SSKJobRecordFinder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSKJobRecordFinder.swift; sourceTree = "<group>"; };
C3A3A170256E1D25004D228D /* SSKReachabilityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSKReachabilityManager.swift; sourceTree = "<group>"; };
C3A71D0A2558989C0043A11F /* MessageWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageWrapper.swift; sourceTree = "<group>"; };
C3A71D1C25589AC30043A11F /* WebSocketProto.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebSocketProto.swift; sourceTree = "<group>"; };
@ -2875,7 +2867,6 @@
C38EF286255B6D85007E1867 /* VersionMigrations.m */,
C33FDA8B255A57FD00E217F9 /* AppVersion.m */,
C33FDB69255A580F00E217F9 /* FeatureFlags.swift */,
C33FDB87255A581100E217F9 /* JobQueue.swift */,
C33FDA99255A57FE00E217F9 /* OutageDetection.swift */,
C33FDACF255A580300E217F9 /* OWSAttachmentDownloads.h */,
C33FDC13255A581E00E217F9 /* OWSAttachmentDownloads.m */,
@ -3189,9 +3180,6 @@
C33FDB31255A580A00E217F9 /* SSKEnvironment.h */,
C33FDAF4255A580600E217F9 /* SSKEnvironment.m */,
C33FDB32255A580A00E217F9 /* SSKIncrementingIdFinder.swift */,
C33FDB4F255A580D00E217F9 /* SSKJobRecord.h */,
C33FDACD255A580200E217F9 /* SSKJobRecord.m */,
C3A3A098256E17B2004D228D /* SSKJobRecordFinder.swift */,
C3A3A170256E1D25004D228D /* SSKReachabilityManager.swift */,
C3ECBF7A257056B700EA7FCE /* Threading.swift */,
C33FDB5F255A580E00E217F9 /* YapDatabaseConnection+OWS.h */,
@ -3664,7 +3652,6 @@
C32C5ADF256DBFAA003C73A2 /* OWSReadTracking.h in Headers */,
C3D9E486256775D20040E4F3 /* TSAttachmentPointer.h in Headers */,
C32C5EF7256DF567003C73A2 /* TSDatabaseView.h in Headers */,
C3A3A0B3256E17F2004D228D /* SSKJobRecord.h in Headers */,
B8856ED7256F1EB4001CE70E /* OWSPreferences.h in Headers */,
C32A026C25A801AF000ED5D4 /* NSData+messagePadding.h in Headers */,
C32C5BE6256DC891003C73A2 /* OWSReadReceiptManager.h in Headers */,
@ -4619,7 +4606,6 @@
C38EF3F9255B6DF7007E1867 /* OWSLayerView.swift in Sources */,
C33FDD03255A582000E217F9 /* WeakTimer.swift in Sources */,
B8B3204E258C15C80020074B /* ContactsMigration.swift in Sources */,
C33FDD41255A582000E217F9 /* JobQueue.swift in Sources */,
C32A025A25A7FC55000ED5D4 /* ClosedGroupsV2Migration.swift in Sources */,
C38EF3B9255B6DE7007E1867 /* ImageEditorPinchGestureRecognizer.swift in Sources */,
C33FDC98255A582000E217F9 /* SwiftSingletons.swift in Sources */,
@ -4790,7 +4776,6 @@
C32C5D9C256DD6DC003C73A2 /* OWSOutgoingReceiptManager.m in Sources */,
C32C5C4F256DCC36003C73A2 /* Storage+OpenGroups.swift in Sources */,
B8B3207B258C22550020074B /* DisplayNameUtilities.swift in Sources */,
C3A3A099256E17B2004D228D /* SSKJobRecordFinder.swift in Sources */,
B8856CEE256F1054001CE70E /* OWSAudioPlayer.m in Sources */,
C32C5EDC256DF501003C73A2 /* YapDatabaseConnection+OWS.m in Sources */,
C3BBE0762554CDA60050F1E3 /* Configuration.swift in Sources */,
@ -4854,7 +4839,6 @@
C352A2F525574B4700338F3E /* Job.swift in Sources */,
C32C5C01256DC9A0003C73A2 /* OWSIdentityManager.m in Sources */,
C32C59C4256DB41F003C73A2 /* TSContactThread.m in Sources */,
C3A3A0AA256E17E6004D228D /* SSKJobRecord.m in Sources */,
C32C5AB0256DBE8F003C73A2 /* TSOutgoingMessage.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

303
SignalUtilitiesKit/JobQueue.swift

@ -1,303 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
/// JobQueue - A durable work queue
///
/// When work needs to be done, add it to the JobQueue.
/// The JobQueue will persist a JobRecord to be sure that work can be restarted if the app is killed.
///
/// The actual work, is carried out in a DurableOperation which the JobQueue spins off, based on the contents
/// of a JobRecord.
///
/// For a concrete example, take message sending.
/// Add an outgoing message to the MessageSenderJobQueue, which first records a SSKMessageSenderJobRecord.
/// The MessageSenderJobQueue then uses that SSKMessageSenderJobRecord to create a MessageSenderOperation which
/// takes care of the actual business of communicating with the service.
///
/// DurableOperations are retryable - via their `remainingRetries` logic. However, if the operation encounters
/// an error where `error.isRetryable == false`, the operation will fail, regardless of available retries.
public extension Error {
var isRetryable: Bool {
return (self as NSError).isRetryable
}
}
extension SSKJobRecordStatus: CustomStringConvertible {
public var description: String {
switch self {
case .ready:
return "ready"
case .unknown:
return "unknown"
case .running:
return "running"
case .permanentlyFailed:
return "permanentlyFailed"
case .obsolete:
return "obsolete"
}
}
}
public enum JobError: Error {
case assertionFailure(description: String)
case obsolete(description: String)
}
public protocol DurableOperation: class {
associatedtype JobRecordType: SSKJobRecord
associatedtype DurableOperationDelegateType: DurableOperationDelegate
var jobRecord: JobRecordType { get }
var durableOperationDelegate: DurableOperationDelegateType? { get set }
var operation: OWSOperation { get }
var remainingRetries: UInt { get set }
}
public protocol DurableOperationDelegate: class {
associatedtype DurableOperationType: DurableOperation
func durableOperationDidSucceed(_ operation: DurableOperationType, transaction: YapDatabaseReadWriteTransaction)
func durableOperation(_ operation: DurableOperationType, didReportError: Error, transaction: YapDatabaseReadWriteTransaction)
func durableOperation(_ operation: DurableOperationType, didFailWithError error: Error, transaction: YapDatabaseReadWriteTransaction)
}
public protocol JobQueue: DurableOperationDelegate {
typealias DurableOperationDelegateType = Self
typealias JobRecordType = DurableOperationType.JobRecordType
// MARK: Dependencies
var dbConnection: YapDatabaseConnection { get }
var finder: JobRecordFinder { get }
// MARK: Default Implementations
func add(jobRecord: JobRecordType, transaction: YapDatabaseReadWriteTransaction)
func restartOldJobs()
func workStep()
func defaultSetup()
// MARK: Required
var runningOperations: [DurableOperationType] { get set }
var jobRecordLabel: String { get }
var isSetup: Bool { get set }
func setup()
func didMarkAsReady(oldJobRecord: JobRecordType, transaction: YapDatabaseReadWriteTransaction)
func operationQueue(jobRecord: JobRecordType) -> OperationQueue
func buildOperation(jobRecord: JobRecordType, transaction: YapDatabaseReadTransaction) throws -> DurableOperationType
/// When `requiresInternet` is true, we immediately run any jobs which are waiting for retry upon detecting Reachability.
///
/// Because `Reachability` isn't 100% reliable, the jobs will be attempted regardless of what we think our current Reachability is.
/// However, because these jobs will likely fail many times in succession, their `retryInterval` could be quite long by the time we
/// are back online.
var requiresInternet: Bool { get }
static var maxRetries: UInt { get }
}
public extension JobQueue {
// MARK: Dependencies
var dbConnection: YapDatabaseConnection {
return SSKEnvironment.shared.primaryStorage.dbReadWriteConnection
}
var finder: JobRecordFinder {
return JobRecordFinder()
}
var reachabilityManager: SSKReachabilityManager {
return SSKEnvironment.shared.reachabilityManager
}
// MARK:
func add(jobRecord: JobRecordType, transaction: YapDatabaseReadWriteTransaction) {
assert(jobRecord.status == .ready)
jobRecord.save(with: transaction)
transaction.addCompletionQueue(DispatchQueue.global()) {
self.startWorkWhenAppIsReady()
}
}
func startWorkWhenAppIsReady() {
guard !CurrentAppContext().isRunningTests else {
DispatchQueue.global().async {
self.workStep()
}
return
}
AppReadiness.runNowOrWhenAppDidBecomeReady {
DispatchQueue.global().async {
self.workStep()
}
}
}
func workStep() {
Logger.debug("")
guard isSetup else {
if !CurrentAppContext().isRunningTests {
owsFailDebug("not setup")
}
return
}
Storage.writeSync { transaction in
guard let nextJob: JobRecordType = self.finder.getNextReady(label: self.jobRecordLabel, transaction: transaction) as? JobRecordType else {
Logger.verbose("nothing left to enqueue")
return
}
do {
try nextJob.saveAsStarted(transaction: transaction)
let operationQueue = self.operationQueue(jobRecord: nextJob)
let durableOperation = try self.buildOperation(jobRecord: nextJob, transaction: transaction)
durableOperation.durableOperationDelegate = self as? Self.DurableOperationType.DurableOperationDelegateType
assert(durableOperation.durableOperationDelegate != nil)
let remainingRetries = self.remainingRetries(durableOperation: durableOperation)
durableOperation.remainingRetries = remainingRetries
self.runningOperations.append(durableOperation)
Logger.debug("adding operation: \(durableOperation) with remainingRetries: \(remainingRetries)")
operationQueue.addOperation(durableOperation.operation)
} catch JobError.assertionFailure(let description) {
owsFailDebug("assertion failure: \(description)")
nextJob.saveAsPermanentlyFailed(transaction: transaction)
} catch JobError.obsolete(let description) {
// TODO is this even worthwhile to have obsolete state? Should we just delete the task outright?
Logger.verbose("marking obsolete task as such. description:\(description)")
nextJob.saveAsObsolete(transaction: transaction)
} catch {
owsFailDebug("unexpected error")
}
DispatchQueue.global().async {
self.workStep()
}
}
}
public func restartOldJobs() {
Storage.writeSync { transaction in
let runningRecords = self.finder.allRecords(label: self.jobRecordLabel, status: .running, transaction: transaction)
Logger.info("marking old `running` JobRecords as ready: \(runningRecords.count)")
for record in runningRecords {
guard let jobRecord = record as? JobRecordType else {
owsFailDebug("unexpectred jobRecord: \(record)")
continue
}
do {
try jobRecord.saveRunningAsReady(transaction: transaction)
self.didMarkAsReady(oldJobRecord: jobRecord, transaction: transaction)
} catch {
owsFailDebug("failed to mark old running records as ready error: \(error)")
jobRecord.saveAsPermanentlyFailed(transaction: transaction)
}
}
}
}
/// Unless you need special handling, your setup method can be as simple as
///
/// func setup() {
/// defaultSetup()
/// }
///
/// So you might ask, why not just rename this method to `setup`? Because
/// `setup` is called from objc, and default implementations from a protocol
/// cannot be marked as @objc.
func defaultSetup() {
guard !isSetup else {
owsFailDebug("already ready already")
return
}
self.restartOldJobs()
if self.requiresInternet {
NotificationCenter.default.addObserver(forName: .reachabilityChanged,
object: self.reachabilityManager.observationContext,
queue: nil) { _ in
if self.reachabilityManager.isReachable {
Logger.verbose("isReachable: true")
self.becameReachable()
} else {
Logger.verbose("isReachable: false")
}
}
}
self.isSetup = true
self.startWorkWhenAppIsReady()
}
func remainingRetries(durableOperation: DurableOperationType) -> UInt {
let maxRetries = type(of: self).maxRetries
let failureCount = durableOperation.jobRecord.failureCount
guard maxRetries > failureCount else {
return 0
}
return maxRetries - failureCount
}
func becameReachable() {
guard requiresInternet else {
owsFailDebug("should only be called if `requiresInternet` is true")
return
}
_ = self.runAnyQueuedRetry()
}
func runAnyQueuedRetry() -> DurableOperationType? {
guard let runningDurableOperation = self.runningOperations.first else {
return nil
}
runningDurableOperation.operation.runAnyQueuedRetry()
return runningDurableOperation
}
// MARK: DurableOperationDelegate
func durableOperationDidSucceed(_ operation: DurableOperationType, transaction: YapDatabaseReadWriteTransaction) {
self.runningOperations = self.runningOperations.filter { $0 !== operation }
operation.jobRecord.remove(with: transaction)
}
func durableOperation(_ operation: DurableOperationType, didReportError: Error, transaction: YapDatabaseReadWriteTransaction) {
do {
try operation.jobRecord.addFailure(transaction: transaction)
} catch {
owsFailDebug("error while addingFailure: \(error)")
operation.jobRecord.saveAsPermanentlyFailed(transaction: transaction)
}
}
func durableOperation(_ operation: DurableOperationType, didFailWithError error: Error, transaction: YapDatabaseReadWriteTransaction) {
self.runningOperations = self.runningOperations.filter { $0 !== operation }
operation.jobRecord.saveAsPermanentlyFailed(transaction: transaction)
}
}
Loading…
Cancel
Save