diff --git a/browser_tests/fixtures/utils/taskHistory.ts b/browser_tests/fixtures/utils/taskHistory.ts deleted file mode 100644 index 01dfb1a4aa..0000000000 --- a/browser_tests/fixtures/utils/taskHistory.ts +++ /dev/null @@ -1,164 +0,0 @@ -import type { Request, Route } from '@playwright/test' -import _ from 'es-toolkit/compat' -import fs from 'fs' -import path from 'path' -import { v4 as uuidv4 } from 'uuid' - -import type { - HistoryTaskItem, - TaskItem, - TaskOutput -} from '../../../src/schemas/apiSchema' -import type { ComfyPage } from '../ComfyPage' - -/** keyof TaskOutput[string] */ -type OutputFileType = 'images' | 'audio' | 'animated' - -const DEFAULT_IMAGE = 'example.webp' - -const getFilenameParam = (request: Request) => { - const url = new URL(request.url()) - return url.searchParams.get('filename') || DEFAULT_IMAGE -} - -const getContentType = (filename: string, fileType: OutputFileType) => { - const subtype = path.extname(filename).slice(1) - switch (fileType) { - case 'images': - return `image/${subtype}` - case 'audio': - return `audio/${subtype}` - case 'animated': - return `video/${subtype}` - } -} - -const setQueueIndex = (task: TaskItem) => { - task.prompt[0] = TaskHistory.queueIndex++ -} - -const setPromptId = (task: TaskItem) => { - task.prompt[1] = uuidv4() -} - -export default class TaskHistory { - static queueIndex = 0 - static readonly defaultTask: Readonly = { - prompt: [0, 'prompt-id', {}, { client_id: uuidv4() }, []], - outputs: {}, - status: { - status_str: 'success', - completed: true, - messages: [] - }, - taskType: 'History' - } - private tasks: HistoryTaskItem[] = [] - private outputContentTypes: Map = new Map() - - constructor(readonly comfyPage: ComfyPage) {} - - private loadAsset: (filename: string) => Buffer = _.memoize( - (filename: string) => { - const filePath = this.comfyPage.assetPath(filename) - return fs.readFileSync(filePath) - } - ) - - private async handleGetHistory(route: Route) { - return route.fulfill({ - status: 200, - contentType: 'application/json', - body: JSON.stringify(this.tasks) - }) - } - - private async handleGetView(route: Route) { - const fileName = getFilenameParam(route.request()) - if (!this.outputContentTypes.has(fileName)) { - return route.continue() - } - - const asset = this.loadAsset(fileName) - return route.fulfill({ - status: 200, - contentType: this.outputContentTypes.get(fileName), - body: asset, - headers: { - 'Cache-Control': 'public, max-age=31536000', - 'Content-Length': asset.byteLength.toString() - } - }) - } - - async setupRoutes() { - return this.comfyPage.page.route( - /.*\/api\/(view|history)(\?.*)?$/, - async (route) => { - const request = route.request() - const method = request.method() - - const isViewReq = request.url().includes('view') && method === 'GET' - if (isViewReq) return this.handleGetView(route) - - const isHistoryPath = request.url().includes('history') - const isGetHistoryReq = isHistoryPath && method === 'GET' - if (isGetHistoryReq) return this.handleGetHistory(route) - - const isClearReq = - method === 'POST' && - isHistoryPath && - request.postDataJSON()?.clear === true - if (isClearReq) return this.clearTasks() - - return route.continue() - } - ) - } - - private createOutputs( - filenames: string[], - filetype: OutputFileType - ): TaskOutput { - return filenames.reduce((outputs, filename, i) => { - const nodeId = `${i + 1}` - outputs[nodeId] = { - [filetype]: [{ filename, subfolder: '', type: 'output' }] - } - const contentType = getContentType(filename, filetype) - this.outputContentTypes.set(filename, contentType) - return outputs - }, {}) - } - - private addTask(task: HistoryTaskItem) { - setPromptId(task) - setQueueIndex(task) - this.tasks.unshift(task) // Tasks are added to the front of the queue - } - - clearTasks(): this { - this.tasks = [] - return this - } - - withTask( - outputFilenames: string[], - outputFiletype: OutputFileType = 'images', - overrides: Partial = {} - ): this { - this.addTask({ - ...TaskHistory.defaultTask, - outputs: this.createOutputs(outputFilenames, outputFiletype), - ...overrides - }) - return this - } - - /** Repeats the last task in the task history a specified number of times. */ - repeat(n: number): this { - for (let i = 0; i < n; i++) - this.addTask(structuredClone(this.tasks.at(0)) as HistoryTaskItem) - return this - } -} diff --git a/src/components/queue/job/JobDetailsPopover.stories.ts b/src/components/queue/job/JobDetailsPopover.stories.ts index 866b88ddb6..6215977bee 100644 --- a/src/components/queue/job/JobDetailsPopover.stories.ts +++ b/src/components/queue/job/JobDetailsPopover.stories.ts @@ -41,12 +41,16 @@ function makeTask( id: string, priority: number, overrides: Omit, 'id' | 'priority'> & - Pick + Pick ): TaskItemImpl { const job: JobListItem = { id, priority, - last_state_update: null, + execution_start_time: null, + execution_end_time: null, + preview_output: null, + outputs_count: null, + workflow_id: null, ...overrides } return new TaskItemImpl(job) @@ -59,8 +63,7 @@ function makePendingTask( ): TaskItemImpl { return makeTask(id, priority, { status: 'pending', - create_time: createTimeMs, - update_time: createTimeMs + create_time: createTimeMs }) } @@ -71,8 +74,7 @@ function makeRunningTask( ): TaskItemImpl { return makeTask(id, priority, { status: 'in_progress', - create_time: createTimeMs, - update_time: createTimeMs + create_time: createTimeMs }) } @@ -85,7 +87,7 @@ function makeRunningTaskWithStart( return makeTask(id, priority, { status: 'in_progress', create_time: start - 5000, - update_time: start + execution_start_time: start }) } @@ -102,22 +104,21 @@ function makeHistoryTask( return makeTask(id, priority, { status: ok ? 'completed' : 'failed', create_time: executionStartTime - 5000, - update_time: now, execution_start_time: executionStartTime, execution_end_time: executionEndTime, - execution_error: errorMessage - ? { - prompt_id: id, - timestamp: now, - node_id: '1', - node_type: 'ExampleNode', - exception_message: errorMessage, - exception_type: 'RuntimeError', - traceback: [], - current_inputs: {}, - current_outputs: {} - } - : undefined + ...(errorMessage && { + execution_error: { + prompt_id: id, + timestamp: now, + node_id: '1', + node_type: 'ExampleNode', + exception_message: errorMessage, + exception_type: 'RuntimeError', + traceback: [], + current_inputs: {}, + current_outputs: {} + } + }) }) } diff --git a/src/platform/remote/comfyui/jobs/jobTypes.ts b/src/platform/remote/comfyui/jobs/jobTypes.ts index e73ad24718..47aa6ea153 100644 --- a/src/platform/remote/comfyui/jobs/jobTypes.ts +++ b/src/platform/remote/comfyui/jobs/jobTypes.ts @@ -53,12 +53,12 @@ const zRawJobListItem = z id: z.string(), status: zJobStatus, create_time: z.number(), - execution_start_time: z.number().nullable().optional(), - execution_end_time: z.number().nullable().optional(), - preview_output: zPreviewOutput.nullable().optional(), - outputs_count: z.number().nullable().optional(), - execution_error: zExecutionError.nullable().optional(), - workflow_id: z.string().nullable().optional(), + execution_start_time: z.number().nullable(), + execution_end_time: z.number().nullable(), + preview_output: zPreviewOutput.nullable(), + outputs_count: z.number().nullable(), + execution_error: zExecutionError.optional(), + workflow_id: z.string().nullable(), priority: z.number().optional() }) .passthrough() diff --git a/tests-ui/tests/composables/useResultGallery.test.ts b/tests-ui/tests/composables/useResultGallery.test.ts index b68ef4bb03..2cf5ad3b5a 100644 --- a/tests-ui/tests/composables/useResultGallery.test.ts +++ b/tests-ui/tests/composables/useResultGallery.test.ts @@ -26,8 +26,11 @@ const createMockJob = (id: string, outputsCount = 1): JobListItem => ({ id, status: 'completed', create_time: Date.now(), + execution_start_time: null, + execution_end_time: null, preview_output: null, outputs_count: outputsCount, + workflow_id: null, priority: 0 }) diff --git a/tests-ui/tests/platform/remote/comfyui/history/reconciliation.test.ts b/tests-ui/tests/platform/remote/comfyui/history/reconciliation.test.ts index e0eee5fc7c..4365e21e9d 100644 --- a/tests-ui/tests/platform/remote/comfyui/history/reconciliation.test.ts +++ b/tests-ui/tests/platform/remote/comfyui/history/reconciliation.test.ts @@ -11,6 +11,11 @@ function createJob(id: string, createTime = 0, priority?: number): JobListItem { id, status: 'completed', create_time: createTime, + execution_start_time: null, + execution_end_time: null, + preview_output: null, + outputs_count: null, + workflow_id: null, priority: priority ?? createTime } } diff --git a/tests-ui/tests/platform/remote/comfyui/jobs/fetchJobs.test.ts b/tests-ui/tests/platform/remote/comfyui/jobs/fetchJobs.test.ts index f3b2ad5a82..31b29b8281 100644 --- a/tests-ui/tests/platform/remote/comfyui/jobs/fetchJobs.test.ts +++ b/tests-ui/tests/platform/remote/comfyui/jobs/fetchJobs.test.ts @@ -27,6 +27,7 @@ function createMockJob( execution_end_time: null, preview_output: null, outputs_count: 0, + workflow_id: null, ...overrides } } diff --git a/tests-ui/tests/store/assetsStore.test.ts b/tests-ui/tests/store/assetsStore.test.ts index 4f5924f342..8429d12910 100644 --- a/tests-ui/tests/store/assetsStore.test.ts +++ b/tests-ui/tests/store/assetsStore.test.ts @@ -95,14 +95,16 @@ describe('assetsStore - Refactored (Option A)', () => { id: `prompt_${index}`, status: 'completed', create_time: 1000 + index, - update_time: 1000 + index, - last_state_update: 1000 + index, - priority: 1000 + index, + execution_start_time: null, + execution_end_time: null, preview_output: { filename: `output_${index}.png`, subfolder: '', type: 'output' - } + }, + outputs_count: null, + workflow_id: null, + priority: 1000 + index }) beforeEach(() => { diff --git a/tests-ui/tests/store/queueStore.test.ts b/tests-ui/tests/store/queueStore.test.ts index d185a7a59a..402e1a3056 100644 --- a/tests-ui/tests/store/queueStore.test.ts +++ b/tests-ui/tests/store/queueStore.test.ts @@ -17,8 +17,11 @@ function createJob( id, status, create_time: createTime, - update_time: createTime, - last_state_update: createTime, + execution_start_time: null, + execution_end_time: null, + preview_output: null, + outputs_count: null, + workflow_id: null, priority: priority ?? createTime } } diff --git a/tests-ui/tests/stores/queueStore.loadWorkflow.test.ts b/tests-ui/tests/stores/queueStore.loadWorkflow.test.ts index 2b6450b817..2a48320ec7 100644 --- a/tests-ui/tests/stores/queueStore.loadWorkflow.test.ts +++ b/tests-ui/tests/stores/queueStore.loadWorkflow.test.ts @@ -35,7 +35,11 @@ const mockJobDetail = { id: 'test-prompt-id', status: 'completed' as const, create_time: Date.now(), - update_time: Date.now(), + execution_start_time: null, + execution_end_time: null, + preview_output: null, + outputs_count: null, + workflow_id: null, workflow: { extra_data: { extra_pnginfo: { @@ -54,6 +58,11 @@ function createHistoryJob(id: string): JobListItem { id, status: 'completed', create_time: now, + execution_start_time: null, + execution_end_time: null, + preview_output: null, + outputs_count: null, + workflow_id: null, priority: now } } @@ -64,6 +73,11 @@ function createRunningJob(id: string): JobListItem { id, status: 'in_progress', create_time: now, + execution_start_time: null, + execution_end_time: null, + preview_output: null, + outputs_count: null, + workflow_id: null, priority: now } }