Files
aigen/server/api/health.get.ts
T

85 lines
3.9 KiB
TypeScript

import { checkComfyHttp, fetchQueue, fetchComfyControlStatus } from '~/server/utils/comfyLifecycle'
import { comfyConfigured } from '~/server/utils/comfy'
import { imageComfyConfigured, getBeastImageHost, getSidecarImageHost, sameImageHost } from '~/server/utils/imageComfy'
import { checkImageComfyHttp, fetchQueueAt } from '~/server/utils/imageComfyLifecycle'
let healthCache: { at: number; body: Record<string, unknown> } | null = null
const HEALTH_CACHE_MS = 2500
export default defineEventHandler(async () => {
if (healthCache && Date.now() - healthCache.at < HEALTH_CACHE_MS) return healthCache.body
const videoConfigured = comfyConfigured()
const imageConfigured = imageComfyConfigured()
const beastHost = getBeastImageHost()
const promptHost = getSidecarImageHost()
const promptIsBeast = Boolean(promptHost && beastHost && sameImageHost(promptHost, beastHost))
const [comfy, queue, beast, beastQueue, prompt, promptQueue, control] = await Promise.all([
videoConfigured
? checkComfyHttp().catch(() => ({ ok: false, host: '', stats: null }))
: Promise.resolve({ ok: false, host: '', stats: null }),
videoConfigured ? fetchQueue() : Promise.resolve({ running: 0, pending: 0, ok: false }),
beastHost
? checkImageComfyHttp(5000, beastHost).catch(() => ({ ok: false, host: beastHost, stats: null }))
: Promise.resolve({ ok: false, host: beastHost, stats: null }),
beastHost ? fetchQueueAt(beastHost) : Promise.resolve({ running: 0, pending: 0, ok: false }),
promptHost && !promptIsBeast
? checkImageComfyHttp(5000, promptHost).catch(() => ({ ok: false, host: promptHost, stats: null }))
: Promise.resolve({ ok: false, host: promptHost, stats: null }),
promptHost && !promptIsBeast ? fetchQueueAt(promptHost) : Promise.resolve({ running: 0, pending: 0, ok: false }),
fetchComfyControlStatus().catch(() => null)
])
const comfyReachable = Boolean(comfy.ok || queue.ok)
const beastReachable = Boolean(beast.ok || beastQueue.ok || comfyReachable)
const busy = Boolean(comfyReachable && queue.running > 0)
const beastBusy = Boolean(beastReachable && beastQueue.running > 0)
const promptOk = promptIsBeast ? beastReachable : Boolean(prompt.ok || promptQueue.ok)
const promptBusy = promptIsBeast ? (beastBusy || busy) : Boolean(promptOk && promptQueue.running > 0)
const imageOk = Boolean(beastReachable || comfyReachable)
const imageBusy = Boolean(imageConfigured && (beastBusy || busy))
const preferredHost = beastHost || comfy.host || ''
const promptQueueRunning = promptIsBeast ? ((beastQueue.running || queue.running) || 0) : (promptQueue.running || 0)
const promptQueuePending = promptIsBeast ? ((beastQueue.pending || queue.pending) || 0) : (promptQueue.pending || 0)
const body = {
ok: true,
service: useRuntimeConfig().public.instanceName || 'aigen',
comfy: {
ok: comfyReachable,
busy,
host: comfy.host || '',
queueRunning: queue.running,
queuePending: queue.pending,
asleep: Boolean(control?.asleep) && !comfyReachable,
processUp: Boolean(control?.process ?? control?.processUp),
lastActivityAt: control?.lastActivityAt || null,
stats: comfy.ok ? comfy.stats : undefined
},
imageComfy: {
configured: imageConfigured,
ok: imageOk,
busy: imageBusy,
host: preferredHost,
box: imageOk ? 'beast' : '',
queueRunning: (beastQueue.running || queue.running) || 0,
queuePending: (beastQueue.pending || queue.pending) || 0,
beast: {
label: 'Beast',
configured: Boolean(beastHost),
ok: beastReachable,
busy: beastBusy || busy,
host: preferredHost
},
sidecar: {
label: 'Qwen VL',
configured: Boolean(promptHost),
ok: promptOk,
busy: promptBusy,
host: promptHost,
queueRunning: promptQueueRunning,
queuePending: promptQueuePending
}
}
}
healthCache = { at: Date.now(), body }
return body
})