Add own-instance API request retrying
This commit is contained in:
parent
a896573a5e
commit
13a4221fce
|
@ -46,6 +46,9 @@ class MastodonController: ObservableObject {
|
|||
@Published private(set) var instance: Instance!
|
||||
private(set) var customEmojis: [Emoji]?
|
||||
|
||||
private var pendingOwnInstanceRequestCallbacks = [(Instance) -> Void]()
|
||||
private var ownInstanceRequest: URLSessionTask?
|
||||
|
||||
var loggedIn: Bool {
|
||||
accountInfo != nil
|
||||
}
|
||||
|
@ -115,17 +118,56 @@ class MastodonController: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
// todo: this should dedup requests
|
||||
func getOwnInstance(completion: ((Instance) -> Void)? = nil) {
|
||||
getOwnInstanceInternal(retryAttempt: 0, completion: completion)
|
||||
}
|
||||
|
||||
private func getOwnInstanceInternal(retryAttempt: Int, completion: ((Instance) -> Void)?) {
|
||||
// this is main thread only to prevent concurrent access to ownInstanceRequest and pendingOwnInstanceRequestCallbacks
|
||||
assert(Thread.isMainThread)
|
||||
|
||||
if let instance = self.instance {
|
||||
completion?(instance)
|
||||
} else {
|
||||
if let completion = completion {
|
||||
pendingOwnInstanceRequestCallbacks.append(completion)
|
||||
}
|
||||
|
||||
if ownInstanceRequest == nil {
|
||||
let request = Client.getInstance()
|
||||
run(request) { (response) in
|
||||
guard case let .success(instance, _) = response else { fatalError() }
|
||||
ownInstanceRequest = run(request) { (response) in
|
||||
switch response {
|
||||
case .failure(_):
|
||||
let delay: DispatchTimeInterval
|
||||
switch retryAttempt {
|
||||
case 0:
|
||||
delay = .seconds(1)
|
||||
case 1:
|
||||
delay = .seconds(5)
|
||||
case 2:
|
||||
delay = .seconds(30)
|
||||
case 3:
|
||||
delay = .seconds(60)
|
||||
default:
|
||||
// if we've failed four times, just give up :/
|
||||
return
|
||||
}
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
|
||||
// completion is nil because in this invocation of getOwnInstanceInternal we've already added it to the pending callbacks array
|
||||
self.getOwnInstanceInternal(retryAttempt: retryAttempt + 1, completion: nil)
|
||||
}
|
||||
|
||||
case let .success(instance, _):
|
||||
DispatchQueue.main.async {
|
||||
self.ownInstanceRequest = nil
|
||||
self.instance = instance
|
||||
completion?(instance)
|
||||
|
||||
for completion in self.pendingOwnInstanceRequestCallbacks {
|
||||
completion(instance)
|
||||
}
|
||||
self.pendingOwnInstanceRequestCallbacks = []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue