diff --git a/lib/data/model/server/try_limiter.dart b/lib/data/model/server/try_limiter.dart index 4c674788..b99874ed 100644 --- a/lib/data/model/server/try_limiter.dart +++ b/lib/data/model/server/try_limiter.dart @@ -3,27 +3,29 @@ import 'package:toolbox/data/res/store.dart'; class TryLimiter { final Map _triedTimes = {}; - bool canTry(String id) { + static final _default = TryLimiter(); + + static bool canTry(String id) { final maxCount = Stores.setting.maxRetryCount.fetch(); if (maxCount <= 0) { return true; } - final times = _triedTimes[id] ?? 0; + final times = _default._triedTimes[id] ?? 0; if (times >= maxCount) { return false; } return true; } - void inc(String sid) { - _triedTimes[sid] = (_triedTimes[sid] ?? 0) + 1; + static void inc(String sid) { + _default._triedTimes[sid] = (_default._triedTimes[sid] ?? 0) + 1; } - void reset(String id) { - _triedTimes[id] = 0; + static void reset(String id) { + _default._triedTimes[id] = 0; } - void clear() { - _triedTimes.clear(); + static void clear() { + _default._triedTimes.clear(); } } diff --git a/lib/data/provider/server.dart b/lib/data/provider/server.dart index 315c1e7e..ecb73edd 100644 --- a/lib/data/provider/server.dart +++ b/lib/data/provider/server.dart @@ -31,8 +31,6 @@ class ServerProvider extends ChangeNotifier { final List _tags = []; List get tags => _tags; - final _limiter = TryLimiter(); - Timer? _timer; Future load() async { @@ -124,7 +122,7 @@ class ServerProvider extends ChangeNotifier { Future _connectFn(Server s, bool onlyFailed) async { if (onlyFailed) { if (s.state != ServerState.failed) return; - _limiter.reset(s.spi.id); + TryLimiter.reset(s.spi.id); } /// If [spi.autoConnect] is false and server is disconnected, then skip. @@ -161,7 +159,7 @@ class ServerProvider extends ChangeNotifier { for (final s in _servers.values) { s.state = ServerState.disconnected; } - _limiter.clear(); + //TryLimiter.clear(); notifyListeners(); } @@ -227,7 +225,7 @@ class ServerProvider extends ChangeNotifier { // Only reconnect if neccessary if (newSpi.shouldReconnect(old)) { // Use [newSpi.id] instead of [old.id] because [old.id] may be changed - _limiter.reset(newSpi.id); + TryLimiter.reset(newSpi.id); refreshData(spi: newSpi); } @@ -256,7 +254,7 @@ class ServerProvider extends ChangeNotifier { if (s == null) return; - if (!_limiter.canTry(sid)) { + if (!TryLimiter.canTry(sid)) { if (s.state != ServerState.failed) { _setServerState(s, ServerState.failed); } @@ -289,7 +287,7 @@ class ServerProvider extends ChangeNotifier { ); } } catch (e) { - _limiter.inc(sid); + TryLimiter.inc(sid); s.status.failedInfo = e.toString(); _setServerState(s, ServerState.failed); @@ -332,7 +330,7 @@ class ServerProvider extends ChangeNotifier { throw err; } } catch (e) { - _limiter.inc(sid); + TryLimiter.inc(sid); s.status.failedInfo = e.toString(); _setServerState(s, ServerState.failed); Loggers.app.warning('Write script to ${spi.name} by sftp', e); @@ -357,13 +355,13 @@ class ServerProvider extends ChangeNotifier { raw = await s.client?.run(ShellFunc.status.exec).string; segments = raw?.split(seperator).map((e) => e.trim()).toList(); if (raw == null || raw.isEmpty || segments == null || segments.isEmpty) { - _limiter.inc(sid); + TryLimiter.inc(sid); s.status.failedInfo = 'Seperate segments failed, raw:\n$raw'; _setServerState(s, ServerState.failed); return; } } catch (e) { - _limiter.inc(sid); + TryLimiter.inc(sid); s.status.failedInfo = e.toString(); _setServerState(s, ServerState.failed); Loggers.app.warning('Get status from ${spi.name} failed', e); @@ -372,7 +370,7 @@ class ServerProvider extends ChangeNotifier { final systemType = SystemType.parse(segments[0]); if (!systemType.isSegmentsLenMatch(segments.length)) { - _limiter.inc(sid); + TryLimiter.inc(sid); s.status.failedInfo = 'Segments not match: expect ${systemType.segmentsLen}, got ${segments.length}'; _setServerState(s, ServerState.failed); @@ -388,7 +386,7 @@ class ServerProvider extends ChangeNotifier { ); s.status = await compute(getStatus, req); } catch (e, trace) { - _limiter.inc(sid); + TryLimiter.inc(sid); s.status.failedInfo = 'Parse failed: $e\n\n$raw'; _setServerState(s, ServerState.failed); Loggers.parse.warning('Server status', e, trace); @@ -398,7 +396,7 @@ class ServerProvider extends ChangeNotifier { /// Call this every time for setting [Server.isBusy] to false _setServerState(s, ServerState.finished); // reset try times only after prepared successfully - _limiter.reset(sid); + TryLimiter.reset(sid); } Future runSnippets(String id, Snippet snippet) async { diff --git a/lib/view/page/server/tab.dart b/lib/view/page/server/tab.dart index 9deef58c..d40952fe 100644 --- a/lib/view/page/server/tab.dart +++ b/lib/view/page/server/tab.dart @@ -11,6 +11,7 @@ import 'package:toolbox/core/extension/ssh_client.dart'; import 'package:toolbox/core/utils/platform/base.dart'; import 'package:toolbox/core/utils/share.dart'; import 'package:toolbox/data/model/app/shell_func.dart'; +import 'package:toolbox/data/model/server/try_limiter.dart'; import 'package:toolbox/data/res/provider.dart'; import 'package:toolbox/data/res/store.dart'; @@ -335,7 +336,22 @@ class _ServerPageState extends State ServerPrivateInfo spi, ) { Widget? rightCorner; - if (!(spi.autoConnect ?? true) && cs == ServerState.disconnected) { + if (cs == ServerState.failed) { + rightCorner = InkWell( + onTap: () { + TryLimiter.reset(spi.id); + Pros.server.refreshData(spi: spi); + }, + child: const Padding( + padding: EdgeInsets.symmetric(horizontal: 7), + child: Icon( + Icons.refresh, + size: 21, + color: Colors.grey, + ), + ), + ); + } else if (!(spi.autoConnect ?? true) && cs == ServerState.disconnected) { rightCorner = InkWell( onTap: () => Pros.server.refreshData(spi: spi), child: const Padding(