feat: add websocket reconnection logic
This commit is contained in:
@@ -1,22 +1,41 @@
|
|||||||
import Combine
|
import Combine
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import Network
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
class LiveStatusManager: ObservableObject {
|
let webSocketMaxReconnectionCount = 3
|
||||||
|
|
||||||
|
class LiveStatusManager: NSObject, ObservableObject, URLSessionWebSocketDelegate {
|
||||||
@Published var listenerCount: Int = -1
|
@Published var listenerCount: Int = -1
|
||||||
|
|
||||||
@ObservedObject private var playbackManager: PlaybackManager
|
@ObservedObject private var playbackManager: PlaybackManager
|
||||||
|
|
||||||
|
private let pathMonitor = NWPathMonitor()
|
||||||
|
|
||||||
private var ws: URLSessionWebSocketTask?
|
private var ws: URLSessionWebSocketTask?
|
||||||
private var playbackStateObserver: AnyCancellable?
|
private var playbackStateObserver: AnyCancellable?
|
||||||
|
private var retryCount = 0
|
||||||
|
|
||||||
init(playbackManager: PlaybackManager) {
|
init(playbackManager: PlaybackManager) {
|
||||||
self.playbackManager = playbackManager
|
self.playbackManager = playbackManager
|
||||||
|
super.init()
|
||||||
|
|
||||||
playbackStateObserver = playbackManager.$playbackState.sink { playbackState in
|
playbackStateObserver = playbackManager.$playbackState.sink { playbackState in
|
||||||
self.onPlaybackStateChanged(playbackState)
|
self.onPlaybackStateChanged(playbackState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pathMonitor.pathUpdateHandler = { path in
|
||||||
|
self.onNetworkChanged(path)
|
||||||
|
}
|
||||||
|
|
||||||
connectToWebSocket()
|
connectToWebSocket()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
ws?.cancel(with: .goingAway, reason: nil)
|
||||||
|
pathMonitor.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
func connectToWebSocket() {
|
func connectToWebSocket() {
|
||||||
guard let url = URL(string: "wss://infinifi.cafe/ws") else {
|
guard let url = URL(string: "wss://infinifi.cafe/ws") else {
|
||||||
return
|
return
|
||||||
@@ -24,12 +43,35 @@ class LiveStatusManager: ObservableObject {
|
|||||||
|
|
||||||
let req = URLRequest(url: url)
|
let req = URLRequest(url: url)
|
||||||
let ws = URLSession.shared.webSocketTask(with: req)
|
let ws = URLSession.shared.webSocketTask(with: req)
|
||||||
|
ws.delegate = self
|
||||||
ws.resume()
|
ws.resume()
|
||||||
|
|
||||||
self.ws = ws
|
self.ws = ws
|
||||||
receiveWebSocketMessage()
|
receiveWebSocketMessage()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) {
|
||||||
|
if retryCount == webSocketMaxReconnectionCount {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.listenerCount = -1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
retryCount += 1
|
||||||
|
connectToWebSocket()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: (any Error)?) {
|
||||||
|
if retryCount == webSocketMaxReconnectionCount {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.listenerCount = -1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
retryCount += 1
|
||||||
|
connectToWebSocket()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func receiveWebSocketMessage() {
|
private func receiveWebSocketMessage() {
|
||||||
ws?.receive { result in
|
ws?.receive { result in
|
||||||
switch result {
|
switch result {
|
||||||
@@ -38,6 +80,7 @@ class LiveStatusManager: ObservableObject {
|
|||||||
print("failed to received \(err)")
|
print("failed to received \(err)")
|
||||||
#endif
|
#endif
|
||||||
case .success(.string(let msg)):
|
case .success(.string(let msg)):
|
||||||
|
self.retryCount = 0
|
||||||
self.handleWebSocketMessage(msg)
|
self.handleWebSocketMessage(msg)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -72,4 +115,14 @@ class LiveStatusManager: ObservableObject {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func onNetworkChanged(_ path: NWPath) {
|
||||||
|
if path.status == .satisfied {
|
||||||
|
if retryCount > 0 {
|
||||||
|
retryCount = 0
|
||||||
|
}
|
||||||
|
retryCount += 1
|
||||||
|
connectToWebSocket()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user