remove redundant endpoint and warn users when cloudflare tunnel is down
This commit is contained in:
@@ -1582,23 +1582,6 @@ async def check_file_endpoint(request):
|
||||
except Exception as e:
|
||||
return await handle_api_error(request, e, 500)
|
||||
|
||||
@server.PromptServer.instance.routes.get("/distributed/system_info")
|
||||
async def system_info_endpoint(request):
|
||||
"""Return system information including platform details"""
|
||||
import platform
|
||||
|
||||
return web.json_response({
|
||||
"platform": {
|
||||
"os_name": os.name, # 'nt' for Windows, 'posix' for Unix/Linux
|
||||
"path_separator": os.sep, # '\\' on Windows, '/' on Linux
|
||||
"system": platform.system(), # 'Windows', 'Linux', 'Darwin'
|
||||
"machine": platform.machine(), # 'x86_64', 'AMD64', etc.
|
||||
},
|
||||
"comfyui": {
|
||||
# Can add ComfyUI-specific info here
|
||||
"version": "distributed-extension",
|
||||
}
|
||||
})
|
||||
|
||||
@server.PromptServer.instance.routes.post("/distributed/job_complete")
|
||||
async def job_complete_endpoint(request):
|
||||
|
||||
@@ -83,6 +83,38 @@ export async function executeParallelDistributed(extension, promptWrapper) {
|
||||
|
||||
extension.log(`Pre-flight check: ${activeWorkers.length} of ${enabledWorkers.length} workers are active`, "debug");
|
||||
|
||||
// Check if master host might be unreachable by workers (cloudflare tunnel down)
|
||||
const masterHost = extension.config?.master?.host || '';
|
||||
const isCloudflareHost = /\.(trycloudflare\.com|cloudflare\.dev)$/i.test(masterHost);
|
||||
|
||||
if (isCloudflareHost && activeWorkers.length > 0) {
|
||||
// Try to verify if the cloudflare tunnel is actually up
|
||||
try {
|
||||
const testUrl = `${window.location.protocol}//${masterHost}/distributed/status`;
|
||||
const response = await fetch(testUrl, {
|
||||
method: 'GET',
|
||||
mode: 'cors',
|
||||
cache: 'no-cache',
|
||||
signal: AbortSignal.timeout(3000) // 3 second timeout
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Master not reachable');
|
||||
}
|
||||
} catch (error) {
|
||||
// Cloudflare tunnel appears to be down
|
||||
extension.log(`Master host ${masterHost} is not reachable - cloudflare tunnel may be down`, "error");
|
||||
|
||||
if (extension.ui?.showCloudflareWarning) {
|
||||
extension.ui.showCloudflareWarning(extension, masterHost);
|
||||
}
|
||||
|
||||
// Stop execution - workers won't be able to send results back
|
||||
extension.log("Blocking execution - workers cannot reach master at cloudflare domain", "error");
|
||||
return null; // This will prevent the workflow from running
|
||||
}
|
||||
}
|
||||
|
||||
// Find all distributed nodes in the workflow
|
||||
const collectorNodes = findNodesByClass(promptWrapper.output, "DistributedCollector");
|
||||
const upscaleNodes = findNodesByClass(promptWrapper.output, "UltimateSDUpscaleDistributed");
|
||||
|
||||
@@ -344,6 +344,131 @@ export class DistributedUI {
|
||||
}
|
||||
}
|
||||
|
||||
showCloudflareWarning(extension, masterHost) {
|
||||
// Remove any existing banner first
|
||||
const existingBanner = document.getElementById('cloudflare-warning-banner');
|
||||
if (existingBanner) {
|
||||
existingBanner.remove();
|
||||
}
|
||||
|
||||
// Create warning banner
|
||||
const banner = document.createElement('div');
|
||||
banner.id = 'cloudflare-warning-banner';
|
||||
banner.style.cssText = `
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: #ff9800;
|
||||
color: #333;
|
||||
padding: 8px 16px;
|
||||
text-align: center;
|
||||
z-index: 10000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
`;
|
||||
|
||||
const messageSpan = document.createElement('span');
|
||||
messageSpan.innerHTML = `Connection issue: Master address <strong>${masterHost}</strong> is not reachable. The cloudflare tunnel may be offline.`;
|
||||
messageSpan.style.fontSize = '13px';
|
||||
|
||||
const resetButton = document.createElement('button');
|
||||
resetButton.textContent = 'Reset Master Address';
|
||||
resetButton.style.cssText = `
|
||||
background: #333;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 6px 14px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
font-size: 13px;
|
||||
transition: background 0.2s;
|
||||
`;
|
||||
resetButton.onmouseover = () => resetButton.style.background = '#555';
|
||||
resetButton.onmouseout = () => resetButton.style.background = '#333';
|
||||
|
||||
const dismissButton = document.createElement('button');
|
||||
dismissButton.textContent = 'Dismiss';
|
||||
dismissButton.style.cssText = `
|
||||
background: transparent;
|
||||
color: #333;
|
||||
border: 1px solid #333;
|
||||
padding: 6px 14px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
transition: opacity 0.2s;
|
||||
`;
|
||||
dismissButton.onmouseover = () => dismissButton.style.opacity = '0.7';
|
||||
dismissButton.onmouseout = () => dismissButton.style.opacity = '1';
|
||||
|
||||
// Add click handlers
|
||||
resetButton.onclick = async () => {
|
||||
resetButton.disabled = true;
|
||||
resetButton.textContent = 'Resetting...';
|
||||
|
||||
try {
|
||||
// Save with empty host - this will trigger auto-detection
|
||||
await extension.api.updateMaster({
|
||||
name: extension.config?.master?.name || "Master",
|
||||
host: ""
|
||||
});
|
||||
|
||||
// The API call above doesn't trigger auto-detection, so we need to do it
|
||||
await extension.detectMasterIP();
|
||||
|
||||
// Reload config to get the new detected IP
|
||||
await extension.loadConfig();
|
||||
|
||||
// Update UI if sidebar is open
|
||||
if (extension.panelElement) {
|
||||
const hostInput = document.getElementById('master-host');
|
||||
if (hostInput) {
|
||||
hostInput.value = extension.config?.master?.host || "";
|
||||
}
|
||||
}
|
||||
|
||||
// Show success message
|
||||
extension.app.extensionManager.toast.add({
|
||||
severity: "success",
|
||||
summary: "Master Host Reset",
|
||||
detail: `IP auto-detected: ${extension.config?.master?.host || 'detecting...'}`,
|
||||
life: 4000
|
||||
});
|
||||
|
||||
banner.remove();
|
||||
} catch (error) {
|
||||
resetButton.disabled = false;
|
||||
resetButton.textContent = 'Reset Master Host';
|
||||
extension.log(`Failed to reset master host: ${error.message}`, "error");
|
||||
}
|
||||
};
|
||||
|
||||
dismissButton.onclick = () => banner.remove();
|
||||
|
||||
// Assemble banner
|
||||
banner.appendChild(messageSpan);
|
||||
banner.appendChild(resetButton);
|
||||
banner.appendChild(dismissButton);
|
||||
|
||||
// Add to page
|
||||
document.body.prepend(banner);
|
||||
|
||||
// Auto-dismiss after 30 seconds
|
||||
setTimeout(() => {
|
||||
if (document.getElementById('cloudflare-warning-banner')) {
|
||||
banner.style.transition = 'opacity 0.5s';
|
||||
banner.style.opacity = '0';
|
||||
setTimeout(() => banner.remove(), 500);
|
||||
}
|
||||
}, 30000);
|
||||
}
|
||||
|
||||
updateStatusDot(workerId, color, title, pulsing = false) {
|
||||
const statusDot = document.getElementById(`status-${workerId}`);
|
||||
if (!statusDot) return;
|
||||
|
||||
Reference in New Issue
Block a user