Route Coolify through a scanned Comfy proxy instead of pinning hopped listen ports.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -10,7 +10,7 @@ const execFileAsync = promisify(execFile)
|
||||
const port = Number(process.env.COMFY_CONTROL_PORT || 8199)
|
||||
const proxyPort = Number(process.env.COMFY_PROXY_PORT || 8198)
|
||||
const token = process.env.COMFY_CONTROL_TOKEN || ''
|
||||
const defaultHttp = (process.env.COMFY_HOST || 'http://127.0.0.1:8188').replace(/\/$/, '')
|
||||
const defaultHttp = (process.env.COMFY_LISTEN || 'http://127.0.0.1:8188').replace(/\/$/, '')
|
||||
const idleMs = Math.max(60_000, Number(process.env.COMFY_IDLE_MS || 30 * 60 * 1000) || 30 * 60 * 1000)
|
||||
const trainingUrl = String(process.env.TRAINING_CONTROL_URL || 'http://127.0.0.1:8200').replace(/\/$/, '')
|
||||
|
||||
@@ -94,14 +94,20 @@ function candidatePorts() {
|
||||
return ordered
|
||||
}
|
||||
|
||||
async function probeStats(portNum, timeoutMs = 800) {
|
||||
const probeSkipUntil = new Map()
|
||||
|
||||
async function probeStats(portNum, timeoutMs = 400) {
|
||||
if (Date.now() < (probeSkipUntil.get(portNum) || 0)) return null
|
||||
try {
|
||||
const res = await fetch(`http://127.0.0.1:${portNum}/system_stats`, { signal: AbortSignal.timeout(timeoutMs) })
|
||||
if (!res.ok) return null
|
||||
const stats = await res.json()
|
||||
if (!stats?.system) return null
|
||||
probeSkipUntil.delete(portNum)
|
||||
return stats
|
||||
} catch {
|
||||
} catch (error) {
|
||||
const timedOut = error?.name === 'TimeoutError' || error?.name === 'AbortError' || /timeout/i.test(String(error?.message || ''))
|
||||
if (timedOut) probeSkipUntil.set(portNum, Date.now() + 30_000)
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -133,15 +139,15 @@ async function findHealthyPort() {
|
||||
let proxyServer = null
|
||||
let proxyTarget = 0
|
||||
|
||||
function ensureProxy(targetPort) {
|
||||
if (!targetPort) return
|
||||
if (proxyTarget !== targetPort) {
|
||||
proxyTarget = targetPort
|
||||
console.log(JSON.stringify({ src: 'comfy-host-agent', event: 'proxy-target', listen: proxyPort, target: proxyTarget }))
|
||||
}
|
||||
function ensureProxyListening() {
|
||||
if (proxyServer) return
|
||||
proxyServer = net.createServer((client) => {
|
||||
const upstream = net.connect(proxyTarget, '127.0.0.1')
|
||||
const target = proxyTarget
|
||||
if (!target) {
|
||||
client.destroy()
|
||||
return
|
||||
}
|
||||
const upstream = net.connect(target, '127.0.0.1')
|
||||
const fail = () => {
|
||||
try { client.destroy() } catch { /* ignore */ }
|
||||
try { upstream.destroy() } catch { /* ignore */ }
|
||||
@@ -159,26 +165,35 @@ function ensureProxy(targetPort) {
|
||||
console.log(JSON.stringify({ src: 'comfy-host-agent', event: 'proxy-error', error: String(error.message || error) }))
|
||||
})
|
||||
proxyServer.listen(proxyPort, '0.0.0.0', () => {
|
||||
console.log(JSON.stringify({ src: 'comfy-host-agent', event: 'proxy', listen: proxyPort, target: proxyTarget }))
|
||||
console.log(JSON.stringify({ src: 'comfy-host-agent', event: 'proxy', listen: proxyPort, target: proxyTarget || null }))
|
||||
})
|
||||
}
|
||||
|
||||
function setProxyTarget(targetPort) {
|
||||
ensureProxyListening()
|
||||
const next = Number(targetPort) || 0
|
||||
if (proxyTarget === next) return
|
||||
proxyTarget = next
|
||||
console.log(JSON.stringify({ src: 'comfy-host-agent', event: 'proxy-target', listen: proxyPort, target: proxyTarget || null }))
|
||||
}
|
||||
|
||||
function markAsleep() {
|
||||
stoppedByAgent = true
|
||||
lastQueueRunning = 0
|
||||
lastHealthyPort = 0
|
||||
lastProcessUp = false
|
||||
lastLaunchAt = 0
|
||||
proxyTarget = 0
|
||||
setProxyTarget(0)
|
||||
}
|
||||
|
||||
async function syncProxy() {
|
||||
const healthyPort = await findHealthyPort()
|
||||
lastHealthyPort = healthyPort || 0
|
||||
if (healthyPort) {
|
||||
ensureProxy(healthyPort)
|
||||
setProxyTarget(healthyPort)
|
||||
lastProcessUp = true
|
||||
} else {
|
||||
setProxyTarget(0)
|
||||
lastProcessUp = false
|
||||
}
|
||||
return healthyPort
|
||||
@@ -211,7 +226,9 @@ function readJsonFile(path) {
|
||||
function desktopListenPort() {
|
||||
try {
|
||||
const url = new URL(defaultHttp.includes('://') ? defaultHttp : `http://${defaultHttp}`)
|
||||
return Number(url.port || 8188) || 8188
|
||||
const next = Number(url.port || 8188) || 8188
|
||||
if (next === port || next === proxyPort) return 8188
|
||||
return next
|
||||
} catch {
|
||||
return 8188
|
||||
}
|
||||
@@ -641,7 +658,7 @@ const server = http.createServer(async (req, res) => {
|
||||
lastActivityAt: new Date(lastWorkAt).toISOString(),
|
||||
idleMs,
|
||||
port: healthyPort || null,
|
||||
proxyPort: healthyPort ? proxyPort : null,
|
||||
proxyPort,
|
||||
training: lastTraining
|
||||
})
|
||||
}
|
||||
@@ -661,7 +678,7 @@ const server = http.createServer(async (req, res) => {
|
||||
return json(res, 200, { ok: true, started: false, already: true, asleep: false, port: healthyPort, proxyPort })
|
||||
}
|
||||
if (lastLaunchAt && Date.now() - lastLaunchAt < 60_000) {
|
||||
return json(res, 200, { ok: true, started: false, already: true, booting: true, asleep: false })
|
||||
return json(res, 200, { ok: true, started: false, already: true, booting: true, asleep: false, proxyPort })
|
||||
}
|
||||
await taskkillImage('Comfy Desktop.exe')
|
||||
stoppedByAgent = false
|
||||
@@ -669,9 +686,9 @@ const server = http.createServer(async (req, res) => {
|
||||
const launched = await startComfy()
|
||||
if (launched.port) {
|
||||
lastProcessUp = true
|
||||
ensureProxy(launched.port)
|
||||
setProxyTarget(launched.port)
|
||||
}
|
||||
return json(res, 200, { ok: true, asleep: false, ...launched })
|
||||
return json(res, 200, { ok: true, asleep: false, proxyPort, ...launched })
|
||||
}
|
||||
if (req.method === 'POST' && url.pathname === '/stop') {
|
||||
const healthyPort = await syncProxy()
|
||||
@@ -697,6 +714,7 @@ const server = http.createServer(async (req, res) => {
|
||||
})
|
||||
|
||||
server.listen(port, '0.0.0.0', async () => {
|
||||
ensureProxyListening()
|
||||
lastHealthyPort = await syncProxy() || 0
|
||||
lastProcessUp = Boolean(lastHealthyPort) || await processUp().catch(() => false)
|
||||
if (lastHealthyPort) await noteQueue(lastHealthyPort)
|
||||
|
||||
Reference in New Issue
Block a user