Create JobQueue

This commit is contained in:
nielsandriesse 2020-11-08 13:12:38 +11:00
parent 28172b4ed2
commit d80804ca5a
15 changed files with 173 additions and 26 deletions

View File

@ -3,9 +3,11 @@ import SessionUtilities
// TODO: Implementation
public final class AttachmentDownloadJob : NSObject, Job, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility
public var delegate: JobDelegate?
public var failureCount: UInt = 0
// MARK: Settings
private static let maxRetryCount: UInt = 20
public static let maxFailureCount: UInt = 20
// MARK: Coding
public init?(coder: NSCoder) { }
@ -15,8 +17,12 @@ public final class AttachmentDownloadJob : NSObject, Job, NSCoding { // NSObjec
// MARK: Running
public func execute() { }
private func handleSuccess() { }
private func handleSuccess() {
delegate?.handleJobSucceeded(self)
}
private func handleFailure(error: Error) { }
private func handleFailure(error: Error) {
delegate?.handleJobFailed(self, with: error)
}
}

View File

@ -3,9 +3,11 @@ import SessionUtilities
// TODO: Implementation
public final class AttachmentUploadJob : NSObject, Job, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility
public var delegate: JobDelegate?
public var failureCount: UInt = 0
// MARK: Settings
private static let maxRetryCount: UInt = 20
public static let maxFailureCount: UInt = 20
// MARK: Coding
public init?(coder: NSCoder) { }
@ -15,8 +17,12 @@ public final class AttachmentUploadJob : NSObject, Job, NSCoding { // NSObject/
// MARK: Running
public func execute() { }
private func handleSuccess() { }
private func handleSuccess() {
delegate?.handleJobSucceeded(self)
}
private func handleFailure(error: Error) { }
private func handleFailure(error: Error) {
delegate?.handleJobFailed(self, with: error)
}
}

View File

@ -1,2 +1,9 @@
public protocol Job { }
public protocol Job : class {
var delegate: JobDelegate? { get set }
var failureCount: UInt { get set }
static var maxFailureCount: UInt { get }
func execute()
}

View File

@ -0,0 +1,6 @@
public protocol JobDelegate {
func handleJobSucceeded(_ job: Job)
func handleJobFailed(_ job: Job, with error: Error)
}

View File

@ -0,0 +1,21 @@
public final class JobQueue : JobDelegate {
public static let shared = JobQueue()
public func add(_ job: Job, using transaction: Any) {
Configuration.shared.storage.persist(job, using: transaction)
job.delegate = self
job.execute()
}
public func handleJobSucceeded(_ job: Job) {
// Mark the job as succeeded
}
public func handleJobFailed(_ job: Job, with error: Error) {
// Persist the job
// Retry it if the max failure count hasn't been reached
// Propagate the error otherwise
}
}

View File

@ -4,16 +4,16 @@ import SessionUtilities
// TODO: Retrying
public final class MessageReceiveJob : NSObject, Job, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility
public var delegate: JobDelegate?
private let data: Data
private var failureCount: UInt
public var failureCount: UInt = 0
// MARK: Settings
private static let maxRetryCount: UInt = 20
public static let maxFailureCount: UInt = 20
// MARK: Initialization
init(data: Data) {
self.data = data
self.failureCount = 0
}
// MARK: Coding
@ -44,11 +44,12 @@ public final class MessageReceiveJob : NSObject, Job, NSCoding { // NSObject/NS
}
private func handleSuccess() {
delegate?.handleJobSucceeded(self)
}
private func handleFailure(error: Error) {
self.failureCount += 1
delegate?.handleJobFailed(self, with: error)
}
}

View File

