diff --git a/README.md b/README.md
index 870a382..291287a 100644
--- a/README.md
+++ b/README.md
@@ -49,7 +49,6 @@
http_url TEXT NOT NULL,
ws_url TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'offline',
- last_heartbeat DATETIME,
last_health_check DATETIME,
current_tasks INTEGER DEFAULT 0,
max_concurrent_tasks INTEGER DEFAULT 1,
@@ -127,7 +126,6 @@ ComfyUI 服务器管理器现在支持持久化功能,这意味着即使管理
- **自动持久化**: 服务器注册、状态变化、注销时自动保存到数据库
- **自动恢复**: 服务启动时自动从数据库加载已注册的服务器
- **健康检查**: 定期检查服务器健康状态并更新数据库
-- **心跳机制**: 支持服务器主动发送心跳,自动检测超时
## 使用方法
diff --git a/js/publisher.js b/js/publisher.js
index bff598f..ca1e763 100644
--- a/js/publisher.js
+++ b/js/publisher.js
@@ -1,413 +1,44 @@
import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js";
-// 检测ComfyUI服务端口的函数
-async function detectComfyUIPort(host) {
- try {
- const currentPort = window.location.port;
- if (currentPort) {
- console.log(`从当前页面URL获取端口: ${currentPort}`);
- return parseInt(currentPort);
- }
- } catch (error) {
- console.warn("无法从当前页面获取端口:", error);
- }
-
- // 默认返回8188
- console.warn("无法检测到ComfyUI端口,使用默认端口8188");
- return 8188;
-}
-
-// 获取本地IP地址的函数
-async function getLocalIPAddress() {
- try {
- // 尝试通过WebRTC获取本地IP地址
- const pc = new RTCPeerConnection({
- iceServers: [],
- });
-
- pc.createDataChannel("");
- const offer = await pc.createOffer();
- await pc.setLocalDescription(offer);
-
- return new Promise((resolve) => {
- pc.onicecandidate = (event) => {
- if (event.candidate) {
- const ipMatch = event.candidate.candidate.match(
- /([0-9]{1,3}(\.[0-9]{1,3}){3})/
- );
- if (ipMatch) {
- const localIP = ipMatch[1];
- // 保留有效的内网IP地址
- if (
- localIP.startsWith("192.168.") ||
- localIP.startsWith("10.") ||
- localIP.startsWith("172.") ||
- localIP === "127.0.0.1"
- ) {
- pc.close();
- resolve(localIP);
- }
- }
- }
- };
-
- // 超时处理
- setTimeout(() => {
- pc.close();
- resolve("127.0.0.1"); // 如果获取失败,使用默认地址
- }, 3000);
- });
- } catch (error) {
- console.warn("无法获取本地IP地址,使用默认地址:", error);
- return "127.0.0.1";
- }
-}
-
// 本地存储的 key
-const COMFY_SERVER_REGISTRATION_KEY = "comfyui_server_registration";
+const WORKFLOW_SERVICE_HOST_KEY = "workflow_publisher_service_host";
-// ComfyUI服务器注册配置 - 使用动态IP地址
-let DEFAULT_SERVER_CONFIG = {
- name: "comfyui_node_1",
- http_url: "http://127.0.0.1:8188", // 将在初始化时更新为实际IP
- workflow_service_host: "http://localhost:8000",
-};
+// 默认工作流服务地址
+const DEFAULT_WORKFLOW_SERVICE_HOST = "http://localhost:8000";
-// 初始化默认配置
-async function initializeDefaultConfig() {
+// 获取工作流服务地址
+function getWorkflowServiceHost() {
try {
- const localIP = await getLocalIPAddress();
- const port = await detectComfyUIPort(localIP);
- DEFAULT_SERVER_CONFIG.http_url = `http://${localIP}:${port}`;
- console.log("自动获取本地IP地址和端口:", localIP, port);
+ const stored = localStorage.getItem(WORKFLOW_SERVICE_HOST_KEY);
+ return stored || DEFAULT_WORKFLOW_SERVICE_HOST;
} catch (error) {
- console.warn("初始化IP地址和端口失败,使用默认地址:", error);
+ console.error("读取工作流服务地址失败:", error);
+ return DEFAULT_WORKFLOW_SERVICE_HOST;
}
}
-// 获取ComfyUI服务器注册配置
-function getComfyServerConfig() {
+// 保存工作流服务地址
+function saveWorkflowServiceHost(host) {
try {
- const stored = localStorage.getItem(COMFY_SERVER_REGISTRATION_KEY);
- return stored ? JSON.parse(stored) : { ...DEFAULT_SERVER_CONFIG };
+ localStorage.setItem(WORKFLOW_SERVICE_HOST_KEY, host);
} catch (error) {
- console.error("读取ComfyUI服务器配置失败:", error);
- return { ...DEFAULT_SERVER_CONFIG };
+ console.error("保存工作流服务地址失败:", error);
}
}
-// 保存ComfyUI服务器注册配置
-function saveComfyServerConfig(config) {
- try {
- localStorage.setItem(COMFY_SERVER_REGISTRATION_KEY, JSON.stringify(config));
- } catch (error) {
- console.error("保存ComfyUI服务器配置失败:", error);
- }
-}
-
-// 获取本地设置
-function getLocalSettings() {
- try {
- const stored = localStorage.getItem("workflow_publisher_settings");
- return stored ? JSON.parse(stored) : { host: "" };
- } catch (error) {
- console.error("读取本地设置失败:", error);
- return { host: "" };
- }
-}
-
-// 保存本地设置
-function saveLocalSettings(settings) {
- try {
- localStorage.setItem(
- "workflow_publisher_settings",
- JSON.stringify(settings)
- );
- } catch (error) {
- console.error("保存本地设置失败:", error);
- }
-}
-
-// ComfyUI服务器注册管理器
-class ComfyServerManager {
- constructor() {
- this.registrationInterval = null;
- this.heartbeatInterval = null;
- this.isRegistered = false;
- this.serverConfig = getComfyServerConfig();
- }
-
- // 注册服务器到工作流服务
- async registerServer() {
- if (!this.serverConfig.workflow_service_host) {
- return { success: false, error: "未设置工作流服务地址" };
- }
-
- try {
- const response = await fetch(
- `${this.serverConfig.workflow_service_host}/api/comfy/register`,
- {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- name: this.serverConfig.name,
- http_url: this.serverConfig.http_url,
- ws_url: this.getWebSocketUrl(),
- }),
- }
- );
-
- if (response.ok) {
- const result = await response.json();
- console.log("ComfyUI服务器注册成功:", result);
- this.isRegistered = true;
- this.startHeartbeat();
- return { success: true };
- } else {
- const errorText = await response.text();
- const errorMessage = `HTTP ${response.status}: ${
- errorText || "服务器响应错误"
- }`;
- console.error("ComfyUI服务器注册失败:", errorMessage);
- return { success: false, error: errorMessage };
- }
- } catch (error) {
- const errorMessage = `网络错误: ${error.message}`;
- console.error("注册ComfyUI服务器时发生错误:", errorMessage);
- return { success: false, error: errorMessage };
- }
- }
-
- // 注销服务器
- async unregisterServer() {
- if (!this.serverConfig.workflow_service_host || !this.isRegistered) {
- return { success: false, error: "未设置工作流服务地址或服务器未注册" };
- }
-
- try {
- const response = await fetch(
- `${this.serverConfig.workflow_service_host}/api/comfy/unregister`,
- {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({ name: this.serverConfig.name }),
- }
- );
-
- if (response.ok) {
- console.log("ComfyUI服务器注销成功");
- this.isRegistered = false;
- this.stopHeartbeat();
- return { success: true };
- } else {
- const errorText = await response.text();
- const errorMessage = `HTTP ${response.status}: ${
- errorText || "服务器响应错误"
- }`;
- console.error("ComfyUI服务器注销失败:", errorMessage);
- return { success: false, error: errorMessage };
- }
- } catch (error) {
- const errorMessage = `网络错误: ${error.message}`;
- console.error("注销ComfyUI服务器时发生错误:", errorMessage);
- return { success: false, error: errorMessage };
- }
- }
-
- // 发送心跳
- async sendHeartbeat() {
- if (!this.serverConfig.workflow_service_host || !this.isRegistered) {
- return false;
- }
-
- try {
- const response = await fetch(
- `${this.serverConfig.workflow_service_host}/api/comfy/heartbeat`,
- {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({ name: this.serverConfig.name }),
- }
- );
-
- if (response.ok) {
- console.debug("心跳发送成功");
- return true;
- } else {
- console.warn("心跳发送失败:", response.status);
- // 如果心跳失败,尝试重新注册
- if (response.status === 404) {
- console.log("服务器不存在,尝试重新注册...");
- this.isRegistered = false;
- await this.registerServer();
- }
- return false;
- }
- } catch (error) {
- console.error("发送心跳时发生错误:", error);
- // 如果网络错误,尝试重新注册
- this.isRegistered = false;
- await this.registerServer();
- return false;
- }
- }
-
- // 启动心跳
- startHeartbeat() {
- if (this.heartbeatInterval) {
- clearInterval(this.heartbeatInterval);
- }
-
- // 每30秒发送一次心跳
- this.heartbeatInterval = setInterval(() => {
- this.sendHeartbeat();
- }, 30000);
-
- console.log("ComfyUI服务器心跳已启动");
- }
-
- // 停止心跳
- stopHeartbeat() {
- if (this.heartbeatInterval) {
- clearInterval(this.heartbeatInterval);
- this.heartbeatInterval = null;
- }
- console.log("ComfyUI服务器心跳已停止");
- }
-
- // 更新服务器配置
- updateConfig(newConfig) {
- this.serverConfig = { ...this.serverConfig, ...newConfig };
- saveComfyServerConfig(this.serverConfig);
-
- // 如果已注册,需要重新注册以更新配置
- if (this.isRegistered) {
- this.unregisterServer().then((result) => {
- if (result.success) {
- setTimeout(() => this.registerServer(), 1000);
- } else {
- console.warn("更新配置时注销失败:", result.error);
- }
- });
- }
- }
-
- // 设置工作流服务地址
- setWorkflowServiceHost(host) {
- this.serverConfig.workflow_service_host = host;
- saveComfyServerConfig(this.serverConfig);
- }
-
- // 获取WebSocket URL(自动从HTTP URL生成)
- getWebSocketUrl() {
- if (!this.serverConfig.http_url) return "";
- const url = new URL(this.serverConfig.http_url);
- // 根据协议自动选择ws或wss
- const protocol = url.protocol === "https:" ? "wss:" : "ws:";
- return `${protocol}//${url.host}/ws`;
- }
-
- // 获取服务器状态
- async getServerStatus() {
- if (!this.serverConfig.workflow_service_host) {
- return null;
- }
-
- try {
- const response = await fetch(
- `${this.serverConfig.workflow_service_host}/api/comfy/status/${this.serverConfig.name}`
- );
- if (response.ok) {
- return await response.json();
- }
- } catch (error) {
- console.error("获取服务器状态失败:", error);
- }
- return null;
- }
-
- // 获取系统健康状态
- async getSystemHealth() {
- if (!this.serverConfig.workflow_service_host) {
- return null;
- }
-
- try {
- const response = await fetch(
- `${this.serverConfig.workflow_service_host}/api/comfy/health`
- );
- if (response.ok) {
- return await response.json();
- }
- } catch (error) {
- console.error("获取系统健康状态失败:", error);
- }
- return null;
- }
-
- // 动态更新IP地址和端口
- async updateLocalIPAddress() {
- try {
- const localIP = await getLocalIPAddress();
- const port = await detectComfyUIPort(localIP);
- const newHttpUrl = `http://${localIP}:${port}`;
-
- if (this.serverConfig.http_url !== newHttpUrl) {
- this.serverConfig.http_url = newHttpUrl;
- saveComfyServerConfig(this.serverConfig);
- console.log("已更新本地IP地址和端口:", localIP, port);
- return { ip: localIP, port: port };
- }
- return null;
- } catch (error) {
- console.warn("更新IP地址和端口失败:", error);
- return null;
- }
- }
-
- // 同步注册状态
- syncRegistrationStatus() {
- if (this.serverConfig.workflow_service_host) {
- this.getServerStatus()
- .then((status) => {
- if (status) {
- this.isRegistered = true;
- console.log("同步注册状态: 已注册");
- } else {
- this.isRegistered = false;
- console.log("同步注册状态: 未注册");
- }
- })
- .catch((error) => {
- console.warn("同步注册状态失败:", error);
- this.isRegistered = false;
- });
- }
- }
-}
-
-// 自定义 fetchApi 函数,使用ComfyUI服务器配置中的工作流服务地址
+// 自定义 fetchApi 函数,使用配置的工作流服务地址
async function customFetchApi(endpoint, options = {}) {
try {
- // 从ComfyUI服务器配置获取工作流服务地址
- const serverConfig = getComfyServerConfig();
-
- // 如果没有配置工作流服务地址,回退到默认的 api.fetchApi
- if (!serverConfig.workflow_service_host) {
+ const host = getWorkflowServiceHost();
+ if (!host) {
console.warn("未配置工作流服务地址,使用默认的 ComfyUI API");
return await api.fetchApi(endpoint, options);
}
// 构建完整的 URL
- const host = serverConfig.workflow_service_host.replace(/\/$/, ""); // 移除末尾的斜杠
- const fullUrl = `${host}${endpoint}`;
+ const fullHost = host.replace(/\/$/, ""); // 移除末尾的斜杠
+ const fullUrl = `${fullHost}${endpoint}`;
console.log(`使用工作流服务地址请求: ${fullUrl}`);
@@ -457,7 +88,7 @@ function createElement(tagName, props) {
return element;
}
-// Modal class (保持不变)
+// Modal class
class Modal {
constructor(id, title, full_width = false) {
this.id = id;
@@ -502,9 +133,6 @@ const createButton = (innerHTML, title, { onClick }) => {
app.registerExtension({
name: "Comfy.WorkflowPublisher",
async setup() {
- // 初始化默认配置,获取本地IP地址
- await initializeDefaultConfig();
-
const addCustomStyles = () => {
const styleId = "jags-publisher-styles";
if (document.getElementById(styleId)) return;
@@ -552,21 +180,22 @@ app.registerExtension({
const iconGet = ``;
const iconPublish = ``;
+ const iconSettings = ``;
+
const btnGet = createButton(iconGet, "从服务器获取工作流", {
onClick: () => showWorkflowListDialog(),
});
const btnPublish = createButton(iconPublish, "发布当前工作流", {
onClick: () => showPublishDialog(),
});
-
- const btnComfyServer = createButton(`🖥️`, "ComfyUI服务器管理", {
- onClick: () => showComfyServerDialog(),
+ const btnSettings = createButton(iconSettings, "设置工作流服务地址", {
+ onClick: () => showSettingsDialog(),
});
const separator = document.createElement("div");
separator.style.cssText =
"border-left: 1px solid var(--border-color); height: 22px; margin: 0 4px;";
- container.append(btnGet, btnPublish, btnComfyServer, separator);
+ container.append(btnGet, btnPublish, btnSettings, separator);
menu.insertBefore(container, menu.firstChild);
});
@@ -581,10 +210,9 @@ app.registerExtension({
true
);
- const comfyServerDialog = new Modal(
- "comfy-server-dialog",
- "ComfyUI服务器管理",
- true
+ const settingsDialog = new Modal(
+ "workflow-publisher-settings-dialog",
+ "设置工作流服务地址"
);
async function showWorkflowListDialog() {
@@ -708,297 +336,93 @@ app.registerExtension({
}
}
- // ComfyUI 服务器管理对话框
- async function showComfyServerDialog() {
+ // 设置对话框
+ async function showSettingsDialog() {
try {
- const serverConfig = getComfyServerConfig();
- const settings = getLocalSettings();
+ const currentHost = getWorkflowServiceHost();
- // 创建服务器配置表单
- const configForm = `
+ const settingsForm = `
-
-
+
+
+ 这是用于获取和发布工作流的服务地址
-
-
-
-
WebSocket地址将自动生成为: ${
- serverConfig.http_url
- ? serverConfig.http_url.replace(/^https?:\/\//, "ws://") +
- "/ws"
- : ""
- }
+
+ 连接状态: 未测试
-
-
-
-
-
-
-
-
- 服务器状态: 未连接
-
-
-
-
-
-
-
+
+
+
`;
- comfyServerDialog.setContent(configForm);
- comfyServerDialog.addButtons([
- { label: "关闭", callback: () => comfyServerDialog.hide() },
+ settingsDialog.setContent(settingsForm);
+ settingsDialog.addButtons([
+ { label: "关闭", callback: () => settingsDialog.hide() },
]);
- comfyServerDialog.show();
-
- // 初始化 ComfyServerManager
- const serverManager = new ComfyServerManager();
- if (settings.host) {
- serverManager.setWorkflowServiceHost(settings.host);
- // 同步注册状态
- serverManager.syncRegistrationStatus();
- }
+ settingsDialog.show();
// 绑定事件
- const btnRegister = document.getElementById("btn-register");
- const btnUnregister = document.getElementById("btn-unregister");
- const btnRefreshStatus = document.getElementById("btn-refresh-status");
- const btnRefreshIP = document.getElementById("btn-refresh-ip");
+ const btnTestConnection = document.getElementById(
+ "btn-test-connection"
+ );
+ const btnSaveSettings = document.getElementById("btn-save-settings");
const statusText = document.getElementById("status-text");
+ const hostInput = document.getElementById("workflow-service-host");
- // 添加HTTP地址输入框的实时预览功能
- const httpUrlInput = document.getElementById("server-http-url");
- const wsUrlPreview = document.getElementById("ws-url-preview");
-
- httpUrlInput.addEventListener("input", function () {
- const httpUrl = this.value;
- if (httpUrl) {
- try {
- const url = new URL(httpUrl);
- // 根据协议自动选择ws或wss
- const protocol = url.protocol === "https:" ? "wss:" : "ws:";
- const wsUrl = `${protocol}//${url.host}/ws`;
- wsUrlPreview.textContent = wsUrl;
- } catch (error) {
- wsUrlPreview.textContent = "无效的URL格式";
- }
- } else {
- wsUrlPreview.textContent = "";
- }
- });
-
- // 注册服务器
- btnRegister.onclick = async () => {
- const newConfig = {
- name: document.getElementById("server-name").value,
- http_url: document.getElementById("server-http-url").value,
- };
-
- const workflowHost = document.getElementById(
- "workflow-service-host"
- ).value;
- if (workflowHost) {
- serverManager.setWorkflowServiceHost(workflowHost);
- // 保存到本地设置
- saveLocalSettings({ host: workflowHost });
- }
-
- serverManager.updateConfig(newConfig);
-
- btnRegister.disabled = true;
- btnRegister.textContent = "注册中...";
-
- const result = await serverManager.registerServer();
- if (result.success) {
- statusText.textContent = "已注册";
- statusText.style.color = "var(--success-color)";
- btnRegister.textContent = "已注册";
- btnRegister.disabled = true;
- btnUnregister.disabled = false;
- } else {
- const errorMessage = result.error || "未知错误";
- statusText.textContent = `注册失败: ${errorMessage}`;
- statusText.style.color = "var(--error-color)";
- btnRegister.textContent = "注册服务器";
- btnRegister.disabled = false;
- }
- };
-
- // 注销服务器
- btnUnregister.onclick = async () => {
- btnUnregister.disabled = true;
- btnUnregister.textContent = "注销中...";
-
- const result = await serverManager.unregisterServer();
- if (result.success) {
- statusText.textContent = "已注销";
- statusText.style.color = "orange";
- btnRegister.disabled = false;
- btnRegister.textContent = "注册服务器";
- btnUnregister.disabled = true;
- btnUnregister.textContent = "注销服务器";
- } else {
- const errorMessage = result.error || "未知错误";
- statusText.textContent = `注销失败: ${errorMessage}`;
- statusText.style.color = "var(--error-color)";
- btnUnregister.disabled = false;
- btnUnregister.textContent = "注销服务器";
- }
- };
-
- // 刷新状态
- btnRefreshStatus.onclick = async () => {
- if (settings.host) {
- serverManager.setWorkflowServiceHost(settings.host);
- const status = await serverManager.getServerStatus();
-
- // 调试信息
- console.log("服务器状态:", status);
- if (status && status.last_heartbeat) {
- console.log("最后心跳时间原始值:", status.last_heartbeat);
- console.log("时间类型:", typeof status.last_heartbeat);
- }
-
- if (status) {
- // 安全地处理时间显示
- let heartbeatTime = "未知";
- if (status.last_heartbeat) {
- try {
- // 尝试解析ISO格式的时间字符串
- const date = new Date(status.last_heartbeat);
- if (!isNaN(date.getTime())) {
- heartbeatTime = date.toLocaleString("zh-CN", {
- year: "numeric",
- month: "2-digit",
- day: "2-digit",
- hour: "2-digit",
- minute: "2-digit",
- second: "2-digit",
- });
- } else {
- heartbeatTime = "时间格式错误";
- }
- } catch (error) {
- console.warn(
- "时间解析失败:",
- error,
- "原始时间:",
- status.last_heartbeat
- );
- heartbeatTime = "时间解析失败";
- }
- }
-
- statusText.textContent = `在线 - 最后心跳: ${heartbeatTime}`;
- statusText.style.color = "var(--success-color)";
- // 同步更新本地注册状态
- serverManager.isRegistered = true;
- btnRegister.disabled = true;
- btnRegister.textContent = "已注册";
- btnUnregister.disabled = false;
- } else {
- statusText.textContent = "未注册";
- statusText.style.color = "orange";
- // 同步更新本地注册状态
- serverManager.isRegistered = false;
- btnRegister.disabled = false;
- btnRegister.textContent = "注册服务器";
- btnUnregister.disabled = true;
- }
- }
- };
-
- // 刷新IP地址和端口
- btnRefreshIP.onclick = async () => {
- btnRefreshIP.disabled = true;
- btnRefreshIP.textContent = "刷新中...";
+ // 测试连接
+ btnTestConnection.onclick = async () => {
+ btnTestConnection.disabled = true;
+ btnTestConnection.textContent = "测试中...";
+ statusText.textContent = "正在测试连接...";
+ statusText.style.color = "orange";
try {
- const result = await serverManager.updateLocalIPAddress();
- if (result) {
- // 更新输入框显示
- document.getElementById(
- "server-http-url"
- ).value = `http://${result.ip}:${result.port}`;
- // 更新WebSocket预览
- const wsUrlPreview = document.getElementById("ws-url-preview");
- wsUrlPreview.textContent = `ws://${result.ip}:${result.port}/ws`;
+ const testHost = hostInput.value.trim();
+ if (!testHost) {
+ throw new Error("请输入工作流服务地址");
+ }
- statusText.textContent = `IP地址和端口已更新为: ${result.ip}:${result.port}`;
+ const response = await fetch(`${testHost}/api/workflow`);
+ if (response.ok) {
+ statusText.textContent = "连接成功";
statusText.style.color = "var(--success-color)";
} else {
- statusText.textContent = "IP地址和端口无需更新";
- statusText.style.color = "orange";
- }
- } catch (error) {
- statusText.textContent = `IP地址和端口更新失败: ${error.message}`;
- statusText.style.color = "var(--error-color)";
- } finally {
- btnRefreshIP.disabled = false;
- btnRefreshIP.textContent = "刷新IP和端口";
- }
- };
-
- // 初始状态检查
- if (settings.host) {
- btnRefreshStatus.click();
- } else {
- // 如果没有设置工作流服务地址,确保按钮状态正确
- btnRegister.disabled = false;
- btnUnregister.disabled = true;
- }
-
- // 自动刷新IP地址和端口
- setTimeout(async () => {
- try {
- const result = await serverManager.updateLocalIPAddress();
- if (result) {
- // 更新输入框显示
- document.getElementById(
- "server-http-url"
- ).value = `http://${result.ip}:${result.port}`;
- // 更新WebSocket预览
- const wsUrlPreview = document.getElementById("ws-url-preview");
- wsUrlPreview.textContent = `ws://${result.ip}:${result.port}/ws`;
- console.log(
- "对话框显示时自动更新IP地址和端口:",
- result.ip,
- result.port
+ throw new Error(
+ `HTTP ${response.status}: ${response.statusText}`
);
}
} catch (error) {
- console.warn("自动更新IP地址和端口失败:", error);
+ statusText.textContent = `连接失败: ${error.message}`;
+ statusText.style.color = "var(--error-color)";
+ } finally {
+ btnTestConnection.disabled = false;
+ btnTestConnection.textContent = "测试连接";
}
- }, 500);
+ };
- // 延迟同步按钮状态,确保与内部状态一致
- setTimeout(() => {
- if (serverManager.isRegistered) {
- btnRegister.disabled = true;
- btnRegister.textContent = "已注册";
- btnUnregister.disabled = false;
- } else {
- btnRegister.disabled = false;
- btnRegister.textContent = "注册服务器";
- btnUnregister.disabled = true;
+ // 保存设置
+ btnSaveSettings.onclick = () => {
+ const newHost = hostInput.value.trim();
+ if (!newHost) {
+ alert("请输入工作流服务地址");
+ return;
}
- }, 1000);
+
+ saveWorkflowServiceHost(newHost);
+ statusText.textContent = "设置已保存";
+ statusText.style.color = "var(--success-color)";
+
+ setTimeout(() => {
+ settingsDialog.hide();
+ }, 1000);
+ };
} catch (error) {
- console.error("显示ComfyUI服务器管理对话框失败:", error);
+ console.error("显示设置对话框失败:", error);
alert(`显示对话框失败: ${error.message}`);
}
}
diff --git a/workflow_service/comfy/comfy_server.py b/workflow_service/comfy/comfy_server.py
index 6d060b2..82ff26d 100644
--- a/workflow_service/comfy/comfy_server.py
+++ b/workflow_service/comfy/comfy_server.py
@@ -36,7 +36,6 @@ class ComfyUIServerInfo:
http_url: str
ws_url: str
status: ServerStatus = ServerStatus.OFFLINE
- last_heartbeat: Optional[datetime] = None
last_health_check: Optional[datetime] = None
current_tasks: int = 0
max_concurrent_tasks: int = 1
@@ -60,7 +59,6 @@ class ComfyUIServerInfo:
http_url=model.http_url,
ws_url=model.ws_url,
status=ServerStatus(model.status),
- last_heartbeat=model.last_heartbeat,
last_health_check=model.last_health_check,
current_tasks=model.current_tasks,
max_concurrent_tasks=model.max_concurrent_tasks,
@@ -75,7 +73,6 @@ class ComfyUIServerInfo:
http_url=self.http_url,
ws_url=self.ws_url,
status=self.status.value,
- last_heartbeat=self.last_heartbeat,
last_health_check=self.last_health_check,
current_tasks=self.current_tasks,
max_concurrent_tasks=self.max_concurrent_tasks,
@@ -91,7 +88,6 @@ class ComfyUIServerManager:
self.servers: Dict[str, ComfyUIServerInfo] = {} # name -> server_info
self.lock = asyncio.Lock()
self.health_check_interval = 30 # 健康检查间隔(秒)
- self.heartbeat_timeout = 60 # 心跳超时时间(秒)
self._health_check_task: Optional[asyncio.Task] = None
self._initialized = False
@@ -145,7 +141,6 @@ class ComfyUIServerManager:
http_url=server.http_url,
ws_url=server.ws_url,
status=server.status.value,
- last_heartbeat=server.last_heartbeat,
last_health_check=server.last_health_check,
current_tasks=server.current_tasks,
max_concurrent_tasks=server.max_concurrent_tasks,
@@ -238,7 +233,6 @@ class ComfyUIServerManager:
if await self._check_server_health(server_info):
server_info.status = ServerStatus.ONLINE
server_info.last_health_check = datetime.now()
- server_info.last_heartbeat = datetime.now()
self.servers[name] = server_info
@@ -263,17 +257,6 @@ class ComfyUIServerManager:
return True
return False
- async def update_server_heartbeat(self, name: str) -> bool:
- """更新服务器心跳"""
- async with self.lock:
- if name in self.servers:
- self.servers[name].last_heartbeat = datetime.now()
- self.servers[name].status = ServerStatus.ONLINE
- # 保存到数据库
- await self._save_server_to_db(self.servers[name])
- return True
- return False
-
async def get_available_server(
self, required_capabilities: Optional[Dict[str, any]] = None
) -> Optional[ComfyUIServerInfo]:
@@ -401,17 +384,6 @@ class ComfyUIServerManager:
async with self.lock:
for server in self.servers.values():
- # 检查心跳超时
- if (
- server.last_heartbeat
- and current_time - server.last_heartbeat
- > timedelta(seconds=self.heartbeat_timeout)
- ):
- server.status = ServerStatus.OFFLINE
- logger.warning(f"服务器 {server.name} 心跳超时,标记为离线")
- # 保存到数据库
- await self._save_server_to_db(server)
-
# 定期健康检查
if (
not server.last_health_check
@@ -424,8 +396,7 @@ class ComfyUIServerManager:
if is_healthy and server.status != ServerStatus.ONLINE:
server.status = ServerStatus.ONLINE
- server.last_heartbeat = current_time # 同步更新心跳时间
- logger.info(f"服务器 {server.name} 恢复在线,心跳时间已同步")
+ logger.info(f"服务器 {server.name} 恢复在线")
elif not is_healthy and server.status == ServerStatus.ONLINE:
server.status = ServerStatus.ERROR
logger.warning(f"服务器 {server.name} 健康检查失败")
diff --git a/workflow_service/database/models.py b/workflow_service/database/models.py
index 2665bcb..285d8ea 100644
--- a/workflow_service/database/models.py
+++ b/workflow_service/database/models.py
@@ -120,7 +120,6 @@ class ComfyUIServer(Base):
http_url = Column(String, nullable=False)
ws_url = Column(String, nullable=False)
status = Column(String, nullable=False, default="offline")
- last_heartbeat = Column(DateTime)
last_health_check = Column(DateTime)
current_tasks = Column(Integer, default=0)
max_concurrent_tasks = Column(Integer, default=1)
@@ -135,7 +134,6 @@ class ComfyUIServer(Base):
"http_url": self.http_url,
"ws_url": self.ws_url,
"status": self.status,
- "last_heartbeat": self.last_heartbeat.isoformat() if self.last_heartbeat else None,
"last_health_check": self.last_health_check.isoformat() if self.last_health_check else None,
"current_tasks": self.current_tasks,
"max_concurrent_tasks": self.max_concurrent_tasks,
diff --git a/workflow_service/routes/comfy_server.py b/workflow_service/routes/comfy_server.py
index 2dbfc37..0db7aa1 100644
--- a/workflow_service/routes/comfy_server.py
+++ b/workflow_service/routes/comfy_server.py
@@ -22,12 +22,6 @@ class ServerRegistrationRequest(BaseModel):
ws_url: str
-class ServerHeartbeatRequest(BaseModel):
- """服务器心跳请求模型"""
-
- name: str
-
-
class ServerUnregisterRequest(BaseModel):
"""服务器注销请求模型"""
@@ -41,7 +35,6 @@ class ServerStatusResponse(BaseModel):
http_url: str
ws_url: str
status: str
- last_heartbeat: Optional[str] = None
last_health_check: Optional[str] = None
current_tasks: int
max_concurrent_tasks: int
@@ -74,25 +67,6 @@ async def register_server(request: ServerRegistrationRequest):
raise HTTPException(status_code=500, detail=f"注册失败: {str(e)}")
-@router.post("/heartbeat", response_model=Dict[str, str])
-async def update_heartbeat(request: ServerHeartbeatRequest):
- """更新服务器心跳"""
- try:
- success = await server_manager.update_server_heartbeat(request.name)
-
- if success:
- return {
- "message": f"服务器 {request.name} 心跳更新成功",
- "status": "success",
- }
- else:
- raise HTTPException(status_code=404, detail=f"服务器 {request.name} 不存在")
-
- except Exception as e:
- logger.error(f"更新服务器 {request.name} 心跳时发生错误: {e}")
- raise HTTPException(status_code=500, detail=f"心跳更新失败: {str(e)}")
-
-
@router.post("/unregister", response_model=Dict[str, str])
async def unregister_server(request: ServerUnregisterRequest):
"""注销ComfyUI服务器"""
@@ -124,11 +98,6 @@ async def get_server_status(server_name: str):
http_url=server_info.http_url,
ws_url=server_info.ws_url,
status=server_info.status.value,
- last_heartbeat=(
- server_info.last_heartbeat.isoformat()
- if server_info.last_heartbeat
- else None
- ),
last_health_check=(
server_info.last_health_check.isoformat()
if server_info.last_health_check
@@ -157,9 +126,6 @@ async def list_all_servers():
http_url=server.http_url,
ws_url=server.ws_url,
status=server.status.value,
- last_heartbeat=(
- server.last_heartbeat.isoformat() if server.last_heartbeat else None
- ),
last_health_check=(
server.last_health_check.isoformat()
if server.last_health_check
diff --git a/workflow_service/routes/monitor.py b/workflow_service/routes/monitor.py
index 85cc0b7..eefdcf6 100644
--- a/workflow_service/routes/monitor.py
+++ b/workflow_service/routes/monitor.py
@@ -430,16 +430,16 @@ async def monitor_dashboard():
}
};
- // 格式化心跳时间,突出显示状态
- const formatHeartbeat = (timeStr) => {
+ // 格式化健康检查时间
+ const formatHealthCheck = (timeStr) => {
if (!timeStr) return 'N/A';
try {
const date = new Date(timeStr);
const now = new Date();
const diff = now - date;
- if (diff > 86400000) return '⚠️ 心跳超时'; // 超过1天
- if (diff > 3600000) return '⚠️ 心跳延迟'; // 超过1小时
+ if (diff > 86400000) return '⚠️ 检查超时'; // 超过1天
+ if (diff > 3600000) return '⚠️ 检查延迟'; // 超过1小时
if (diff < 60000) return '✅ 刚刚';
if (diff < 3600000) return `✅ ${Math.floor(diff / 60000)}分钟前`;
return `✅ ${Math.floor(diff / 3600000)}小时前`;
@@ -465,11 +465,7 @@ async def monitor_dashboard():
|
- 心跳: ${formatHeartbeat(server.last_heartbeat)}
-
-
|
-
- 检查: ${formatTime(server.last_health_check)}
+ 检查: ${formatHealthCheck(server.last_health_check)}
${server.error ? `${server.error}
` : ''}
@@ -607,9 +603,6 @@ async def get_server_status() -> List[Dict[str, Any]]:
"max_concurrent_tasks": getattr(
server, "max_concurrent_tasks", 1
),
- "last_heartbeat": getattr(
- server, "last_heartbeat", None
- ),
"last_health_check": getattr(
server, "last_health_check", None
),
@@ -625,9 +618,6 @@ async def get_server_status() -> List[Dict[str, Any]]:
"max_concurrent_tasks": getattr(
server, "max_concurrent_tasks", 1
),
- "last_heartbeat": getattr(
- server, "last_heartbeat", None
- ),
"last_health_check": getattr(
server, "last_health_check", None
),
@@ -641,7 +631,6 @@ async def get_server_status() -> List[Dict[str, Any]]:
"error": str(e),
"current_tasks": getattr(server, "current_tasks", 0),
"max_concurrent_tasks": getattr(server, "max_concurrent_tasks", 1),
- "last_heartbeat": getattr(server, "last_heartbeat", None),
"last_health_check": getattr(server, "last_health_check", None),
}