fix: force rediscover on manual reconnect

This commit is contained in:
edde746
2026-04-20 08:15:16 +02:00
parent 56baa48223
commit 64d5c1f6aa
4 changed files with 34 additions and 15 deletions
+6 -2
View File
@@ -551,8 +551,12 @@ class _MainAppState extends State<MainApp> with WidgetsBindingObserver {
: const Duration(minutes: 2);
if (now.difference(_lastResumeProbe) >= cooldown) {
_lastResumeProbe = now;
_serverManager.checkServerHealth();
_serverManager.reconnectOfflineServers();
// Await health check before reconnecting so stale "online" servers
// get marked offline and included in the reconnection sweep.
unawaited(() async {
await _serverManager.checkServerHealth();
await _serverManager.reconnectOfflineServers();
}());
}
case AppLifecycleState.paused:
case AppLifecycleState.detached:
+10 -6
View File
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:io' show Platform, exit;
import 'package:flutter/material.dart';
@@ -589,13 +590,16 @@ class _MainScreenState extends State<MainScreen> with RouteAware, WindowListener
setState(() => _isReconnecting = true);
final serverManager = context.read<MultiServerProvider>().serverManager;
serverManager.checkServerHealth();
serverManager.reconnectOfflineServers().whenComplete(() {
// Give a moment for status updates to propagate
Future.delayed(const Duration(seconds: 1), () {
unawaited(() async {
try {
// Health check first so stale "online" servers get marked offline before
// we snapshot the offline list for reconnection.
await serverManager.checkServerHealth();
await serverManager.reconnectOfflineServers(forceRediscovery: true);
} finally {
if (mounted) setState(() => _isReconnecting = false);
});
});
}
}());
}
void _handleLiveTvChanged() {
+14 -4
View File
@@ -492,12 +492,17 @@ class MultiServerManager {
}
}
/// Attempt reconnection for all offline servers
Future<void> reconnectOfflineServers() async {
/// Attempt reconnection for all offline servers.
///
/// When [forceRediscovery] is true, the cached endpoint is cleared before
/// reconnecting so the fast-path is skipped and a full candidate race runs.
/// Used by the manual reconnect button when the cached URL may be stale
/// (e.g. after a network change while the app was backgrounded).
Future<void> reconnectOfflineServers({bool forceRediscovery = false}) async {
// Coalesce concurrent calls — return the in-flight future if one exists
if (_activeReconnect != null) return _activeReconnect!;
_activeReconnect = _doReconnectOfflineServers();
_activeReconnect = _doReconnectOfflineServers(forceRediscovery: forceRediscovery);
try {
await _activeReconnect;
} finally {
@@ -505,13 +510,18 @@ class MultiServerManager {
}
}
Future<void> _doReconnectOfflineServers() async {
Future<void> _doReconnectOfflineServers({required bool forceRediscovery}) async {
final offline = offlineServerIds;
if (offline.isEmpty) return;
appLogger.d('Attempting reconnection for ${offline.length} offline servers');
Sentry.addBreadcrumb(Breadcrumb(message: 'Reconnecting ${offline.length} offline server(s)', category: 'servers'));
if (forceRediscovery) {
final storage = await StorageService.getInstance();
await Future.wait(offline.map(storage.clearServerEndpoint));
}
final futures = offline.map((serverId) {
final server = _servers[serverId];
if (server == null) return Future<void>.value();
+4 -3
View File
@@ -238,7 +238,7 @@ class PlexClient {
'Switching Plex endpoint after GET failure',
error: {'from': failedEndpoint, 'to': nextBaseUrl, 'path': path},
);
await _handleEndpointSwitch(nextBaseUrl);
await _handleEndpointSwitch(nextBaseUrl, persist: false);
final response = await _http.get(
path,
queryParameters: queryParameters,
@@ -247,6 +247,7 @@ class PlexClient {
abort: abort,
);
appLogger.i('Endpoint failover retry succeeded', error: {'newEndpoint': nextBaseUrl});
await _onEndpointChanged?.call(nextBaseUrl);
return response;
} finally {
_failoverSwitching = false;
@@ -2887,7 +2888,7 @@ class PlexClient {
}
}
Future<void> _handleEndpointSwitch(String newBaseUrl) async {
Future<void> _handleEndpointSwitch(String newBaseUrl, {bool persist = true}) async {
if (config.baseUrl == newBaseUrl) {
return;
}
@@ -2897,7 +2898,7 @@ class PlexClient {
config = config.copyWith(baseUrl: newBaseUrl);
LogRedactionManager.registerServerUrl(newBaseUrl);
if (_onEndpointChanged != null) {
if (persist && _onEndpointChanged != null) {
await _onEndpointChanged(newBaseUrl);
}
}