@ -5,18 +5,18 @@ import SessionUtilities
// TODO: Retrying
public final class MessageSendJob : NSObject, Job, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility
public var delegate: JobDelegate?
private let message: Message
private let destination: Message.Destination
private var failureCount: UInt
public var failureCount: UInt = 0
// MARK: Settings
private static let maxRetryCount: UInt = 20
public static let maxFailureCount: UInt = 20
// MARK: Initialization
init(message: Message, destination: Message.Destination) {
self.message = message
self.destination = destination
self.failureCount = 0
}
// MARK: Coding
@ -49,11 +49,12 @@ public final class MessageSendJob : NSObject, Job, NSCoding { // NSObject/NSCodi
}
private func handleSuccess() {
delegate?.handleJobSucceeded(self)
}
private func handleFailure(error: Error) {
self.failureCount += 1
delegate?.handleJobFailed(self, with: error)
}
}

View File

@ -7,16 +7,16 @@ import SessionUtilities
// TODO: Retrying
public final class NotifyPNServerJob : NSObject, Job, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility
public var delegate: JobDelegate?
private let message: SnodeMessage
private var failureCount: UInt
public var failureCount: UInt = 0
// MARK: Settings
private static let maxRetryCount: UInt = 20
public static let maxFailureCount: UInt = 20
// MARK: Initialization
init(message: SnodeMessage) {
self.message = message
self.failureCount = 0
}
// MARK: Coding
@ -33,15 +33,16 @@ public final class NotifyPNServerJob : NSObject, Job, NSCoding { // NSObject/NSC
// MARK: Running
public func execute() {
}
private func handleSuccess() {
delegate?.handleJobSucceeded(self)
}
private func handleFailure(error: Error) {
self.failureCount += 1
delegate?.handleJobFailed(self, with: error)
}
}

View File

@ -98,8 +98,9 @@ internal enum MessageSender {
NotificationCenter.default.post(name: .messageSent, object: NSNumber(value: message.sentTimestamp!))
}
let notifyPNServerJob = NotifyPNServerJob(message: snodeMessage)
Configuration.shared.storage.persist(notifyPNServerJob)
notifyPNServerJob.execute()
Configuration.shared.storage.with { transaction in
JobQueue.shared.add(notifyPNServerJob, using: transaction)
}
}
let _ = promise.catch(on: DispatchQueue.main) { _ in
if case .contact(_) = destination {

View File

@ -8,5 +8,5 @@ public protocol SessionMessagingKitStorageProtocol {
func getOrGenerateRegistrationID(using transaction: Any) -> UInt32
func isClosedGroup(_ publicKey: String) -> Bool
func getClosedGroupPrivateKey(for publicKey: String) -> String?
func persist(_ job: Job)
func persist(_ job: Job, using transaction: Any)
}

View File

@ -4,4 +4,5 @@ FOUNDATION_EXPORT double SessionUtilitiesVersionNumber;
FOUNDATION_EXPORT const unsigned char SessionUtilitiesVersionString[];
#import <SessionUtilities/NSDate+Timestamp.h>
#import <SessionUtilities/NSTimer+Proxying.h>
#import <SessionUtilities/ECKeyPair+Utilities.h>

View File

@ -0,0 +1,16 @@
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSTimer (Session)
// This method avoids the classic NSTimer retain cycle bug by using a weak reference to the target
+ (NSTimer *)weakScheduledTimerWithTimeInterval:(NSTimeInterval)timeInterval
target:(id)target
selector:(SEL)selector
userInfo:(nullable id)userInfo
repeats:(BOOL)repeats;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,64 @@
#import <Foundation/Foundation.h>
#import "NSTimer+Proxying.h"
#import <objc/runtime.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSTimerProxy : NSObject
@property (nonatomic, weak) id target;
@property (nonatomic) SEL selector;
@end
@implementation NSTimerProxy
- (void)timerFired:(NSDictionary *)userInfo
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self.target performSelector:self.selector withObject:userInfo];
#pragma clang diagnostic pop
}
@end
static void *kNSTimer_SN_Proxy = &kNSTimer_SN_Proxy;
@implementation NSTimer (Session)
- (NSTimerProxy *)sn_proxy
{
return objc_getAssociatedObject(self, kNSTimer_SN_Proxy);
}
- (void)sn_setProxy:(NSTimerProxy *)proxy
{
#if DEBUG
assert(proxy != nil);
#endif
objc_setAssociatedObject(self, kNSTimer_SN_Proxy, proxy, OBJC_ASSOCIATION_RETAIN);
}
+ (NSTimer *)weakScheduledTimerWithTimeInterval:(NSTimeInterval)timeInterval
target:(id)target
selector:(SEL)selector
userInfo:(nullable id)userInfo
repeats:(BOOL)repeats
{
NSTimerProxy *proxy = [NSTimerProxy new];
proxy.target = target;
proxy.selector = selector;
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:timeInterval
target:proxy
selector:@selector(timerFired:)
userInfo:userInfo
repeats:repeats];
[timer sn_setProxy:proxy];
return timer;
}
@end
NS_ASSUME_NONNULL_END

