feat (ui): exec fase 5
This commit is contained in:
@@ -420,6 +420,9 @@ let execTerminalState = {
|
|||||||
outputText: '',
|
outputText: '',
|
||||||
outputLineCount: 0,
|
outputLineCount: 0,
|
||||||
outputTruncated: false,
|
outputTruncated: false,
|
||||||
|
sessionInfo: null,
|
||||||
|
infoPollTimer: null,
|
||||||
|
infoTickTimer: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const EXEC_OUTPUT_MAX_CHARS = 200000;
|
const EXEC_OUTPUT_MAX_CHARS = 200000;
|
||||||
@@ -430,6 +433,8 @@ const EXEC_RECONNECT_BASE_MS = 350;
|
|||||||
const EXEC_RECONNECT_MAX_MS = 5000;
|
const EXEC_RECONNECT_MAX_MS = 5000;
|
||||||
const EXEC_RECONNECT_MAX_ATTEMPTS = 8;
|
const EXEC_RECONNECT_MAX_ATTEMPTS = 8;
|
||||||
const EXEC_PASTE_CHUNK_SIZE = 2048;
|
const EXEC_PASTE_CHUNK_SIZE = 2048;
|
||||||
|
const EXEC_SESSION_INFO_POLL_MS = 7000;
|
||||||
|
const EXEC_IDLE_TTL_SECONDS = 60 * 60;
|
||||||
|
|
||||||
function _execEls() {
|
function _execEls() {
|
||||||
return {
|
return {
|
||||||
@@ -526,7 +531,73 @@ function _execInitTerminal() {
|
|||||||
|
|
||||||
function _execConnectedStatus() {
|
function _execConnectedStatus() {
|
||||||
const sid = execTerminalState.sessionId || '';
|
const sid = execTerminalState.sessionId || '';
|
||||||
return sid ? `Connected (${sid})` : 'Connected';
|
if (!sid) return 'Connected';
|
||||||
|
const info = execTerminalState.sessionInfo;
|
||||||
|
if (!info) return `Connected (${sid})`;
|
||||||
|
if (info.closed) return `Session closed: ${info.close_reason || 'closed'}`;
|
||||||
|
|
||||||
|
const last = Number(info.last_activity || 0);
|
||||||
|
if (!Number.isFinite(last) || last <= 0) return `Connected (${sid})`;
|
||||||
|
const now = Math.floor(Date.now() / 1000);
|
||||||
|
const idleAge = Math.max(0, now - last);
|
||||||
|
const idleLeft = Math.max(0, EXEC_IDLE_TTL_SECONDS - idleAge);
|
||||||
|
const mm = String(Math.floor(idleLeft / 60)).padStart(2, '0');
|
||||||
|
const ss = String(idleLeft % 60).padStart(2, '0');
|
||||||
|
return `Connected (${sid}) - idle in ${mm}:${ss}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _execStopSessionInfoTimers() {
|
||||||
|
if (execTerminalState.infoPollTimer) {
|
||||||
|
clearInterval(execTerminalState.infoPollTimer);
|
||||||
|
execTerminalState.infoPollTimer = null;
|
||||||
|
}
|
||||||
|
if (execTerminalState.infoTickTimer) {
|
||||||
|
clearInterval(execTerminalState.infoTickTimer);
|
||||||
|
execTerminalState.infoTickTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _execCanUpdateConnectedStatus() {
|
||||||
|
if (!execTerminalState.sessionId) return false;
|
||||||
|
if (
|
||||||
|
execTerminalState.reconnectEnabled &&
|
||||||
|
execTerminalState.reconnectAttempts > 0 &&
|
||||||
|
!execTerminalState.source
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function _execRefreshSessionInfo() {
|
||||||
|
const sid = execTerminalState.sessionId;
|
||||||
|
if (!sid) return;
|
||||||
|
try {
|
||||||
|
const info = await api(`/containers/exec/${encodeURIComponent(sid)}`, 'GET');
|
||||||
|
if (sid !== execTerminalState.sessionId) return;
|
||||||
|
execTerminalState.sessionInfo = info || null;
|
||||||
|
if (execTerminalState.sessionInfo?.closed) {
|
||||||
|
execTerminalState.reconnectEnabled = false;
|
||||||
|
_execCancelReconnect();
|
||||||
|
_execCloseEventSource();
|
||||||
|
_execSetStatus(`Session closed: ${execTerminalState.sessionInfo.close_reason || 'closed'}`);
|
||||||
|
_execStopSessionInfoTimers();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_execCanUpdateConnectedStatus()) _execSetStatus(_execConnectedStatus());
|
||||||
|
} catch (_) {
|
||||||
|
// stream reconnect status has priority
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _execStartSessionInfoTimers() {
|
||||||
|
_execStopSessionInfoTimers();
|
||||||
|
_execRefreshSessionInfo();
|
||||||
|
execTerminalState.infoPollTimer = setInterval(_execRefreshSessionInfo, EXEC_SESSION_INFO_POLL_MS);
|
||||||
|
execTerminalState.infoTickTimer = setInterval(() => {
|
||||||
|
if (!_execCanUpdateConnectedStatus()) return;
|
||||||
|
_execSetStatus(_execConnectedStatus());
|
||||||
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _execAppendOutput(txt) {
|
function _execAppendOutput(txt) {
|
||||||
@@ -888,7 +959,9 @@ async function containerExecOpen(name) {
|
|||||||
execTerminalState.sessionId = '';
|
execTerminalState.sessionId = '';
|
||||||
execTerminalState.lastSeq = 0;
|
execTerminalState.lastSeq = 0;
|
||||||
execTerminalState.reconnectEnabled = false;
|
execTerminalState.reconnectEnabled = false;
|
||||||
|
execTerminalState.sessionInfo = null;
|
||||||
_execCancelReconnect();
|
_execCancelReconnect();
|
||||||
|
_execStopSessionInfoTimers();
|
||||||
execTerminalState.rawMode = true;
|
execTerminalState.rawMode = true;
|
||||||
_execInitTerminal();
|
_execInitTerminal();
|
||||||
_execUpdateInputModeUi();
|
_execUpdateInputModeUi();
|
||||||
@@ -907,8 +980,10 @@ async function containerExecOpen(name) {
|
|||||||
execTerminalState.sessionId = sid;
|
execTerminalState.sessionId = sid;
|
||||||
execTerminalState.lastSeq = 0;
|
execTerminalState.lastSeq = 0;
|
||||||
execTerminalState.reconnectEnabled = true;
|
execTerminalState.reconnectEnabled = true;
|
||||||
|
execTerminalState.sessionInfo = null;
|
||||||
_execSetStatus(`Connected (${sid})`);
|
_execSetStatus(`Connected (${sid})`);
|
||||||
_execAttachStream(0, false);
|
_execAttachStream(0, false);
|
||||||
|
_execStartSessionInfoTimers();
|
||||||
|
|
||||||
_execScheduleResize();
|
_execScheduleResize();
|
||||||
|
|
||||||
@@ -998,6 +1073,7 @@ async function containerExecClose() {
|
|||||||
|
|
||||||
execTerminalState.reconnectEnabled = false;
|
execTerminalState.reconnectEnabled = false;
|
||||||
_execCancelReconnect();
|
_execCancelReconnect();
|
||||||
|
_execStopSessionInfoTimers();
|
||||||
_execCloseEventSource();
|
_execCloseEventSource();
|
||||||
_execDestroyTerminal();
|
_execDestroyTerminal();
|
||||||
_execSetTerminalUiMode(false);
|
_execSetTerminalUiMode(false);
|
||||||
@@ -1013,6 +1089,7 @@ async function containerExecClose() {
|
|||||||
|
|
||||||
execTerminalState.sessionId = '';
|
execTerminalState.sessionId = '';
|
||||||
execTerminalState.lastSeq = 0;
|
execTerminalState.lastSeq = 0;
|
||||||
|
execTerminalState.sessionInfo = null;
|
||||||
if (els.back) els.back.style.display = 'none';
|
if (els.back) els.back.style.display = 'none';
|
||||||
|
|
||||||
if (sid) {
|
if (sid) {
|
||||||
|
|||||||
Reference in New Issue
Block a user