@ -1,12 +1,11 @@
/*
/*
This class is used for settings friend requests to expired
Modeled after ` OWSDisappearingMessagesJob ` .
This is modelled after ` OWSDisappearingMessagesJob ` .
*/
*/
@objc ( OWSLokiFriendRequestExpire Job)
@objc ( LKFriendRequestExpiration Job)
public final class FriendRequestExpir e Job : NSObject {
public final class FriendRequestExpir ation Job : NSObject {
private let databaseConnection : YapDatabaseConnection
private let databaseConnection : YapDatabaseConnection
private let messageFinder = FriendRequestExpir e MessageFinder( )
private let messageFinder = FriendRequestExpir ation MessageFinder( )
// T h e s e p r o p e r t i e s s h o u l d o n l y b e a c c e s s e d o n t h e m a i n t h r e a d .
// T h e s e p r o p e r t i e s s h o u l d o n l y b e a c c e s s e d o n t h e m a i n t h r e a d .
private var hasStarted = false
private var hasStarted = false
@ -18,26 +17,21 @@ public final class FriendRequestExpireJob : NSObject {
fileprivate static let serialQueue = DispatchQueue ( label : " network.loki.friendrequest.expire " )
fileprivate static let serialQueue = DispatchQueue ( label : " network.loki.friendrequest.expire " )
// / C r e a t e a ` F r i e n d R e q u e s t E x p i r e J o b ` .
// / C r e a t e a ` F r i e n d R e q u e s t E x p i r e J o b ` .
// / T h i s w i l l c r e a t e a a u t o - r u n n i n g j o b w h i c h w i l l s e t f r i e n d r e q u e s t s t o e x p i r e d .
// / T h i s w i l l c r e a t e a n a u t o - r u n n i n g j o b w h i c h w i l l s e t f r i e n d r e q u e s t s t o e x p i r e d .
// /
// / - P a r a m e t e r p r i m a r y S t o r a g e : T h e p r i m a r y s t o r a g e .
@objc public init ( withPrimaryStorage primaryStorage : OWSPrimaryStorage ) {
@objc public init ( withPrimaryStorage primaryStorage : OWSPrimaryStorage ) {
databaseConnection = primaryStorage . newDatabaseConnection ( )
databaseConnection = primaryStorage . newDatabaseConnection ( )
super . init ( )
super . init ( )
// T h i s ma k e s s u r e w e o n l y e v e r h a v e o n e i n s t a n c e o f t h i s c l a s s
// T h i s en s u r e s w e o n l y e v e r h a v e o n e i n s t a n c e o f t h i s c l a s s
SwiftSingletons . register ( self )
SwiftSingletons . register ( self )
// S e t up a t i m e r t h a t r u n s p e r i o d i c a l l y t o c h e c k f o r n e w f r i e n d r e q u e s t m e s s a g e s t h a t w i l l s o o n e x p i r e
// S e t up a t i m e r t h a t r u n s p e r i o d i c a l l y t o c h e c k f o r n e w f r i e n d r e q u e s t m e s s a g e s t h a t w i l l s o o n e x p i r e
AppReadiness . runNowOrWhenAppDidBecomeReady {
AppReadiness . runNowOrWhenAppDidBecomeReady {
if CurrentAppContext ( ) . isMainApp {
if CurrentAppContext ( ) . isMainApp {
let fallbackInterval = 5 * kMinuteInterval
let fallbackInterval = 5 * kMinuteInterval
self . fallbackTimer = WeakTimer . scheduledTimer ( timeInterval : fallbackInterval , target : self , userInfo : nil , repeats : true ) { [ weak self ] _ in
self . fallbackTimer = WeakTimer . scheduledTimer ( timeInterval : fallbackInterval , target : self , userInfo : nil , repeats : true ) { [ weak self ] _ in
AssertIsOnMainThread ( )
AssertIsOnMainThread ( )
self ? . timerDidFire ( isMainTimer : false )
guard let strongSelf = self else { return }
strongSelf . timerDidFire ( mainTimer : false )
}
}
}
}
}
}
@ -50,19 +44,19 @@ public final class FriendRequestExpireJob : NSObject {
NotificationCenter . default . removeObserver ( self )
NotificationCenter . default . removeObserver ( self )
}
}
// / S t a r t t h e j o b i f w e h a v e n ' t d o n e it y e t
// / S t a r t t h e j o b i f w e h a v e n ' t d o n e so y e t .
@objc public func startIfNecessary ( ) {
@objc public func startIfNecessary ( ) {
DispatchQueue . main . async {
DispatchQueue . main . async {
guard ! self . hasStarted else { return }
guard ! self . hasStarted else { return }
self . hasStarted = true ;
self . hasStarted = true ;
FriendRequestExpir e Job. serialQueue . async {
FriendRequestExpir ation Job. serialQueue . async {
self . runLoop ( )
self . runLoop ( )
}
}
}
}
}
}
// / T h e m a i n l o o p
// / T h e m a i n l o o p .
private func runLoop ( ) {
private func runLoop ( ) {
AssertIsOnFriendRequestExpireQueue ( ) ;
AssertIsOnFriendRequestExpireQueue ( ) ;
@ -83,27 +77,19 @@ public final class FriendRequestExpireJob : NSObject {
// S c h e d u l e t h e n e x t t i m e r t o r u n
// S c h e d u l e t h e n e x t t i m e r t o r u n
private func scheduleRun ( by date : Date ) {
private func scheduleRun ( by date : Date ) {
DispatchQueue . main . async {
DispatchQueue . main . async {
guard CurrentAppContext ( ) . isMainAppAndActive else {
guard CurrentAppContext ( ) . isMainAppAndActive else { return } // D o n ' t s c h e d u l e r u n w h e n i n a c t i v e o r n o t i n m a i n a p p
// D o n ' t s c h e d u l e r u n w h e n i n a c t i v e o r n o t i n m a i n a p p .
return
}
let minDelaySeconds : TimeInterval = 1
let minDelaySeconds : TimeInterval = 1
let delaySeconds = max ( minDelaySeconds , date . timeIntervalSinceNow )
let delaySeconds = max ( minDelaySeconds , date . timeIntervalSinceNow )
let newTimerScheduleDate = Date ( timeIntervalSinceNow : delaySeconds )
let newTimerScheduleDate = Date ( timeIntervalSinceNow : delaySeconds )
// c h e c k t h a t w e o n l y s e t t h e d a t e i f n e e d e d
// C h e c k t h a t w e o n l y s e t t h e d a t e i f n e e d e d
if let previousDate = self . nextExpireDate , previousDate < date {
if let previousDate = self . nextExpireDate , previousDate < date { return } // I f t h e d a t e i s l a t e r t h a n t h e o n e w e h a v e s t o r e d t h e n j u s t i g n o r e
// I f t h e d a t e i s l a t e r t h a n t h e o n e w e h a v e s t o r e d t h e n j u s t i g n o r e
return
}
self . resetNextExpireTimer ( )
self . resetNextExpireTimer ( )
self . nextExpireDate = newTimerScheduleDate
self . nextExpireDate = newTimerScheduleDate
self . nextExpireTimer = WeakTimer . scheduledTimer ( timeInterval : delaySeconds , target : self , userInfo : nil , repeats : false ) { [ weak self ] _ in
self . nextExpireTimer = WeakTimer . scheduledTimer ( timeInterval : delaySeconds , target : self , userInfo : nil , repeats : false ) { [ weak self ] _ in
guard let strongSelf = self else { return }
self ? . timerDidFire ( isMainTimer : true )
strongSelf . timerDidFire ( mainTimer : true )
}
}
}
}
}
}
@ -125,15 +111,15 @@ public final class FriendRequestExpireJob : NSObject {
// S a n i t y c h e c k
// S a n i t y c h e c k
guard message . friendRequestExpiresAt <= now else {
guard message . friendRequestExpiresAt <= now else {
owsFailDebug ( " Refusing to expire friend request which doesn't expire until: \( message . friendRequestExpiresAt ) ")
owsFailDebug ( " Refusing to expire friend request which doesn't expire until: \( message . friendRequestExpiresAt ) . ")
return ;
return
}
}
// C h e c k t h a t w e o n l y e x p i r e s e n t f r i e n d r e q u e s t s
// C h e c k t h a t w e o n l y e x p i r e s e n t f r i e n d r e q u e s t s
guard message is TSOutgoingMessage && message . friendRequestStatus = = . pending else {
guard message is TSOutgoingMessage && message . friendRequestStatus = = . pending else {
// S e t m e s s a g e t o n o t e x p i r e , s o o u r o t h e r l o g i c w o r k s c o r r e c t l y
// S e t m e s s a g e t o n o t e x p i r e , s o o u r o t h e r l o g i c w o r k s c o r r e c t l y
message . saveFriendRequestExpires ( at : 0 , with : transaction )
message . saveFriendRequestExpires ( at : 0 , with : transaction )
return ;
return
}
}
// L o k i : E x p i r e t h e f r i e n d r e q u e s t m e s s a g e
// L o k i : E x p i r e t h e f r i e n d r e q u e s t m e s s a g e
@ -151,16 +137,16 @@ public final class FriendRequestExpireJob : NSObject {
nextExpireDate = nil
nextExpireDate = nil
}
}
private func timerDidFire ( m ainTimer: Bool ) {
private func timerDidFire ( isM ainTimer: Bool ) {
guard CurrentAppContext ( ) . isMainAppAndActive else {
guard CurrentAppContext ( ) . isMainAppAndActive else {
let infoString = m ainTimer ? " Main timer fired while main app is inactive " : " Ignoring fallback timer for app which is not main and active."
let infoString = isM ainTimer ? " Main timer fired while main app is inactive . " : " Ignoring fallback timer for app which is not main and active."
Logger . info ( " [Loki Friend Request Expire Job] \( infoString ) " )
Logger . info ( " [Loki ] Friend request expiration job: \( infoString ) " )
return
return
}
}
if ( m ainTimer) { self . resetNextExpireTimer ( ) }
if ( isM ainTimer) { self . resetNextExpireTimer ( ) }
FriendRequestExpir e Job. serialQueue . async {
FriendRequestExpir ation Job. serialQueue . async {
self . runLoop ( )
self . runLoop ( )
}
}
}
}
@ -168,12 +154,12 @@ public final class FriendRequestExpireJob : NSObject {
}
}
// MARK: E v e n t s
// MARK: E v e n t s
private extension FriendRequestExpir e Job {
private extension FriendRequestExpir ation Job {
@objc func didBecomeActive ( ) {
@objc func didBecomeActive ( ) {
AssertIsOnMainThread ( )
AssertIsOnMainThread ( )
AppReadiness . runNowOrWhenAppDidBecomeReady {
AppReadiness . runNowOrWhenAppDidBecomeReady {
FriendRequestExpir e Job. serialQueue . async {
FriendRequestExpir ation Job. serialQueue . async {
self . runLoop ( )
self . runLoop ( )
}
}
}
}
@ -187,12 +173,12 @@ private extension FriendRequestExpireJob {
}
}
// MARK: A s s e r t s
// MARK: A s s e r t s
private extension FriendRequestExpir e Job {
private extension FriendRequestExpir ation Job {
func AssertIsOnFriendRequestExpireQueue ( ) {
func AssertIsOnFriendRequestExpireQueue ( ) {
#if DEBUG
#if DEBUG
guard #available ( iOS 10.0 , * ) else { return }
guard #available ( iOS 10.0 , * ) else { return }
dispatchPrecondition ( condition : . onQueue ( FriendRequestExpir e Job. serialQueue ) )
dispatchPrecondition ( condition : . onQueue ( FriendRequestExpir ation Job. serialQueue ) )
#endif
#endif
}
}
}
}