Refuse to start Comfy while AITraining has the GPU.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Towsty
2026-09-01 20:53:52 -05:00
co-authored by Cursor
parent e248eb26d8
commit a705610721
2 changed files with 56 additions and 2 deletions
+38 -1
View File
@@ -12,18 +12,43 @@ 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 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(/\/$/, '')
let lastWorkAt = Date.now()
let lastQueueRunning = 0
let stoppedByAgent = false
let lastHealthyPort = 0
let lastProcessUp = false
let lastTraining = { busy: false, jobId: null, status: null, name: null, message: '' }
function markWork() {
lastWorkAt = Date.now()
stoppedByAgent = false
}
async function trainingLock() {
try {
const res = await fetch(`${trainingUrl}/status`, { signal: AbortSignal.timeout(2500) })
const body = await res.json().catch(() => null)
const job = body?.job
const status = String(job?.status || '')
const busy = Boolean(job && ['preparing', 'queued', 'running', 'stopping'].includes(status))
lastTraining = {
busy,
jobId: job?.id || null,
status: busy ? status : null,
name: busy ? (job?.outputName || null) : null,
message: busy
? `AITraining is ${status}${job?.outputName ? ` (${job.outputName})` : ''}. Stop that job before poking Comfy.`
: ''
}
return lastTraining
} catch {
lastTraining = { busy: false, jobId: null, status: null, name: null, message: '' }
return lastTraining
}
}
function json(res, status, body) {
const payload = JSON.stringify(body)
res.writeHead(status, { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) })
@@ -603,10 +628,20 @@ const server = http.createServer(async (req, res) => {
lastActivityAt: new Date(lastWorkAt).toISOString(),
idleMs,
port: healthyPort || null,
proxyPort: healthyPort ? proxyPort : null
proxyPort: healthyPort ? proxyPort : null,
training: lastTraining
})
}
if (req.method === 'POST' && url.pathname === '/start') {
const training = await trainingLock()
if (training.busy) {
return json(res, 409, {
ok: false,
error: 'train-busy',
message: training.message,
training
})
}
const healthyPort = await syncProxy()
if (healthyPort) {
markWork()
@@ -663,6 +698,8 @@ server.listen(port, '0.0.0.0', async () => {
idleMs,
candidates: candidatePorts()
}))
void trainingLock()
setInterval(() => { void trainingLock() }, 3000)
let lastIdleCheck = 0
setInterval(() => {
syncProxy().then(async (nextPort) => {