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>
|
||||
</div>
|
||||
<button
|
||||
v-if="job.status === 'waiting' && canCutInStudioJob"
|
||||
v-if="job.status === 'waiting'"
|
||||
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"
|
||||
@click="cutInStudioJob(job.id)"
|
||||
>
|
||||
{{ job.cutIn ? 'Next' : 'Run next' }}
|
||||
{{ job.cutIn ? 'Next' : (canCutInStudioJob ? 'Run next' : 'Start now') }}
|
||||
</button>
|
||||
<button
|
||||
v-if="job.status === 'waiting' || job.status === 'held'"
|
||||
|
||||
+2
-2
@@ -88,13 +88,13 @@
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<button
|
||||
v-if="job.status === 'waiting' && canCutIn"
|
||||
v-if="job.status === 'waiting'"
|
||||
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"
|
||||
:disabled="Boolean(busyId)"
|
||||
@click="cutIn(job)"
|
||||
>
|
||||
{{ job.cutIn ? 'Next after current shot' : 'Run next' }}
|
||||
{{ job.cutIn ? 'Next after current shot' : (canCutIn ? 'Run next' : 'Start now') }}
|
||||
</button>
|
||||
<template v-if="job.shots">
|
||||
<template v-if="canProcessShots(job)">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
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) => {
|
||||
const { owner } = assertLibraryOwner(event)
|
||||
@@ -51,6 +51,7 @@ export default defineEventHandler((event) => {
|
||||
.filter(queue => !claimed.has(queue.id) && queue.status !== 'complete')
|
||||
.map(summarizeQueue)
|
||||
: []
|
||||
if (jobs.some(job => job.status === 'waiting')) void kickStudioQueue()
|
||||
return {
|
||||
jobs,
|
||||
orphans,
|
||||
|
||||
@@ -423,10 +423,12 @@ export async function requestCutIn(owner: string, id: string) {
|
||||
const jobsNow = readJobs(owner)
|
||||
const running = jobsNow.find(job => job.status === 'running')
|
||||
|| jobsNow.find(job => job.status === 'held')
|
||||
if (!running) {
|
||||
throw createError({ statusCode: 409, statusMessage: 'Nothing is generating, so this job can just wait its turn' })
|
||||
const target = jobsNow.find(job => job.id === id)
|
||||
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' })
|
||||
}
|
||||
const updated = await mutate(owner, (jobs) => {
|
||||
@@ -440,7 +442,7 @@ export async function requestCutIn(owner: string, id: string) {
|
||||
for (const item of jobs) {
|
||||
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') {
|
||||
active.holdForCutIn = true
|
||||
active.resumeAutoRun = active.payload.queueAutoRun === true
|
||||
@@ -448,14 +450,13 @@ export async function requestCutIn(owner: string, id: string) {
|
||||
}
|
||||
return structuredClone(job)
|
||||
})
|
||||
const liveId = running.liveJobId
|
||||
if (liveId) {
|
||||
const live = getJob(liveId)
|
||||
if (running?.liveJobId) {
|
||||
const live = getJob(running.liveJobId)
|
||||
if (live?.library) {
|
||||
live.library.stopAfterCurrent = true
|
||||
}
|
||||
}
|
||||
kickStudioQueue()
|
||||
await kickStudioQueue()
|
||||
return updated
|
||||
}
|
||||
|
||||
@@ -533,6 +534,15 @@ export function kickStudioQueue() {
|
||||
return run
|
||||
}
|
||||
|
||||
let kickRetryTimer: ReturnType<typeof setTimeout> | null = null
|
||||
function scheduleKickRetry() {
|
||||
if (kickRetryTimer) return
|
||||
kickRetryTimer = setTimeout(() => {
|
||||
kickRetryTimer = null
|
||||
kickStudioQueue()
|
||||
}, 2500)
|
||||
}
|
||||
|
||||
function pendingAlive(job: StudioJob) {
|
||||
if (job.liveJobId && readPendingJob(job.liveJobId)?.promptId) return true
|
||||
if (!job.shotQueueId) return false
|
||||
@@ -595,7 +605,12 @@ async function dispatchStudioQueue() {
|
||||
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)
|
||||
if (cutIn) {
|
||||
await startStudioJob(cutIn)
|
||||
|
||||
Reference in New Issue
Block a user