new: manual refresh failed servers

This commit is contained in:
lollipopkit
2023-11-03 00:38:06 -06:00
parent a9f9a1650e
commit a1b9cecebb
3 changed files with 38 additions and 22 deletions

View File

@@ -3,27 +3,29 @@ import 'package:toolbox/data/res/store.dart';
class TryLimiter { class TryLimiter {
final Map<String, int> _triedTimes = {}; final Map<String, int> _triedTimes = {};
bool canTry(String id) { static final _default = TryLimiter();
static bool canTry(String id) {
final maxCount = Stores.setting.maxRetryCount.fetch(); final maxCount = Stores.setting.maxRetryCount.fetch();
if (maxCount <= 0) { if (maxCount <= 0) {
return true; return true;
} }
final times = _triedTimes[id] ?? 0; final times = _default._triedTimes[id] ?? 0;
if (times >= maxCount) { if (times >= maxCount) {
return false; return false;
} }
return true; return true;
} }
void inc(String sid) { static void inc(String sid) {
_triedTimes[sid] = (_triedTimes[sid] ?? 0) + 1; _default._triedTimes[sid] = (_default._triedTimes[sid] ?? 0) + 1;
} }
void reset(String id) { static void reset(String id) {
_triedTimes[id] = 0; _default._triedTimes[id] = 0;
} }
void clear() { static void clear() {
_triedTimes.clear(); _default._triedTimes.clear();
} }
} }

View File

@@ -31,8 +31,6 @@ class ServerProvider extends ChangeNotifier {
final List<String> _tags = []; final List<String> _tags = [];
List<String> get tags => _tags; List<String> get tags => _tags;
final _limiter = TryLimiter();
Timer? _timer; Timer? _timer;
Future<void> load() async { Future<void> load() async {
@@ -124,7 +122,7 @@ class ServerProvider extends ChangeNotifier {
Future<void> _connectFn(Server s, bool onlyFailed) async { Future<void> _connectFn(Server s, bool onlyFailed) async {
if (onlyFailed) { if (onlyFailed) {
if (s.state != ServerState.failed) return; 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. /// 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) { for (final s in _servers.values) {
s.state = ServerState.disconnected; s.state = ServerState.disconnected;
} }
_limiter.clear(); //TryLimiter.clear();
notifyListeners(); notifyListeners();
} }
@@ -227,7 +225,7 @@ class ServerProvider extends ChangeNotifier {
// Only reconnect if neccessary // Only reconnect if neccessary
if (newSpi.shouldReconnect(old)) { if (newSpi.shouldReconnect(old)) {
// Use [newSpi.id] instead of [old.id] because [old.id] may be changed // Use [newSpi.id] instead of [old.id] because [old.id] may be changed
_limiter.reset(newSpi.id); TryLimiter.reset(newSpi.id);
refreshData(spi: newSpi); refreshData(spi: newSpi);
} }
@@ -256,7 +254,7 @@ class ServerProvider extends ChangeNotifier {
if (s == null) return; if (s == null) return;
if (!_limiter.canTry(sid)) { if (!TryLimiter.canTry(sid)) {
if (s.state != ServerState.failed) { if (s.state != ServerState.failed) {
_setServerState(s, ServerState.failed); _setServerState(s, ServerState.failed);
} }
@@ -289,7 +287,7 @@ class ServerProvider extends ChangeNotifier {
); );
} }
} catch (e) { } catch (e) {
_limiter.inc(sid); TryLimiter.inc(sid);
s.status.failedInfo = e.toString(); s.status.failedInfo = e.toString();
_setServerState(s, ServerState.failed); _setServerState(s, ServerState.failed);
@@ -332,7 +330,7 @@ class ServerProvider extends ChangeNotifier {
throw err; throw err;
} }
} catch (e) { } catch (e) {
_limiter.inc(sid); TryLimiter.inc(sid);
s.status.failedInfo = e.toString(); s.status.failedInfo = e.toString();
_setServerState(s, ServerState.failed); _setServerState(s, ServerState.failed);
Loggers.app.warning('Write script to ${spi.name} by sftp', e); 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; raw = await s.client?.run(ShellFunc.status.exec).string;
segments = raw?.split(seperator).map((e) => e.trim()).toList(); segments = raw?.split(seperator).map((e) => e.trim()).toList();
if (raw == null || raw.isEmpty || segments == null || segments.isEmpty) { if (raw == null || raw.isEmpty || segments == null || segments.isEmpty) {
_limiter.inc(sid); TryLimiter.inc(sid);
s.status.failedInfo = 'Seperate segments failed, raw:\n$raw'; s.status.failedInfo = 'Seperate segments failed, raw:\n$raw';
_setServerState(s, ServerState.failed); _setServerState(s, ServerState.failed);
return; return;
} }
} catch (e) { } catch (e) {
_limiter.inc(sid); TryLimiter.inc(sid);
s.status.failedInfo = e.toString(); s.status.failedInfo = e.toString();
_setServerState(s, ServerState.failed); _setServerState(s, ServerState.failed);
Loggers.app.warning('Get status from ${spi.name} failed', e); Loggers.app.warning('Get status from ${spi.name} failed', e);
@@ -372,7 +370,7 @@ class ServerProvider extends ChangeNotifier {
final systemType = SystemType.parse(segments[0]); final systemType = SystemType.parse(segments[0]);
if (!systemType.isSegmentsLenMatch(segments.length)) { if (!systemType.isSegmentsLenMatch(segments.length)) {
_limiter.inc(sid); TryLimiter.inc(sid);
s.status.failedInfo = s.status.failedInfo =
'Segments not match: expect ${systemType.segmentsLen}, got ${segments.length}'; 'Segments not match: expect ${systemType.segmentsLen}, got ${segments.length}';
_setServerState(s, ServerState.failed); _setServerState(s, ServerState.failed);
@@ -388,7 +386,7 @@ class ServerProvider extends ChangeNotifier {
); );
s.status = await compute(getStatus, req); s.status = await compute(getStatus, req);
} catch (e, trace) { } catch (e, trace) {
_limiter.inc(sid); TryLimiter.inc(sid);
s.status.failedInfo = 'Parse failed: $e\n\n$raw'; s.status.failedInfo = 'Parse failed: $e\n\n$raw';
_setServerState(s, ServerState.failed); _setServerState(s, ServerState.failed);
Loggers.parse.warning('Server status', e, trace); 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 /// Call this every time for setting [Server.isBusy] to false
_setServerState(s, ServerState.finished); _setServerState(s, ServerState.finished);
// reset try times only after prepared successfully // reset try times only after prepared successfully
_limiter.reset(sid); TryLimiter.reset(sid);
} }
Future<SnippetResult?> runSnippets(String id, Snippet snippet) async { Future<SnippetResult?> runSnippets(String id, Snippet snippet) async {

View File

@@ -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/platform/base.dart';
import 'package:toolbox/core/utils/share.dart'; import 'package:toolbox/core/utils/share.dart';
import 'package:toolbox/data/model/app/shell_func.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/provider.dart';
import 'package:toolbox/data/res/store.dart'; import 'package:toolbox/data/res/store.dart';
@@ -335,7 +336,22 @@ class _ServerPageState extends State<ServerPage>
ServerPrivateInfo spi, ServerPrivateInfo spi,
) { ) {
Widget? rightCorner; 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( rightCorner = InkWell(
onTap: () => Pros.server.refreshData(spi: spi), onTap: () => Pros.server.refreshData(spi: spi),
child: const Padding( child: const Padding(