Start waiting image jobs after video, and add Start now on idle queue rows.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+2
-2
@@ -842,12 +842,12 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
v-if="job.status === 'waiting' && canCutInStudioJob"
|
v-if="job.status === 'waiting'"
|
||||||
type="button"
|
type="button"
|
||||||
class="shrink-0 rounded-full border border-sky-300/40 px-2.5 py-1 text-xs text-sky-100 hover:border-sky-200 hover:text-white"
|
class="shrink-0 rounded-full border border-sky-300/40 px-2.5 py-1 text-xs text-sky-100 hover:border-sky-200 hover:text-white"
|
||||||
@click="cutInStudioJob(job.id)"
|
@click="cutInStudioJob(job.id)"
|
||||||
>
|
>
|
||||||
{{ job.cutIn ? 'Next' : 'Run next' }}
|
{{ job.cutIn ? 'Next' : (canCutInStudioJob ? 'Run next' : 'Start now') }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
v-if="job.status === 'waiting' || job.status === 'held'"
|
v-if="job.status === 'waiting' || job.status === 'held'"
|
||||||
|
|||||||
+2
-2
@@ -88,13 +88,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-wrap gap-2">
|
<div class="flex flex-wrap gap-2">
|
||||||
<button
|
<button
|
||||||
v-if="job.status === 'waiting' && canCutIn"
|
v-if="job.status === 'waiting'"
|
||||||
type="button"
|
type="button"
|
||||||
class="rounded-full border border-sky-300/40 px-3 py-1.5 text-xs text-sky-100 hover:border-sky-200 disabled:cursor-not-allowed disabled:opacity-50"
|
class="rounded-full border border-sky-300/40 px-3 py-1.5 text-xs text-sky-100 hover:border-sky-200 disabled:cursor-not-allowed disabled:opacity-50"
|
||||||
:disabled="Boolean(busyId)"
|
:disabled="Boolean(busyId)"
|
||||||
@click="cutIn(job)"
|
@click="cutIn(job)"
|
||||||
>
|
>
|
||||||
{{ job.cutIn ? 'Next after current shot' : 'Run next' }}
|
{{ job.cutIn ? 'Next after current shot' : (canCutIn ? 'Run next' : 'Start now') }}
|
||||||
</button>
|
</button>
|
||||||
<template v-if="job.shots">
|
<template v-if="job.shots">
|
||||||
<template v-if="canProcessShots(job)">
|
<template v-if="canProcessShots(job)">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { listShotQueues, summarizeQueue } from '~/server/utils/shotQueue'
|
import { listShotQueues, summarizeQueue } from '~/server/utils/shotQueue'
|
||||||
import { listStudioJobs, summarizeStudioJob } from '~/server/utils/studioQueue'
|
import { kickStudioQueue, listStudioJobs, summarizeStudioJob } from '~/server/utils/studioQueue'
|
||||||
|
|
||||||
export default defineEventHandler((event) => {
|
export default defineEventHandler((event) => {
|
||||||
const { owner } = assertLibraryOwner(event)
|
const { owner } = assertLibraryOwner(event)
|
||||||
@@ -51,6 +51,7 @@ export default defineEventHandler((event) => {
|
|||||||
.filter(queue => !claimed.has(queue.id) && queue.status !== 'complete')
|
.filter(queue => !claimed.has(queue.id) && queue.status !== 'complete')
|
||||||
.map(summarizeQueue)
|
.map(summarizeQueue)
|
||||||
: []
|
: []
|
||||||
|
if (jobs.some(job => job.status === 'waiting')) void kickStudioQueue()
|
||||||
return {
|
return {
|
||||||
jobs,
|
jobs,
|
||||||
orphans,
|
orphans,
|
||||||
|
|||||||
@@ -423,10 +423,12 @@ export async function requestCutIn(owner: string, id: string) {
|
|||||||
const jobsNow = readJobs(owner)
|
const jobsNow = readJobs(owner)
|
||||||
const running = jobsNow.find(job => job.status === 'running')
|
const running = jobsNow.find(job => job.status === 'running')
|
||||||
|| jobsNow.find(job => job.status === 'held')
|
|| jobsNow.find(job => job.status === 'held')
|
||||||
if (!running) {
|
const target = jobsNow.find(job => job.id === id)
|
||||||
throw createError({ statusCode: 409, statusMessage: 'Nothing is generating, so this job can just wait its turn' })
|
if (!target) throw createError({ statusCode: 404, statusMessage: 'Queued job not found' })
|
||||||
|
if (target.status !== 'waiting') {
|
||||||
|
throw createError({ statusCode: 409, statusMessage: 'Only a waiting job can cut in' })
|
||||||
}
|
}
|
||||||
if (running.id === id) {
|
if (running?.id === id) {
|
||||||
throw createError({ statusCode: 409, statusMessage: 'That job is already running' })
|
throw createError({ statusCode: 409, statusMessage: 'That job is already running' })
|
||||||
}
|
}
|
||||||
const updated = await mutate(owner, (jobs) => {
|
const updated = await mutate(owner, (jobs) => {
|
||||||
@@ -440,7 +442,7 @@ export async function requestCutIn(owner: string, id: string) {
|
|||||||
for (const item of jobs) {
|
for (const item of jobs) {
|
||||||
if (item.id !== id && item.status === 'waiting') item.cutIn = false
|
if (item.id !== id && item.status === 'waiting') item.cutIn = false
|
||||||
}
|
}
|
||||||
const active = jobs.find(item => item.id === running.id)
|
const active = running ? jobs.find(item => item.id === running.id) : undefined
|
||||||
if (active && active.status === 'running') {
|
if (active && active.status === 'running') {
|
||||||
active.holdForCutIn = true
|
active.holdForCutIn = true
|
||||||
active.resumeAutoRun = active.payload.queueAutoRun === true
|
active.resumeAutoRun = active.payload.queueAutoRun === true
|
||||||
@@ -448,14 +450,13 @@ export async function requestCutIn(owner: string, id: string) {
|
|||||||
}
|
}
|
||||||
return structuredClone(job)
|
return structuredClone(job)
|
||||||
})
|
})
|
||||||
const liveId = running.liveJobId
|
if (running?.liveJobId) {
|
||||||
if (liveId) {
|
const live = getJob(running.liveJobId)
|
||||||
const live = getJob(liveId)
|
|
||||||
if (live?.library) {
|
if (live?.library) {
|
||||||
live.library.stopAfterCurrent = true
|
live.library.stopAfterCurrent = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kickStudioQueue()
|
await kickStudioQueue()
|
||||||
return updated
|
return updated
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,6 +534,15 @@ export function kickStudioQueue() {
|
|||||||
return run
|
return run
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let kickRetryTimer: ReturnType<typeof setTimeout> | null = null
|
||||||
|
function scheduleKickRetry() {
|
||||||
|
if (kickRetryTimer) return
|
||||||
|
kickRetryTimer = setTimeout(() => {
|
||||||
|
kickRetryTimer = null
|
||||||
|
kickStudioQueue()
|
||||||
|
}, 2500)
|
||||||
|
}
|
||||||
|
|
||||||
function pendingAlive(job: StudioJob) {
|
function pendingAlive(job: StudioJob) {
|
||||||
if (job.liveJobId && readPendingJob(job.liveJobId)?.promptId) return true
|
if (job.liveJobId && readPendingJob(job.liveJobId)?.promptId) return true
|
||||||
if (!job.shotQueueId) return false
|
if (!job.shotQueueId) return false
|
||||||
@@ -595,7 +605,12 @@ async function dispatchStudioQueue() {
|
|||||||
jobs: current.jobs.map(item => structuredClone(item))
|
jobs: current.jobs.map(item => structuredClone(item))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (await videoJobsBusy()) return
|
if (await videoJobsBusy()) {
|
||||||
|
if (listOwnersWithStudioQueues().some(owner => readJobs(owner).some(job => job.status === 'waiting'))) {
|
||||||
|
scheduleKickRetry()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
const cutIn = pickCutIn(store.jobs)
|
const cutIn = pickCutIn(store.jobs)
|
||||||
if (cutIn) {
|
if (cutIn) {
|
||||||
await startStudioJob(cutIn)
|
await startStudioJob(cutIn)
|
||||||
|
|||||||
Reference in New Issue
Block a user