More granular websocket error handling
This commit is contained in:
@@ -162,8 +162,7 @@ struct API
|
|||||||
|
|
||||||
websocketTask.sendPing { error in
|
websocketTask.sendPing { error in
|
||||||
if let error {
|
if let error {
|
||||||
print("Ping error: \(error). Trying to reconnect.")
|
notifyError(error, continuation: continuation)
|
||||||
continuation.yield(.error(.websocketError(error)))
|
|
||||||
websocketTask = spawnWebsocketTask(with: continuation)
|
websocketTask = spawnWebsocketTask(with: continuation)
|
||||||
} else {
|
} else {
|
||||||
continuation.yield(.event(Event(type: .receivedWebsocketPong)))
|
continuation.yield(.event(Event(type: .receivedWebsocketPong)))
|
||||||
@@ -204,14 +203,28 @@ struct API
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
print("Websocket Error: \(error)")
|
notifyError(error, continuation: continuation)
|
||||||
continuation.yield(.error(API.Error.websocketError(error)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return websocketTask
|
return websocketTask
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func notifyError(_ error: any Swift.Error, continuation: AsyncStream<StreamEvent>.Continuation) {
|
||||||
|
print("Websocket Error: \(error)")
|
||||||
|
var shouldNotifyObservers = true
|
||||||
|
let nsError = error as NSError
|
||||||
|
if nsError.code == 53 {
|
||||||
|
// This is a "connection abort", caused by backgrounding.
|
||||||
|
// Don't notify UI, just silently reconnect.
|
||||||
|
shouldNotifyObservers = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldNotifyObservers {
|
||||||
|
continuation.yield(.error(.websocketError(error)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func request() -> RequestBuilder {
|
private func request() -> RequestBuilder {
|
||||||
RequestBuilder(url: baseURL)
|
RequestBuilder(url: baseURL)
|
||||||
}
|
}
|
||||||
@@ -247,6 +260,7 @@ struct API
|
|||||||
|
|
||||||
// Private UI events
|
// Private UI events
|
||||||
case receivedWebsocketPong
|
case receivedWebsocketPong
|
||||||
|
case websocketReconnected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ extension ContentView
|
|||||||
case .favoritesUpdate:
|
case .favoritesUpdate:
|
||||||
await refresh(.favorites)
|
await refresh(.favorites)
|
||||||
|
|
||||||
|
case .websocketReconnected: fallthrough
|
||||||
case .metadataUpdate: fallthrough
|
case .metadataUpdate: fallthrough
|
||||||
case .mpdUpdate:
|
case .mpdUpdate:
|
||||||
await refresh([.playlist, .nowPlaying, .favorites])
|
await refresh([.playlist, .nowPlaying, .favorites])
|
||||||
|
|||||||
@@ -346,7 +346,7 @@ struct ErrorDisplayModifier: ViewModifier
|
|||||||
Rectangle()
|
Rectangle()
|
||||||
.fill(.background)
|
.fill(.background)
|
||||||
|
|
||||||
contentPlaceholderView(title: .connectionError, systemImage: "exclamationmark.triangle.fill")
|
contentPlaceholderView(title: "\(String(describing: error))", systemImage: "exclamationmark.triangle.fill")
|
||||||
.tint(.label)
|
.tint(.label)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user