|
|
|
@ -32,6 +32,7 @@ public extension LokiAPI {
|
|
|
|
|
|
|
|
|
|
// MARK: Internal API
|
|
|
|
|
internal static func getRandomSnode() -> Promise<LokiAPITarget> {
|
|
|
|
|
// All of this has to happen on DispatchQueue.global() due to the way OWSMessageManager works
|
|
|
|
|
if randomSnodePool.isEmpty {
|
|
|
|
|
let target = seedNodePool.randomElement()!
|
|
|
|
|
let url = URL(string: "\(target)/json_rpc")!
|
|
|
|
@ -49,7 +50,7 @@ public extension LokiAPI {
|
|
|
|
|
]
|
|
|
|
|
])
|
|
|
|
|
print("[Loki] Invoking get_n_service_nodes on \(target).")
|
|
|
|
|
return TSNetworkManager.shared().perform(request).map(on: DispatchQueue.global()) { intermediate in
|
|
|
|
|
return TSNetworkManager.shared().perform(request, withCompletionQueue: DispatchQueue.global()).map(on: DispatchQueue.global()) { intermediate in
|
|
|
|
|
let rawResponse = intermediate.responseObject
|
|
|
|
|
guard let json = rawResponse as? JSON, let intermediate = json["result"] as? JSON, let rawTargets = intermediate["service_node_states"] as? [JSON] else { throw LokiAPIError.randomSnodePoolUpdatingFailed }
|
|
|
|
|
randomSnodePool = try Set(rawTargets.flatMap { rawTarget in
|
|
|
|
@ -61,7 +62,7 @@ public extension LokiAPI {
|
|
|
|
|
})
|
|
|
|
|
// randomElement() uses the system's default random generator, which is cryptographically secure
|
|
|
|
|
return randomSnodePool.randomElement()!
|
|
|
|
|
}.recover { error -> Promise<LokiAPITarget> in
|
|
|
|
|
}.recover(on: DispatchQueue.global()) { error -> Promise<LokiAPITarget> in
|
|
|
|
|
print("[Loki] Failed to contact seed node at: \(target).")
|
|
|
|
|
throw error
|
|
|
|
|
}.retryingIfNeeded(maxRetryCount: 16) // The seed nodes have historically been unreliable
|
|
|
|
|