Fix snode pool updating bug

This commit is contained in:
Niels Andriesse 2021-05-03 09:08:50 +10:00
parent 9b2dedb70b
commit 371222098b
3 changed files with 55 additions and 46 deletions

View File

@ -149,6 +149,8 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv
appDelegate.syncConfigurationIfNeeded()
}
}
// Re-populate snode pool if needed
SnodeAPI.getSnodePool().retainUntilComplete()
// Onion request path countries cache
DispatchQueue.global(qos: .utility).async {
let _ = IP2Country.shared.populateCacheIfNeeded()

View File

@ -414,6 +414,8 @@ static NSTimeInterval launchStartedAt;
if (CurrentAppContext().isMainApp && SNFeatures.useV2OpenGroups) {
[SNOpenGroupAPIV2 getDefaultRoomsIfNeeded];
}
[[SNSnodeAPI getSnodePool] retainUntilComplete];
if (![UIApplication sharedApplication].isRegisteredForRemoteNotifications) {
OWSLogInfo(@"Retrying remote notification registration since user hasn't registered yet.");

View File

@ -135,52 +135,6 @@ public final class SnodeAPI : NSObject {
return getSnodePool().map2 { $0.randomElement()! }
}
private static func getSnodePool() -> Promise<Set<Snode>> {
loadSnodePoolIfNeeded()
let now = Date()
let hasSnodePoolExpired = given(Storage.shared.getLastSnodePoolRefreshDate()) { now.timeIntervalSince($0) > 2 * 60 * 60 } ?? true
let snodePool = SnodeAPI.snodePool
let hasInsufficientSnodes = (snodePool.count < minSnodePoolCount)
if hasInsufficientSnodes || hasSnodePoolExpired {
if let getSnodePoolPromise = getSnodePoolPromise { return getSnodePoolPromise }
let promise: Promise<Set<Snode>>
if snodePool.count < minSnodePoolCount {
promise = getSnodePoolFromSeedNode()
} else {
promise = getSnodePoolFromSnode().recover2 { _ in
getSnodePoolFromSeedNode()
}
}
getSnodePoolPromise = promise
promise.map2 { snodePool -> Set<Snode> in
if snodePool.isEmpty {
throw Error.snodePoolUpdatingFailed
} else {
return snodePool
}
}
promise.then2 { snodePool -> Promise<Set<Snode>> in
let (promise, seal) = Promise<Set<Snode>>.pending()
SNSnodeKitConfiguration.shared.storage.write(with: { transaction in
Storage.shared.setLastSnodePoolRefreshDate(to: now, using: transaction)
setSnodePool(to: snodePool, using: transaction)
}, completion: {
seal.fulfill(snodePool)
})
return promise
}
promise.done2 { _ in
getSnodePoolPromise = nil
}
promise.catch2 { _ in
getSnodePoolPromise = nil
}
return promise
} else {
return Promise.value(snodePool)
}
}
private static func getSnodePoolFromSeedNode() -> Promise<Set<Snode>> {
let target = seedNodePool.randomElement()!
let url = "\(target)/json_rpc"
@ -269,6 +223,57 @@ public final class SnodeAPI : NSObject {
}
// MARK: Public API
@objc(getSnodePool)
public static func objc_getSnodePool() -> AnyPromise {
AnyPromise.from(getSnodePool())
}
public static func getSnodePool() -> Promise<Set<Snode>> {
loadSnodePoolIfNeeded()
let now = Date()
let hasSnodePoolExpired = given(Storage.shared.getLastSnodePoolRefreshDate()) { now.timeIntervalSince($0) > 2 * 60 * 60 } ?? true
let snodePool = SnodeAPI.snodePool
let hasInsufficientSnodes = (snodePool.count < minSnodePoolCount)
if hasInsufficientSnodes || hasSnodePoolExpired {
if let getSnodePoolPromise = getSnodePoolPromise { return getSnodePoolPromise }
let promise: Promise<Set<Snode>>
if snodePool.count < minSnodePoolCount {
promise = getSnodePoolFromSeedNode()
} else {
promise = getSnodePoolFromSnode().recover2 { _ in
getSnodePoolFromSeedNode()
}
}
getSnodePoolPromise = promise
promise.map2 { snodePool -> Set<Snode> in
if snodePool.isEmpty {
throw Error.snodePoolUpdatingFailed
} else {
return snodePool
}
}
promise.then2 { snodePool -> Promise<Set<Snode>> in
let (promise, seal) = Promise<Set<Snode>>.pending()
SNSnodeKitConfiguration.shared.storage.write(with: { transaction in
Storage.shared.setLastSnodePoolRefreshDate(to: now, using: transaction)
setSnodePool(to: snodePool, using: transaction)
}, completion: {
seal.fulfill(snodePool)
})
return promise
}
promise.done2 { _ in
getSnodePoolPromise = nil
}
promise.catch2 { _ in
getSnodePoolPromise = nil
}
return promise
} else {
return Promise.value(snodePool)
}
}
public static func getSessionID(for onsName: String) -> Promise<String> {
let sodium = Sodium()
let validationCount = 3