Fix shot auto-run: do not settle or honor stale paused mid-chain, and keep Run remaining from dying after one shot.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1869,8 +1869,9 @@ export async function toggleStudioQueuePause(owner: string, options: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function onStudioQueueBurstStarted(owner: string, queueId: string, liveJobId: string) {
|
export async function onStudioQueueBurstStarted(owner: string, queueId: string, liveJobId: string) {
|
||||||
const { isShotQueueCancelled } = await import('~/server/utils/shotQueue')
|
const { isShotQueueCancelled, getShotQueue } = await import('~/server/utils/shotQueue')
|
||||||
if (isShotQueueCancelled(queueId)) return
|
if (isShotQueueCancelled(queueId)) return
|
||||||
|
const queue = getShotQueue(owner, queueId)
|
||||||
await mutateStore(owner, (store) => {
|
await mutateStore(owner, (store) => {
|
||||||
const row = store.jobs.find(job => job.shotQueueId === queueId)
|
const row = store.jobs.find(job => job.shotQueueId === queueId)
|
||||||
if (!row || row.status === 'cancelled') {
|
if (!row || row.status === 'cancelled') {
|
||||||
@@ -1882,6 +1883,11 @@ export async function onStudioQueueBurstStarted(owner: string, queueId: string,
|
|||||||
row.pauseAfterCurrent = false
|
row.pauseAfterCurrent = false
|
||||||
row.pausedByUser = false
|
row.pausedByUser = false
|
||||||
row.holdForCutIn = false
|
row.holdForCutIn = false
|
||||||
|
// Run remaining / auto-run bursts must resume the rest without another click.
|
||||||
|
if (queue?.autoRun === true) {
|
||||||
|
row.resumeAutoRun = true
|
||||||
|
row.payload.queueAutoRun = true
|
||||||
|
}
|
||||||
row.updatedAt = Date.now()
|
row.updatedAt = Date.now()
|
||||||
syncPausedFlag(store)
|
syncPausedFlag(store)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import {
|
|||||||
isShotQueueCancelled,
|
isShotQueueCancelled,
|
||||||
lastCompletedIndex,
|
lastCompletedIndex,
|
||||||
liveSegmentPrompt,
|
liveSegmentPrompt,
|
||||||
|
pendingSegmentCount,
|
||||||
prepareQueueBurst,
|
prepareQueueBurst,
|
||||||
remainingFromQueue,
|
remainingFromQueue,
|
||||||
setQueueJob,
|
setQueueJob,
|
||||||
@@ -276,7 +277,10 @@ function chainShouldHold(job: Job) {
|
|||||||
? getShotQueue(job.library.ownerKey, job.library.queueId)
|
? getShotQueue(job.library.ownerKey, job.library.queueId)
|
||||||
: null
|
: null
|
||||||
if (job.library.queueId && !queue) return true
|
if (job.library.queueId && !queue) return true
|
||||||
if (queue?.stopAfterCurrent || queue?.status === 'paused') return true
|
if (queue?.stopAfterCurrent) return true
|
||||||
|
// A stale "paused" flag used to abort auto-run mid-batch after finishQueueBurst.
|
||||||
|
// Only honor paused when this live job is not explicitly auto-running.
|
||||||
|
if (queue?.status === 'paused' && job.library.queueAutoRun !== true) return true
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,9 +323,12 @@ export async function continueQueuedExtensions(
|
|||||||
const liveQueue = job.library.queueId
|
const liveQueue = job.library.queueId
|
||||||
? getShotQueue(job.library.ownerKey, job.library.queueId)
|
? getShotQueue(job.library.ownerKey, job.library.queueId)
|
||||||
: null
|
: null
|
||||||
if (liveQueue?.stopAfterCurrent || liveQueue?.autoRun === false) {
|
// User pause / cut-in only. Do not let a stale autoRun=false on disk cancel an
|
||||||
if (liveQueue.stopAfterCurrent) job.library.stopAfterCurrent = true
|
// in-flight "run remaining" / checkbox auto-run batch (options.autoRun).
|
||||||
if (liveQueue.autoRun === false) job.library.queueAutoRun = false
|
if (liveQueue?.stopAfterCurrent) {
|
||||||
|
job.library.stopAfterCurrent = true
|
||||||
|
} else if (liveQueue?.autoRun === false && options.autoRun !== true) {
|
||||||
|
job.library.queueAutoRun = false
|
||||||
}
|
}
|
||||||
if (chainShouldHold(job)) {
|
if (chainShouldHold(job)) {
|
||||||
job.library.stopAfterCurrent = true
|
job.library.stopAfterCurrent = true
|
||||||
@@ -494,12 +501,24 @@ export async function continueQueuedExtensions(
|
|||||||
const paused = job.status !== 'error' && job.status !== 'cancelled'
|
const paused = job.status !== 'error' && job.status !== 'cancelled'
|
||||||
const hold = job.library.stopAfterCurrent === true && paused
|
const hold = job.library.stopAfterCurrent === true && paused
|
||||||
if (hold && job.status === 'running') job.status = 'complete'
|
if (hold && job.status === 'running') job.status = 'complete'
|
||||||
|
// Keep autoRun on the shot queue when this burst was an explicit run-all and more
|
||||||
|
// shots remain — finishQueueBurst used to clear it and force one-click-per-shot.
|
||||||
|
const keepAuto = autoRun && !hold && job.status !== 'error' && job.status !== 'cancelled'
|
||||||
|
if (keepAuto && job.library) job.library.queueAutoRun = true
|
||||||
await finishQueueBurst(
|
await finishQueueBurst(
|
||||||
job.library.ownerKey,
|
job.library.ownerKey,
|
||||||
job.library.queueId,
|
job.library.queueId,
|
||||||
hold || (paused && !job.library.queueAutoRun),
|
hold || (paused && !job.library.queueAutoRun),
|
||||||
job.status === 'error' || job.status === 'cancelled' ? (job.error || 'Stopped') : undefined
|
job.status === 'error' || job.status === 'cancelled' ? (job.error || 'Stopped') : undefined
|
||||||
).catch(() => null)
|
).catch(() => null)
|
||||||
|
if (keepAuto) {
|
||||||
|
await updateShotQueue(job.library.ownerKey, job.library.queueId, (queue) => {
|
||||||
|
if (pendingSegmentCount(queue) > 0 && queue.status !== 'complete' && queue.status !== 'error') {
|
||||||
|
queue.autoRun = true
|
||||||
|
if (queue.status === 'paused') queue.status = 'idle'
|
||||||
|
}
|
||||||
|
}).catch(() => null)
|
||||||
|
}
|
||||||
setQueueJob(job.library.queueId, null)
|
setQueueJob(job.library.queueId, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -363,9 +363,9 @@ export function watchComfyJob(job: Job, options: { persist?: boolean } = {}): Pr
|
|||||||
})
|
})
|
||||||
deletePendingJob(job.id)
|
deletePendingJob(job.id)
|
||||||
job.saving = false
|
job.saving = false
|
||||||
// Persist path: clear the studio "Generating" row as soon as the library save
|
// Only settle the studio row when this live job is done with the chain.
|
||||||
// finishes. Waiting for runGeneration's finally used to leave jobs stuck in the queue.
|
// Settling while chainContinuing killed overnight auto-run after every shot.
|
||||||
if (persist && job.library?.ownerKey) {
|
if (persist && job.library?.ownerKey && !job.library.chainContinuing) {
|
||||||
const { onLiveVideoSettled } = await import('~/server/utils/studioQueue')
|
const { onLiveVideoSettled } = await import('~/server/utils/studioQueue')
|
||||||
await onLiveVideoSettled(job).catch(() => null)
|
await onLiveVideoSettled(job).catch(() => null)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user