Restart ComfyUI automatically after plugin updates
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
const RESTART_STATUS_URL = "/o1key/restart/status";
|
||||
const RESTART_TIMEOUT_MS = 120_000;
|
||||
let restartInProgress = false;
|
||||
|
||||
async function readJson(response) {
|
||||
const data = await response.json().catch(() => ({}));
|
||||
if (!response.ok) throw new Error(data.error || `请求失败 (${response.status})`);
|
||||
return data;
|
||||
}
|
||||
|
||||
function delay(milliseconds) {
|
||||
return new Promise((resolve) => window.setTimeout(resolve, milliseconds));
|
||||
}
|
||||
|
||||
async function fetchWithTimeout(url, options = {}, timeout = 2_500) {
|
||||
const controller = new AbortController();
|
||||
const timer = window.setTimeout(() => controller.abort(), timeout);
|
||||
try {
|
||||
return await fetch(url, {
|
||||
...options,
|
||||
cache: "no-store",
|
||||
signal: controller.signal,
|
||||
});
|
||||
} finally {
|
||||
window.clearTimeout(timer);
|
||||
}
|
||||
}
|
||||
|
||||
async function getRestartStatus() {
|
||||
const separator = RESTART_STATUS_URL.includes("?") ? "&" : "?";
|
||||
const response = await fetchWithTimeout(
|
||||
`${RESTART_STATUS_URL}${separator}_=${Date.now()}`
|
||||
);
|
||||
return readJson(response);
|
||||
}
|
||||
|
||||
function setRestartButtonState(button, busy) {
|
||||
if (!button) return;
|
||||
button.disabled = busy;
|
||||
button.setAttribute("aria-busy", String(busy));
|
||||
button.setAttribute("aria-label", busy ? "ComfyUI 正在重启" : "重启");
|
||||
button.setAttribute("title", busy ? "ComfyUI 正在重启" : "重启");
|
||||
|
||||
const icon = button.querySelector(".side-bar-button-icon");
|
||||
if (icon) {
|
||||
icon.className = busy
|
||||
? "pi pi-spinner pi-spin side-bar-button-icon"
|
||||
: "pi pi-refresh side-bar-button-icon";
|
||||
}
|
||||
|
||||
const label = button.querySelector(".side-bar-button-label");
|
||||
if (label) label.textContent = busy ? "重启中" : "重启";
|
||||
}
|
||||
|
||||
async function waitForRestart(oldBootId) {
|
||||
const deadline = Date.now() + RESTART_TIMEOUT_MS;
|
||||
|
||||
while (Date.now() < deadline) {
|
||||
try {
|
||||
const status = await getRestartStatus();
|
||||
if (status.ready && status.boot_id && status.boot_id !== oldBootId) {
|
||||
const systemStatus = await fetchWithTimeout(
|
||||
`/api/system_stats?_=${Date.now()}`
|
||||
);
|
||||
if (systemStatus.ok) return;
|
||||
}
|
||||
} catch {
|
||||
// 旧进程退出到新进程监听端口之间,接口暂时不可用是正常状态。
|
||||
}
|
||||
await delay(1_000);
|
||||
}
|
||||
|
||||
throw new Error("等待 ComfyUI 重启超时,请查看终端中的错误信息。");
|
||||
}
|
||||
|
||||
function reloadAfterRestart() {
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set("o1key_restart", Date.now().toString());
|
||||
window.location.replace(url.toString());
|
||||
}
|
||||
|
||||
export async function startComfyUIRestart() {
|
||||
if (restartInProgress) throw new Error("ComfyUI 正在重启,请稍候。");
|
||||
restartInProgress = true;
|
||||
let reloadRequested = false;
|
||||
const button = document.querySelector("#o1key-restart-button");
|
||||
setRestartButtonState(button, true);
|
||||
|
||||
try {
|
||||
let currentStatus = null;
|
||||
try {
|
||||
currentStatus = await getRestartStatus();
|
||||
} catch {
|
||||
// POST 响应还会返回旧进程的 boot_id,因此预检失败不阻断重启。
|
||||
}
|
||||
|
||||
const response = await fetchWithTimeout("/o1key/restart", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: "{}",
|
||||
}, 5_000);
|
||||
const result = await readJson(response);
|
||||
const oldBootId = result.boot_id || currentStatus?.boot_id;
|
||||
if (!oldBootId) throw new Error("无法确认当前 ComfyUI 进程标识。");
|
||||
|
||||
await waitForRestart(oldBootId);
|
||||
reloadAfterRestart();
|
||||
reloadRequested = true;
|
||||
} catch (error) {
|
||||
setRestartButtonState(button, false);
|
||||
throw error;
|
||||
} finally {
|
||||
if (!reloadRequested) restartInProgress = false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user