Network Reconnection Delay
Nucleic-Session: 4BE3E40C-E939-444C-8AED-93C0AFE13C07 Co-authored-by: Nucleic <[email protected]>
This commit is contained in:
@@ -320,12 +320,48 @@ final class RemoteStore: ObservableObject {
|
||||
}
|
||||
|
||||
/// Returning to the foreground: the network may have changed while the app was suspended (and
|
||||
/// path/keepalive callbacks were frozen). Re-read the path and re-dial anything not live so the
|
||||
/// transport is correct by the time the UI is on screen, rather than after a backoff.
|
||||
/// path/keepalive callbacks were frozen). Re-read the path, re-dial anything not live, then
|
||||
/// actively revalidate the connections that still *look* live — a socket the OS killed while we
|
||||
/// were suspended wakes marked `.connected`, and trusting that would stall the reconnect until
|
||||
/// the 55s keepalive deadline. `revalidate` pings each such link and re-dials the instant it
|
||||
/// fails to answer, so the transport is correct (and fast) by the time the UI is on screen.
|
||||
func onForeground() {
|
||||
endBackgroundHold()
|
||||
guard !demoMode, isPaired else { return }
|
||||
pathMonitor.refresh()
|
||||
// Ensure a connection exists for every paired host (and drop unpaired); this re-dials the
|
||||
// ones already known to be offline.
|
||||
reconnect()
|
||||
// The zombies from suspension still read `.connected` — probe and re-dial the dead ones.
|
||||
for conn in connections.values where conn.connectivity.isLive { conn.revalidate() }
|
||||
}
|
||||
|
||||
#if canImport(UIKit)
|
||||
/// Held while backgrounded so iOS keeps the process (and thus the live sockets + 20s keepalive)
|
||||
/// running for its short grant, instead of suspending us the moment we background.
|
||||
private var backgroundTask: UIBackgroundTaskIdentifier = .invalid
|
||||
#endif
|
||||
|
||||
/// Entering the background: ask iOS to keep us running briefly so a quick app-switch (glance at
|
||||
/// another app, tap a Live Activity, answer a banner) doesn't tear the connection down and force
|
||||
/// a cold reconnect on return. The grant is short (~30s) and best-effort; once it lapses the OS
|
||||
/// suspends us and the socket dies, which the next `onForeground` revalidation reconnects fast.
|
||||
func onBackground() {
|
||||
guard !demoMode else { return }
|
||||
#if canImport(UIKit)
|
||||
endBackgroundHold()
|
||||
backgroundTask = UIApplication.shared.beginBackgroundTask(withName: "nucleic.sync.hold") {
|
||||
[weak self] in self?.endBackgroundHold()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private func endBackgroundHold() {
|
||||
#if canImport(UIKit)
|
||||
guard backgroundTask != .invalid else { return }
|
||||
UIApplication.shared.endBackgroundTask(backgroundTask)
|
||||
backgroundTask = .invalid
|
||||
#endif
|
||||
}
|
||||
|
||||
private func seedDemo() {
|
||||
|
||||
Reference in New Issue
Block a user