forked from shadowfacts/Tusker
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!
|
@Published private(set) var instance: Instance!
|
||||||
private(set) var customEmojis: [Emoji]?
|
private(set) var customEmojis: [Emoji]?
|
||||||
|
|
||||||
|
private var pendingOwnInstanceRequestCallbacks = [(Instance) -> Void]()
|
||||||
|
private var ownInstanceRequest: URLSessionTask?
|
||||||
|
|
||||||
var loggedIn: Bool {
|
var loggedIn: Bool {
|
||||||
accountInfo != nil
|
accountInfo != nil
|
||||||
}
|
}
|
||||||
|
@ -115,17 +118,56 @@ class MastodonController: ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: this should dedup requests
|
|
||||||
func getOwnInstance(completion: ((Instance) -> Void)? = nil) {
|
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 {
|
if let instance = self.instance {
|
||||||
completion?(instance)
|
completion?(instance)
|
||||||
} else {
|
} else {
|
||||||
let request = Client.getInstance()
|
if let completion = completion {
|
||||||
run(request) { (response) in
|
pendingOwnInstanceRequestCallbacks.append(completion)
|
||||||
guard case let .success(instance, _) = response else { fatalError() }
|
}
|
||||||
DispatchQueue.main.async {
|
|
||||||
self.instance = instance
|
if ownInstanceRequest == nil {
|
||||||
completion?(instance)
|
let request = Client.getInstance()
|
||||||
|
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
|
||||||
|
|
||||||
|
for completion in self.pendingOwnInstanceRequestCallbacks {
|
||||||
|
completion(instance)
|
||||||
|
}
|
||||||
|
self.pendingOwnInstanceRequestCallbacks = []
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue