commit 84174ef9adf01488f8863f13878dd25e31943afc
parent f78eeb1f22a14d818fe0d9291c4f55813c882d1c
Author: William Casarin <jb55@jb55.com>
Date: Sun, 7 May 2023 10:28:36 -0700
Ping relays on resume, if there's an error then try to reconnect
This is an attempt to fix the fail-to-reconnect issues. Let's see if it works.
Diffstat:
4 files changed, 49 insertions(+), 4 deletions(-)
diff --git a/damus/ContentView.swift b/damus/ContentView.swift
@@ -59,6 +59,8 @@ struct ContentView: View {
return keypair.privkey
}
+ @Environment(\.scenePhase) var scenePhase
+
@State var status: String = "Not connected"
@State var active_sheet: Sheets? = nil
@State var damus_state: DamusState? = nil
@@ -403,6 +405,22 @@ struct ContentView: View {
.onReceive(handle_notify(.unmute_thread)) { notif in
home.filter_events()
}
+ .onChange(of: scenePhase) { (phase: ScenePhase) in
+ switch phase {
+ case .background:
+ print("📙 DAMUS BACKGROUNDED")
+ break
+ case .inactive:
+ print("📙 DAMUS INACTIVE")
+ break
+ case .active:
+ print("📙 DAMUS ACTIVE")
+ guard let ds = damus_state else { return }
+ ds.pool.ping()
+ @unknown default:
+ break
+ }
+ }
.onReceive(handle_notify(.local_notification)) { notif in
guard let local = notif.object as? LossyLocalNotification,
diff --git a/damus/Nostr/RelayConnection.swift b/damus/Nostr/RelayConnection.swift
@@ -42,6 +42,7 @@ final class RelayConnection {
private(set) var isConnecting = false
private(set) var last_connection_attempt: TimeInterval = 0
+ private(set) var last_pong: Date? = nil
private(set) var backoff: TimeInterval = 1.0
private lazy var socket = WebSocket(url.url)
private var subscriptionToken: AnyCancellable?
@@ -54,6 +55,18 @@ final class RelayConnection {
self.handleEvent = handleEvent
}
+ func ping() {
+ socket.ping { err in
+ if let err {
+ self.isConnecting = false
+ self.isConnected = false
+ self.reconnect_with_backoff()
+ } else {
+ self.last_pong = .now
+ }
+ }
+ }
+
func connect(force: Bool = false) {
if !force && (isConnected || isConnecting) {
return
@@ -111,15 +124,14 @@ final class RelayConnection {
DispatchQueue.main.async {
self.isConnected = false
self.isConnecting = false
- self.reconnect()
+ self.reconnect_with_backoff()
}
case .error(let error):
print("⚠️ Warning: RelayConnection (\(self.url)) error: \(error)")
DispatchQueue.main.async {
self.isConnected = false
self.isConnecting = false
- self.backoff *= 1.5
- self.reconnect_in(after: self.backoff)
+ self.reconnect_with_backoff()
}
}
DispatchQueue.main.async {
@@ -127,6 +139,11 @@ final class RelayConnection {
}
}
+ func reconnect_with_backoff() {
+ self.backoff *= 1.5
+ self.reconnect_in(after: self.backoff)
+ }
+
func reconnect() {
guard !isConnecting else {
return // we're already trying to connect
diff --git a/damus/Nostr/RelayPool.swift b/damus/Nostr/RelayPool.swift
@@ -79,7 +79,13 @@ class RelayPool {
self.handlers = handlers.filter { $0.sub_id != sub_id }
print("removing \(sub_id) handler, current: \(handlers.count)")
}
-
+
+ func ping() {
+ for relay in relays {
+ relay.connection.ping()
+ }
+ }
+
func register_handler(sub_id: String, handler: @escaping (String, NostrConnectionEvent) -> ()) {
for handler in handlers {
// don't add duplicate handlers
diff --git a/damus/Nostr/WebSocket.swift b/damus/Nostr/WebSocket.swift
@@ -32,6 +32,10 @@ final class WebSocket: NSObject, URLSessionWebSocketDelegate {
self.session = session
}
+ func ping(receiveHandler: @escaping (Error?) -> Void) {
+ self.webSocketTask.sendPing(pongReceiveHandler: receiveHandler)
+ }
+
func connect() {
resume()
}