View File

@ -603,6 +603,10 @@
C352A32F2557549C00338F3E /* NotifyPNServerJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A32E2557549C00338F3E /* NotifyPNServerJob.swift */; };
C352A349255781F400338F3E /* AttachmentDownloadJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A348255781F400338F3E /* AttachmentDownloadJob.swift */; };
C352A35B2557824E00338F3E /* AttachmentUploadJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A35A2557824E00338F3E /* AttachmentUploadJob.swift */; };
C352A36D2557858E00338F3E /* NSTimer+Proxying.m in Sources */ = {isa = PBXBuildFile; fileRef = C352A36C2557858D00338F3E /* NSTimer+Proxying.m */; };
C352A3772557864000338F3E /* NSTimer+Proxying.h in Headers */ = {isa = PBXBuildFile; fileRef = C352A3762557859C00338F3E /* NSTimer+Proxying.h */; settings = {ATTRIBUTES = (Public, ); }; };
C352A3892557876500338F3E /* JobQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A3882557876500338F3E /* JobQueue.swift */; };
C352A3932557883D00338F3E /* JobDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A3922557883D00338F3E /* JobDelegate.swift */; };
C353F8F9244809150011121A /* PNOptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C353F8F8244809150011121A /* PNOptionView.swift */; };
C3548F0624456447009433A8 /* PNModeVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3548F0524456447009433A8 /* PNModeVC.swift */; };
C3548F0824456AB6009433A8 /* UIView+Wrapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3548F0724456AB6009433A8 /* UIView+Wrapping.swift */; };
@ -1609,6 +1613,10 @@
C352A32E2557549C00338F3E /* NotifyPNServerJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotifyPNServerJob.swift; sourceTree = "<group>"; };
C352A348255781F400338F3E /* AttachmentDownloadJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentDownloadJob.swift; sourceTree = "<group>"; };
C352A35A2557824E00338F3E /* AttachmentUploadJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentUploadJob.swift; sourceTree = "<group>"; };
C352A36C2557858D00338F3E /* NSTimer+Proxying.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSTimer+Proxying.m"; sourceTree = "<group>"; };
C352A3762557859C00338F3E /* NSTimer+Proxying.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSTimer+Proxying.h"; sourceTree = "<group>"; };
C352A3882557876500338F3E /* JobQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JobQueue.swift; sourceTree = "<group>"; };
C352A3922557883D00338F3E /* JobDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JobDelegate.swift; sourceTree = "<group>"; };
C353F8F8244809150011121A /* PNOptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PNOptionView.swift; sourceTree = "<group>"; };
C3548F0524456447009433A8 /* PNModeVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PNModeVC.swift; sourceTree = "<group>"; };
C3548F0724456AB6009433A8 /* UIView+Wrapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Wrapping.swift"; sourceTree = "<group>"; };
@ -3250,6 +3258,8 @@
isa = PBXGroup;
children = (
C352A2F425574B4700338F3E /* Job.swift */,
C352A3922557883D00338F3E /* JobDelegate.swift */,
C352A3882557876500338F3E /* JobQueue.swift */,
C352A348255781F400338F3E /* AttachmentDownloadJob.swift */,
C352A35A2557824E00338F3E /* AttachmentUploadJob.swift */,
C352A31225574F5200338F3E /* MessageReceiveJob.swift */,
@ -3354,6 +3364,8 @@
C3C2A5CE2553860700C340D1 /* Logging.swift */,
C300A6302554B68200555489 /* NSDate+Timestamp.h */,
C300A6312554B6D100555489 /* NSDate+Timestamp.mm */,
C352A3762557859C00338F3E /* NSTimer+Proxying.h */,
C352A36C2557858D00338F3E /* NSTimer+Proxying.m */,
C3C2A5D62553860B00C340D1 /* Promise+Retrying.swift */,
C3C2AC2D2553CBEB00C340D1 /* String+Trimming.swift */,
);
@ -3810,6 +3822,7 @@
buildActionMask = 2147483647;
files = (
C300A63B2554B72200555489 /* NSDate+Timestamp.h in Headers */,
C352A3772557864000338F3E /* NSTimer+Proxying.h in Headers */,
C3471F5625553E1100297E91 /* ECKeyPair+Utilities.h in Headers */,
C3C2A67D255388CC00C340D1 /* SessionUtilities.h in Headers */,
);
@ -4920,6 +4933,7 @@
files = (
C3AABDDF2553ECF00042FF4C /* Array+Description.swift in Sources */,
C3BBE0A82554D4DE0050F1E3 /* JSON.swift in Sources */,
C352A36D2557858E00338F3E /* NSTimer+Proxying.m in Sources */,
C3C2ABD22553C6C900C340D1 /* Data+SecureRandom.swift in Sources */,
C3471F6825553E7600297E91 /* ECKeyPair+Utilities.m in Sources */,
C3BBE0AA2554D4DE0050F1E3 /* Dictionary+Description.swift in Sources */,
@ -4942,9 +4956,11 @@
C352A32F2557549C00338F3E /* NotifyPNServerJob.swift in Sources */,
C300A5F22554B09800555489 /* MessageSender.swift in Sources */,
C3C2A74D2553A39700C340D1 /* VisibleMessage.swift in Sources */,
C352A3932557883D00338F3E /* JobDelegate.swift in Sources */,
C352A31325574F5200338F3E /* MessageReceiveJob.swift in Sources */,
C3C2A7562553A3AB00C340D1 /* VisibleMessage+Quote.swift in Sources */,
C300A5FC2554B0A000555489 /* MessageReceiver.swift in Sources */,
C352A3892557876500338F3E /* JobQueue.swift in Sources */,
C3BBE0B52554F0E10050F1E3 /* ProofOfWork.swift in Sources */,
C3BBE0802554CDD70050F1E3 /* Storage.swift in Sources */,
C3C2A7842553AAF300C340D1 /* SNProto.swift in Sources */,

View File

@ -34,12 +34,12 @@ static void *kNSTimer_OWS_Proxy = &kNSTimer_OWS_Proxy;
@implementation NSTimer (OWS)
- (NSTimerProxy *)ows_proxy
- (NSTimerProxy *)sn_proxy
{
return objc_getAssociatedObject(self, kNSTimer_OWS_Proxy);
}
- (void)ows_setProxy:(NSTimerProxy *)proxy
- (void)sn_setProxy:(NSTimerProxy *)proxy
{
OWSAssertDebug(proxy);
@ -60,7 +60,7 @@ static void *kNSTimer_OWS_Proxy = &kNSTimer_OWS_Proxy;
selector:@selector(timerFired:)
userInfo:userInfo
repeats:repeats];
[timer ows_setProxy:proxy];
[timer sn_setProxy:proxy];
return timer;
}