mirror of
https://github.com/chaos-zhu/easynode.git
synced 2026-10-06 12:33:59 +08:00
feat: native 重连机制优化
This commit is contained in:
@@ -50,8 +50,15 @@ class SshTerminalController {
|
||||
try {
|
||||
final transport = await _transportFactory.open(
|
||||
config,
|
||||
logger: (message) => terminal.write('[Info] $message\r\n'),
|
||||
logger: (message) {
|
||||
if (_disposed) return;
|
||||
terminal.write('[Info] $message\r\n');
|
||||
},
|
||||
);
|
||||
if (_disposed) {
|
||||
await transport.close();
|
||||
return;
|
||||
}
|
||||
_transport = transport;
|
||||
terminal.write('[Info] 准备连接目标终端: ${config.name} - ${config.host}\r\n');
|
||||
// dartssh2 `SSHKeyPair.fromPem` already returns `List<SSHKeyPair>`, no
|
||||
@@ -68,18 +75,24 @@ class SshTerminalController {
|
||||
identities: identities,
|
||||
);
|
||||
} on SshTransportException catch (error) {
|
||||
if (_disposed) return;
|
||||
terminal.write('[Error] ${error.message}\r\n');
|
||||
rethrow;
|
||||
} catch (error) {
|
||||
if (_disposed) return;
|
||||
terminal.write('[Error] $error\r\n');
|
||||
rethrow;
|
||||
}
|
||||
if (_disposed) return;
|
||||
final session = await _client!.shell();
|
||||
if (_disposed) return;
|
||||
_session = session;
|
||||
_stdoutSub = session.stdout.listen((data) {
|
||||
if (_disposed) return;
|
||||
_writeTerminalOutput(utf8.decode(data, allowMalformed: true));
|
||||
});
|
||||
_stderrSub = session.stderr.listen((data) {
|
||||
if (_disposed) return;
|
||||
_writeTerminalOutput(utf8.decode(data, allowMalformed: true));
|
||||
});
|
||||
terminal.onOutput = (data) {
|
||||
@@ -140,6 +153,8 @@ class SshTerminalController {
|
||||
|
||||
Future<void> disconnect() async {
|
||||
_disposed = true;
|
||||
terminal.onOutput = null;
|
||||
terminal.onResize = null;
|
||||
await _stdoutSub?.cancel();
|
||||
await _stderrSub?.cancel();
|
||||
_stdoutSub = null;
|
||||
|
||||
@@ -74,12 +74,18 @@ class TerminalSessionManager extends ChangeNotifier {
|
||||
final session = _findOrNull(id);
|
||||
if (session == null) return;
|
||||
final terminal = session.controller.terminal;
|
||||
await session.controller.disconnect();
|
||||
// Force-disconnect regardless of current state (connecting/connected/error).
|
||||
final oldController = session.controller;
|
||||
session.controller = SshTerminalController(
|
||||
config: session.config,
|
||||
terminal: terminal,
|
||||
);
|
||||
session.controller.terminal.write('\r\n[Reconnecting]\r\n');
|
||||
session.status = TerminalSessionStatus.connecting;
|
||||
notifyListeners();
|
||||
// Tear down the old controller in the background — it no longer owns the
|
||||
// terminal so its disconnect cannot interfere with the new connection.
|
||||
unawaited(oldController.disconnect());
|
||||
terminal.write('\r\n[Reconnecting]\r\n');
|
||||
await _connect(session);
|
||||
}
|
||||
|
||||
@@ -112,12 +118,18 @@ class TerminalSessionManager extends ChangeNotifier {
|
||||
}
|
||||
|
||||
Future<void> _connect(TerminalSession session) async {
|
||||
final controller = session.controller;
|
||||
session.status = TerminalSessionStatus.connecting;
|
||||
session.lastError = null;
|
||||
notifyListeners();
|
||||
try {
|
||||
await session.controller.connect();
|
||||
if (!_sessions.contains(session)) return;
|
||||
await controller.connect();
|
||||
// After await, verify this controller is still the active one — a
|
||||
// concurrent reconnect may have replaced it.
|
||||
if (!_sessions.contains(session) ||
|
||||
session.controller != controller) {
|
||||
return;
|
||||
}
|
||||
session.status = TerminalSessionStatus.connected;
|
||||
notifyListeners();
|
||||
if (_shouldAutoStartStatusMonitor()) {
|
||||
@@ -129,7 +141,10 @@ class TerminalSessionManager extends ChangeNotifier {
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
if (!_sessions.contains(session)) return;
|
||||
if (!_sessions.contains(session) ||
|
||||
session.controller != controller) {
|
||||
return;
|
||||
}
|
||||
session.status = TerminalSessionStatus.error;
|
||||
session.lastError = error.toString();
|
||||
session.controller.terminal.write('\r\n[Error] ${session.lastError}\r\n');
|
||||
|
||||
Reference in New Issue
Block a user