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:
Towsty
2026-09-02 08:04:11 -05:00
co-authored by Cursor
parent 2ae5f6fb2e
commit bdec8872b6
5 changed files with 99 additions and 36 deletions
+36 -18
View File
@@ -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)