AppExpiry should take database reference as needed
This change should have no user impact.
This commit is contained in:
parent
f06e6c4fe8
commit
e5340f6d56
@ -112,7 +112,10 @@ public class AppSetup {
|
||||
let modelReadCaches = ModelReadCaches(factory: ModelReadCacheFactory())
|
||||
let earlyMessageManager = EarlyMessageManager()
|
||||
let messagePipelineSupervisor = MessagePipelineSupervisor.createStandardSupervisor()
|
||||
let appExpiry = AppExpiry()
|
||||
let appExpiry = AppExpiry(
|
||||
keyValueStoreFactory: SDSKeyValueStoreFactory(),
|
||||
schedulers: DispatchQueueSchedulers()
|
||||
)
|
||||
let paymentsHelper = PaymentsHelperImpl()
|
||||
let paymentsCurrencies = PaymentsCurrenciesImpl()
|
||||
let spamChallengeResolver = SpamChallengeResolver()
|
||||
|
||||
@ -43,7 +43,7 @@ extension HTTPUtils {
|
||||
}
|
||||
|
||||
if httpError.responseStatusCode == AppExpiry.appExpiredStatusCode {
|
||||
appExpiry.setHasAppExpiredAtCurrentVersion()
|
||||
appExpiry.setHasAppExpiredAtCurrentVersion(db: DependenciesBridge.shared.db)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -472,7 +472,7 @@ public class OWSURLSession: NSObject, OWSURLSessionProtocol {
|
||||
return
|
||||
}
|
||||
|
||||
AppExpiry.shared.setHasAppExpiredAtCurrentVersion()
|
||||
AppExpiry.shared.setHasAppExpiredAtCurrentVersion(db: DependenciesBridge.shared.db)
|
||||
}
|
||||
|
||||
// MARK: Request building
|
||||
|
||||
@ -469,7 +469,7 @@ public class OWSWebSocket: NSObject {
|
||||
// The websocket is only used to connect to the main signal
|
||||
// service, so we need to check for remote deprecation.
|
||||
if responseStatus == AppExpiry.appExpiredStatusCode {
|
||||
appExpiry.setHasAppExpiredAtCurrentVersion()
|
||||
appExpiry.setHasAppExpiredAtCurrentVersion(db: DependenciesBridge.shared.db)
|
||||
}
|
||||
|
||||
let headers = OWSHttpHeaders()
|
||||
@ -1186,7 +1186,7 @@ extension OWSWebSocket {
|
||||
},
|
||||
failure: { (failure: OWSHTTPErrorWrapper) in
|
||||
if failure.error.responseStatusCode == AppExpiry.appExpiredStatusCode {
|
||||
Self.appExpiry.setHasAppExpiredAtCurrentVersion()
|
||||
Self.appExpiry.setHasAppExpiredAtCurrentVersion(db: DependenciesBridge.shared.db)
|
||||
}
|
||||
|
||||
failureParam(failure)
|
||||
|
||||
@ -243,6 +243,11 @@ public class SSKEnvironment: NSObject {
|
||||
warmCachesForObject("paymentsCurrencies", paymentsCurrencies.warmCaches)
|
||||
warmCachesForObject("storyManager", StoryManager.setup)
|
||||
warmCachesForObject("deviceManager", DependenciesBridge.shared.deviceManager.warmCaches)
|
||||
warmCachesForObject("appExpiry") {
|
||||
DependenciesBridge.shared.db.read { tx in
|
||||
self.appExpiry.warmCaches(with: tx)
|
||||
}
|
||||
}
|
||||
|
||||
NotificationCenter.default.post(name: SSKEnvironment.warmCachesNotification, object: nil)
|
||||
}
|
||||
|
||||
@ -109,7 +109,10 @@ public class MockSSKEnvironment: SSKEnvironment {
|
||||
let modelReadCaches = ModelReadCaches(factory: TestableModelReadCacheFactory())
|
||||
let earlyMessageManager = EarlyMessageManager()
|
||||
let messagePipelineSupervisor = MessagePipelineSupervisor.createStandardSupervisor()
|
||||
let appExpiry = AppExpiry()
|
||||
let appExpiry = AppExpiry(
|
||||
keyValueStoreFactory: SDSKeyValueStoreFactory(),
|
||||
schedulers: DispatchQueueSchedulers()
|
||||
)
|
||||
let paymentsHelper = MockPaymentsHelper()
|
||||
let paymentsCurrencies = MockPaymentsCurrencies()
|
||||
let paymentsEvents = PaymentsEventsNoop()
|
||||
|
||||
@ -10,8 +10,8 @@ public class AppExpiry: NSObject {
|
||||
@objc
|
||||
public static let appExpiredStatusCode: UInt = 499
|
||||
|
||||
@objc
|
||||
public let keyValueStore = SDSKeyValueStore(collection: "AppExpiry")
|
||||
private let keyValueStore: KeyValueStore
|
||||
private let schedulers: Schedulers
|
||||
|
||||
private struct ExpirationState: Codable, Equatable {
|
||||
let version4: String
|
||||
@ -37,18 +37,20 @@ public class AppExpiry: NSObject {
|
||||
}
|
||||
}
|
||||
private let expirationState = AtomicValue<ExpirationState>(.init(mode: .default))
|
||||
private static var expirationStateKey: String { "expirationState" }
|
||||
|
||||
@objc
|
||||
public required override init() {
|
||||
static let keyValueCollection = "AppExpiry"
|
||||
static let keyValueKey = "expirationState"
|
||||
|
||||
public required init(
|
||||
keyValueStoreFactory: KeyValueStoreFactory,
|
||||
schedulers: Schedulers
|
||||
) {
|
||||
self.keyValueStore = keyValueStoreFactory.keyValueStore(collection: Self.keyValueCollection)
|
||||
self.schedulers = schedulers
|
||||
|
||||
super.init()
|
||||
|
||||
SwiftSingletons.register(self)
|
||||
|
||||
AppReadiness.runNowOrWhenAppWillBecomeReady {
|
||||
// We don't need to re-warm this cache after a device migration.
|
||||
self.warmCaches()
|
||||
}
|
||||
}
|
||||
|
||||
private func logExpirationState() {
|
||||
@ -61,41 +63,40 @@ public class AppExpiry: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
private func warmCaches() {
|
||||
public func warmCaches(with tx: DBReadTransaction) {
|
||||
owsAssertDebug(GRDBSchemaMigrator.areMigrationsComplete)
|
||||
|
||||
if let persistedExpirationState: ExpirationState = databaseStorage.read(block: { transaction in
|
||||
guard let persistedExpirationState: ExpirationState = try? self.keyValueStore.getCodableValue(
|
||||
forKey: Self.expirationStateKey,
|
||||
transaction: transaction
|
||||
) else {
|
||||
return nil
|
||||
}
|
||||
let persistedExpirationState: ExpirationState? = try? self.keyValueStore.getCodableValue(
|
||||
forKey: Self.keyValueKey,
|
||||
transaction: tx
|
||||
)
|
||||
|
||||
// We only want to restore the persisted state if it's for our current version.
|
||||
guard persistedExpirationState.version4 == AppVersion.shared.currentAppVersion4 else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return persistedExpirationState
|
||||
}) {
|
||||
expirationState.set(persistedExpirationState)
|
||||
// We only want to restore the persisted state if it's for our current version.
|
||||
guard
|
||||
let persistedExpirationState,
|
||||
persistedExpirationState.version4 == AppVersion.shared.currentAppVersion4
|
||||
else {
|
||||
return
|
||||
}
|
||||
|
||||
expirationState.set(persistedExpirationState)
|
||||
|
||||
logExpirationState()
|
||||
}
|
||||
|
||||
private func updateExpirationState(_ state: ExpirationState) {
|
||||
private func updateExpirationState(_ state: ExpirationState, db: DB) {
|
||||
expirationState.set(state)
|
||||
|
||||
logExpirationState()
|
||||
|
||||
databaseStorage.asyncWrite { transaction in
|
||||
db.asyncWrite { transaction in
|
||||
do {
|
||||
// Don't write or fire notification if the value hasn't changed.
|
||||
if let oldState: ExpirationState = try self.keyValueStore.getCodableValue(forKey: Self.expirationStateKey,
|
||||
transaction: transaction),
|
||||
oldState == state {
|
||||
let oldState: ExpirationState? = try self.keyValueStore.getCodableValue(
|
||||
forKey: Self.keyValueKey,
|
||||
transaction: transaction
|
||||
)
|
||||
if let oldState, oldState == state {
|
||||
return
|
||||
}
|
||||
} catch {
|
||||
@ -104,13 +105,14 @@ public class AppExpiry: NSObject {
|
||||
do {
|
||||
try self.keyValueStore.setCodable(
|
||||
state,
|
||||
key: Self.expirationStateKey,
|
||||
key: Self.keyValueKey,
|
||||
transaction: transaction
|
||||
)
|
||||
} catch {
|
||||
owsFailDebug("Error persisting expiration state \(error)")
|
||||
}
|
||||
transaction.addAsyncCompletionOffMain {
|
||||
|
||||
transaction.addAsyncCompletion(on: self.schedulers.global()) {
|
||||
NotificationCenter.default.postNotificationNameAsync(
|
||||
Self.AppExpiryDidChange,
|
||||
object: nil
|
||||
@ -119,28 +121,28 @@ public class AppExpiry: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
public func setHasAppExpiredAtCurrentVersion() {
|
||||
public func setHasAppExpiredAtCurrentVersion(db: DB) {
|
||||
Logger.warn("")
|
||||
|
||||
updateExpirationState(ExpirationState(mode: .immediately))
|
||||
updateExpirationState(ExpirationState(mode: .immediately), db: db)
|
||||
}
|
||||
|
||||
@objc
|
||||
public func setExpirationDateForCurrentVersion(_ newExpirationDate: Date?) {
|
||||
public func setExpirationDateForCurrentVersion(_ newExpirationDate: Date?, db: DB) {
|
||||
guard !isExpired else {
|
||||
return owsFailDebug("Ignoring expiration date change for expired build.")
|
||||
}
|
||||
|
||||
Logger.warn("\(String(describing: newExpirationDate))")
|
||||
|
||||
let newState: ExpirationState
|
||||
if let newExpirationDate = newExpirationDate {
|
||||
// Ignore any expiration date that is later than when the app expires by default.
|
||||
guard newExpirationDate < AppVersion.shared.defaultExpirationDate else { return }
|
||||
updateExpirationState(ExpirationState(mode: .atDate, expirationDate: newExpirationDate))
|
||||
newState = .init(mode: .atDate, expirationDate: newExpirationDate)
|
||||
} else {
|
||||
updateExpirationState(ExpirationState(mode: .default))
|
||||
newState = .init(mode: .default)
|
||||
}
|
||||
updateExpirationState(newState, db: db)
|
||||
}
|
||||
|
||||
@objc
|
||||
|
||||
@ -854,12 +854,13 @@ private extension ServiceRemoteConfigManager {
|
||||
if let minimumVersions = minimumVersions {
|
||||
Logger.info("Minimum client versions: \(minimumVersions)")
|
||||
|
||||
let db = DependenciesBridge.shared.db
|
||||
if let remoteExpirationDate = remoteExpirationDate(minimumVersions: minimumVersions) {
|
||||
Logger.info("Setting client expiration date: \(remoteExpirationDate)")
|
||||
AppExpiry.shared.setExpirationDateForCurrentVersion(remoteExpirationDate)
|
||||
AppExpiry.shared.setExpirationDateForCurrentVersion(remoteExpirationDate, db: db)
|
||||
} else {
|
||||
Logger.info("Clearing client expiration date")
|
||||
AppExpiry.shared.setExpirationDateForCurrentVersion(nil)
|
||||
AppExpiry.shared.setExpirationDateForCurrentVersion(nil, db: db)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user