Add a Sleep GPU button that stops Comfy to free VRAM.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
import { listJobs } from '~/server/utils/jobs'
|
||||
import { listOwnersWithStudioQueues, listStudioJobs } from '~/server/utils/studioQueue'
|
||||
import { requestComfySleep } from '~/server/utils/comfyLifecycle'
|
||||
|
||||
export default defineEventHandler(async () => {
|
||||
const live = listJobs().filter(job => job.status === 'queued' || job.status === 'uploading' || job.status === 'running')
|
||||
if (live.length) {
|
||||
throw createError({
|
||||
statusCode: 409,
|
||||
statusMessage: 'A job is still running. Cancel it first, then sleep the GPU.'
|
||||
})
|
||||
}
|
||||
for (const owner of listOwnersWithStudioQueues()) {
|
||||
if (listStudioJobs(owner).some(job => job.status === 'running')) {
|
||||
throw createError({
|
||||
statusCode: 409,
|
||||
statusMessage: 'A job is still running. Cancel it first, then sleep the GPU.'
|
||||
})
|
||||
}
|
||||
}
|
||||
return await requestComfySleep()
|
||||
})
|
||||
@@ -81,7 +81,7 @@ export async function fetchQueue() {
|
||||
}
|
||||
}
|
||||
|
||||
async function controlRequest(path: string, method = 'GET') {
|
||||
async function controlRequest(path: string, method = 'GET', timeoutMs = 5000) {
|
||||
const { controlUrl, controlToken } = settings()
|
||||
if (!controlUrl) return null
|
||||
try {
|
||||
@@ -91,10 +91,9 @@ async function controlRequest(path: string, method = 'GET') {
|
||||
Accept: 'application/json',
|
||||
...(controlToken ? { Authorization: `Bearer ${controlToken}` } : {})
|
||||
},
|
||||
signal: AbortSignal.timeout(5000)
|
||||
signal: AbortSignal.timeout(timeoutMs)
|
||||
})
|
||||
if (!res.ok) return { ok: false, status: res.status }
|
||||
return await res.json() as {
|
||||
const body = await res.json().catch(() => null) as {
|
||||
ok?: boolean
|
||||
http?: boolean
|
||||
process?: boolean
|
||||
@@ -108,9 +107,23 @@ async function controlRequest(path: string, method = 'GET') {
|
||||
port?: number | null
|
||||
proxyPort?: number | null
|
||||
stopped?: boolean
|
||||
killed?: unknown
|
||||
error?: string
|
||||
running?: number
|
||||
pending?: number
|
||||
status?: number
|
||||
} | null
|
||||
if (!res.ok) {
|
||||
return {
|
||||
ok: false as const,
|
||||
status: res.status,
|
||||
error: body?.error,
|
||||
running: body?.running,
|
||||
pending: body?.pending,
|
||||
killed: body?.killed
|
||||
}
|
||||
}
|
||||
return body || { ok: true }
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
@@ -151,6 +164,43 @@ export async function requestComfyWake() {
|
||||
}
|
||||
}
|
||||
|
||||
export async function requestComfySleep() {
|
||||
const { controlUrl } = settings()
|
||||
if (!controlUrl) {
|
||||
throw createError({
|
||||
statusCode: 503,
|
||||
statusMessage: 'COMFY_CONTROL_URL is not set. The studio cannot poke the Beast host agent.'
|
||||
})
|
||||
}
|
||||
const remote = await controlRequest('/stop', 'POST', 25_000)
|
||||
if (!remote) {
|
||||
throw createError({
|
||||
statusCode: 503,
|
||||
statusMessage: 'Beast host agent is unreachable. Confirm it is running on the desktop.'
|
||||
})
|
||||
}
|
||||
if (remote.status === 409 || remote.error === 'queue-busy') {
|
||||
const running = Number(remote.running || 0)
|
||||
const pending = Number(remote.pending || 0)
|
||||
throw createError({
|
||||
statusCode: 409,
|
||||
statusMessage: `Comfy is still working (${running} running, ${pending} queued). Cancel the job first, then sleep the GPU.`
|
||||
})
|
||||
}
|
||||
if (remote.ok === false) {
|
||||
throw createError({
|
||||
statusCode: Number(remote.status) || 502,
|
||||
statusMessage: 'Beast host agent refused to stop Comfy.'
|
||||
})
|
||||
}
|
||||
return {
|
||||
ok: true,
|
||||
stopped: true,
|
||||
asleep: true,
|
||||
killed: remote.killed ?? null
|
||||
}
|
||||
}
|
||||
|
||||
async function findLocalComfyProcess() {
|
||||
const platform = process.platform
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user