refactor: rename internal promptId/PromptId to jobId/JobId (#8730)

## Summary

Rename all internal TypeScript usage of legacy `promptId`/`PromptId`
naming to `jobId`/`JobId` across ~38 files for consistency with the
domain model.

## Changes

- **What**: Renamed internal variable names, type aliases, function
names, class getters, interface fields, and comments from
`promptId`/`PromptId` to `jobId`/`JobId`. Wire-protocol field names
(`prompt_id` in Zod schemas and `e.detail.prompt_id` accesses) are
intentionally preserved since they match the backend API contract.

## Review Focus

- All changes are pure renames with no behavioral changes
- Wire-protocol fields (`prompt_id`) are deliberately unchanged to
maintain backend compatibility
- Test fixtures updated to use consistent `job-id` naming

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8730-refactor-rename-internal-promptId-PromptId-to-jobId-JobId-3016d73d3650813ca40ce337f7c5271a)
by [Unito](https://www.unito.io)
This commit is contained in:
Christian Byrne
2026-02-20 02:10:53 -08:00
committed by GitHub
parent 541ad387b9
commit 473713cf02
39 changed files with 455 additions and 402 deletions

View File

@@ -6,10 +6,11 @@ import type { Ref } from 'vue'
import { useJobList } from '@/composables/queue/useJobList'
import type { JobState } from '@/types/queue'
import type { BuildJobDisplayCtx } from '@/utils/queueDisplay'
import { buildJobDisplay } from '@/utils/queueDisplay'
import type { TaskItemImpl } from '@/stores/queueStore'
type TestTask = {
promptId: string
jobId: string
queueIndex: number
mockState: JobState
executionTime?: number
@@ -69,7 +70,7 @@ vi.mock('@/composables/queue/useQueueProgress', () => ({
vi.mock('@/utils/queueDisplay', () => ({
buildJobDisplay: vi.fn(
(task: TaskItemImpl, state: JobState, options: BuildJobDisplayCtx) => ({
primary: `Job ${task.promptId}`,
primary: `Job ${task.jobId}`,
secondary: `${state} meta`,
iconName: `${state}-icon`,
iconImageUrl: undefined,
@@ -108,21 +109,21 @@ vi.mock('@/stores/queueStore', () => ({
}))
let executionStoreMock: {
activePromptId: string | null
activeJobId: string | null
executingNode: null | { title?: string; type?: string }
isPromptInitializing: (promptId?: string | number) => boolean
isJobInitializing: (jobId?: string | number) => boolean
}
let isPromptInitializingMock: (promptId?: string | number) => boolean
let isJobInitializingMock: (jobId?: string | number) => boolean
const ensureExecutionStore = () => {
if (!isPromptInitializingMock) {
isPromptInitializingMock = vi.fn(() => false)
if (!isJobInitializingMock) {
isJobInitializingMock = vi.fn(() => false)
}
if (!executionStoreMock) {
executionStoreMock = reactive({
activePromptId: null as string | null,
activeJobId: null as string | null,
executingNode: null as null | { title?: string; type?: string },
isPromptInitializing: (promptId?: string | number) =>
isPromptInitializingMock(promptId)
isJobInitializing: (jobId?: string | number) =>
isJobInitializingMock(jobId)
})
}
return executionStoreMock
@@ -172,8 +173,7 @@ vi.mock('@/platform/workflow/management/stores/workflowStore', () => ({
const createTask = (
overrides: Partial<TestTask> & { mockState?: JobState } = {}
): TestTask => ({
promptId:
overrides.promptId ?? `task-${Math.random().toString(36).slice(2, 7)}`,
jobId: overrides.jobId ?? `task-${Math.random().toString(36).slice(2, 7)}`,
queueIndex: overrides.queueIndex ?? 0,
mockState: overrides.mockState ?? 'pending',
executionTime: overrides.executionTime,
@@ -201,7 +201,7 @@ const resetStores = () => {
queueStore.historyTasks = []
const executionStore = ensureExecutionStore()
executionStore.activePromptId = null
executionStore.activeJobId = null
executionStore.executingNode = null
const jobPreviewStore = ensureJobPreviewStore()
@@ -219,9 +219,9 @@ const resetStores = () => {
localeRef.value = 'en-US'
tMock.mockClear()
if (isPromptInitializingMock) {
vi.mocked(isPromptInitializingMock).mockReset()
vi.mocked(isPromptInitializingMock).mockReturnValue(false)
if (isJobInitializingMock) {
vi.mocked(isJobInitializingMock).mockReset()
vi.mocked(isJobInitializingMock).mockReturnValue(false)
}
}
@@ -255,10 +255,82 @@ describe('useJobList', () => {
return api!
}
it('tracks recently added pending jobs and clears the hint after expiry', async () => {
vi.useFakeTimers()
queueStoreMock.pendingTasks = [
createTask({ jobId: '1', queueIndex: 1, mockState: 'pending' })
]
const { jobItems } = initComposable()
await flush()
jobItems.value
expect(buildJobDisplay).toHaveBeenCalledWith(
expect.anything(),
'pending',
expect.objectContaining({ showAddedHint: true })
)
vi.mocked(buildJobDisplay).mockClear()
await vi.advanceTimersByTimeAsync(3000)
await flush()
jobItems.value
expect(buildJobDisplay).toHaveBeenCalledWith(
expect.anything(),
'pending',
expect.objectContaining({ showAddedHint: false })
)
})
it('removes pending hint immediately when the task leaves the queue', async () => {
vi.useFakeTimers()
const taskId = '2'
queueStoreMock.pendingTasks = [
createTask({ jobId: taskId, queueIndex: 1, mockState: 'pending' })
]
const { jobItems } = initComposable()
await flush()
jobItems.value
queueStoreMock.pendingTasks = []
await flush()
expect(vi.getTimerCount()).toBe(0)
vi.mocked(buildJobDisplay).mockClear()
queueStoreMock.pendingTasks = [
createTask({ jobId: taskId, queueIndex: 2, mockState: 'pending' })
]
await flush()
jobItems.value
expect(buildJobDisplay).toHaveBeenCalledWith(
expect.anything(),
'pending',
expect.objectContaining({ showAddedHint: true })
)
})
it('cleans up timeouts on unmount', async () => {
vi.useFakeTimers()
queueStoreMock.pendingTasks = [
createTask({ jobId: '3', queueIndex: 1, mockState: 'pending' })
]
initComposable()
await flush()
expect(vi.getTimerCount()).toBeGreaterThan(0)
wrapper?.unmount()
wrapper = null
await flush()
expect(vi.getTimerCount()).toBe(0)
})
it('sorts all tasks by create time', async () => {
queueStoreMock.pendingTasks = [
createTask({
promptId: 'p',
jobId: 'p',
queueIndex: 1,
mockState: 'pending',
createTime: 3000
@@ -266,7 +338,7 @@ describe('useJobList', () => {
]
queueStoreMock.runningTasks = [
createTask({
promptId: 'r',
jobId: 'r',
queueIndex: 5,
mockState: 'running',
createTime: 2000
@@ -274,7 +346,7 @@ describe('useJobList', () => {
]
queueStoreMock.historyTasks = [
createTask({
promptId: 'h',
jobId: 'h',
queueIndex: 3,
mockState: 'completed',
createTime: 1000,
@@ -285,7 +357,7 @@ describe('useJobList', () => {
const { allTasksSorted } = initComposable()
await flush()
expect(allTasksSorted.value.map((task) => task.promptId)).toEqual([
expect(allTasksSorted.value.map((task) => task.jobId)).toEqual([
'p',
'r',
'h'
@@ -294,9 +366,9 @@ describe('useJobList', () => {
it('filters by job tab and resets failed tab when failures disappear', async () => {
queueStoreMock.historyTasks = [
createTask({ promptId: 'c', queueIndex: 3, mockState: 'completed' }),
createTask({ promptId: 'f', queueIndex: 2, mockState: 'failed' }),
createTask({ promptId: 'p', queueIndex: 1, mockState: 'pending' })
createTask({ jobId: 'c', queueIndex: 3, mockState: 'completed' }),
createTask({ jobId: 'f', queueIndex: 2, mockState: 'failed' }),
createTask({ jobId: 'p', queueIndex: 1, mockState: 'pending' })
]
const instance = initComposable()
@@ -304,15 +376,15 @@ describe('useJobList', () => {
instance.selectedJobTab.value = 'Completed'
await flush()
expect(instance.filteredTasks.value.map((t) => t.promptId)).toEqual(['c'])
expect(instance.filteredTasks.value.map((t) => t.jobId)).toEqual(['c'])
instance.selectedJobTab.value = 'Failed'
await flush()
expect(instance.filteredTasks.value.map((t) => t.promptId)).toEqual(['f'])
expect(instance.filteredTasks.value.map((t) => t.jobId)).toEqual(['f'])
expect(instance.hasFailedJobs.value).toBe(true)
queueStoreMock.historyTasks = [
createTask({ promptId: 'c', queueIndex: 3, mockState: 'completed' })
createTask({ jobId: 'c', queueIndex: 3, mockState: 'completed' })
]
await flush()
@@ -323,13 +395,13 @@ describe('useJobList', () => {
it('filters by active workflow when requested', async () => {
queueStoreMock.pendingTasks = [
createTask({
promptId: 'wf-1',
jobId: 'wf-1',
queueIndex: 2,
mockState: 'pending',
workflowId: 'workflow-1'
}),
createTask({
promptId: 'wf-2',
jobId: 'wf-2',
queueIndex: 1,
mockState: 'pending',
workflowId: 'workflow-2'
@@ -346,28 +418,26 @@ describe('useJobList', () => {
workflowStoreMock.activeWorkflow = { activeState: { id: 'workflow-1' } }
await flush()
expect(instance.filteredTasks.value.map((t) => t.promptId)).toEqual([
'wf-1'
])
expect(instance.filteredTasks.value.map((t) => t.jobId)).toEqual(['wf-1'])
})
it('hydrates job items with active progress and compute hours', async () => {
queueStoreMock.runningTasks = [
createTask({
promptId: 'active',
jobId: 'active',
queueIndex: 3,
mockState: 'running',
executionTime: 7_200_000
}),
createTask({
promptId: 'other',
jobId: 'other',
queueIndex: 2,
mockState: 'running',
executionTime: 3_600_000
})
]
executionStoreMock.activePromptId = 'active'
executionStoreMock.activeJobId = 'active'
executionStoreMock.executingNode = { title: 'Render Node' }
totalPercent.value = 80
currentNodePercent.value = 40
@@ -390,7 +460,7 @@ describe('useJobList', () => {
it('assigns preview urls for running jobs when previews enabled', async () => {
queueStoreMock.runningTasks = [
createTask({
promptId: 'live-preview',
jobId: 'live-preview',
queueIndex: 1,
mockState: 'running'
})
@@ -409,7 +479,7 @@ describe('useJobList', () => {
it('omits preview urls when previews are disabled', async () => {
queueStoreMock.runningTasks = [
createTask({
promptId: 'disabled-preview',
jobId: 'disabled-preview',
queueIndex: 1,
mockState: 'running'
})
@@ -450,28 +520,28 @@ describe('useJobList', () => {
vi.setSystemTime(new Date('2024-01-10T12:00:00Z'))
queueStoreMock.historyTasks = [
createTask({
promptId: 'today-small',
jobId: 'today-small',
queueIndex: 4,
mockState: 'completed',
executionEndTimestamp: Date.now(),
executionTime: 2_000
}),
createTask({
promptId: 'today-large',
jobId: 'today-large',
queueIndex: 3,
mockState: 'completed',
executionEndTimestamp: Date.now(),
executionTime: 5_000
}),
createTask({
promptId: 'yesterday',
jobId: 'yesterday',
queueIndex: 2,
mockState: 'failed',
executionEndTimestamp: Date.now() - 86_400_000,
executionTime: 1_000
}),
createTask({
promptId: 'undated',
jobId: 'undated',
queueIndex: 1,
mockState: 'pending'
})

View File

@@ -127,7 +127,7 @@ export function useJobList() {
watch(
() =>
queueStore.pendingTasks
.map((task) => taskIdToKey(task.promptId))
.map((task) => taskIdToKey(task.jobId))
.filter((id): id is string => !!id),
(pendingIds) => {
const pendingSet = new Set(pendingIds)
@@ -158,7 +158,7 @@ export function useJobList() {
const shouldShowAddedHint = (task: TaskItemImpl, state: JobState) => {
if (state !== 'pending') return false
const id = taskIdToKey(task.promptId)
const id = taskIdToKey(task.jobId)
if (!id) return false
return recentlyAddedPendingIds.value.has(id)
}
@@ -183,8 +183,8 @@ export function useJobList() {
})
const undatedLabel = computed(() => t('queue.jobList.undated') || 'Undated')
const isJobInitializing = (promptId: string | number | undefined) =>
executionStore.isPromptInitializing(promptId)
const isJobInitializing = (jobId: string | number | undefined) =>
executionStore.isJobInitializing(jobId)
const currentNodeName = computed(() => {
return resolveNodeDisplayName(executionStore.executingNode, {
@@ -212,7 +212,7 @@ export function useJobList() {
const tasksWithJobState = computed<TaskWithState[]>(() =>
allTasksSorted.value.map((task) => ({
task,
state: jobStateFromTask(task, isJobInitializing(task?.promptId))
state: jobStateFromTask(task, isJobInitializing(task?.jobId))
}))
)
@@ -255,10 +255,9 @@ export function useJobList() {
const jobItems = computed<JobListItem[]>(() => {
return filteredTaskEntries.value.map(({ task, state }) => {
const isActive =
String(task.promptId ?? '') ===
String(executionStore.activePromptId ?? '')
String(task.jobId ?? '') === String(executionStore.activeJobId ?? '')
const showAddedHint = shouldShowAddedHint(task, state)
const promptKey = taskIdToKey(task.promptId)
const promptKey = taskIdToKey(task.jobId)
const promptPreviewUrl =
state === 'running' && jobPreviewStore.isPreviewEnabled && promptKey
? jobPreviewStore.previewsByPromptId[promptKey]
@@ -277,7 +276,7 @@ export function useJobList() {
})
return {
id: String(task.promptId),
id: String(task.jobId),
title: display.primary,
meta: display.secondary,
state,
@@ -334,7 +333,7 @@ export function useJobList() {
groupIdx = groups.length - 1
index.set(key, groupIdx)
}
const ji = jobItemById.value.get(String(task.promptId))
const ji = jobItemById.value.get(String(task.jobId))
if (ji) groups[groupIdx].items.push(ji)
}

View File

@@ -72,8 +72,7 @@ const interruptMock = vi.fn()
const deleteItemMock = vi.fn()
vi.mock('@/scripts/api', () => ({
api: {
interrupt: (runningPromptId: string | null) =>
interruptMock(runningPromptId),
interrupt: (runningJobId: string | null) => interruptMock(runningJobId),
deleteItem: (type: string, id: string) => deleteItemMock(type, id)
}
}))
@@ -120,7 +119,7 @@ vi.mock('@/stores/queueStore', () => ({
}))
const executionStoreMock = {
clearInitializationByPromptId: vi.fn()
clearInitializationByJobId: vi.fn()
}
vi.mock('@/stores/executionStore', () => ({
useExecutionStore: () => executionStoreMock

View File

@@ -84,7 +84,7 @@ export function useJobMenu(
} else if (target.state === 'pending') {
await api.deleteItem('queue', target.id)
}
executionStore.clearInitializationByPromptId(target.id)
executionStore.clearInitializationByJobId(target.id)
await queueStore.update()
}

View File

@@ -17,7 +17,7 @@ const executionStore = reactive<{
executingNode: unknown
executingNodeProgress: number
nodeProgressStates: Record<string, unknown>
activePrompt: {
activeJob: {
workflow: {
changeTracker: {
activeState: {
@@ -32,7 +32,7 @@ const executionStore = reactive<{
executingNode: null,
executingNodeProgress: 0,
nodeProgressStates: {},
activePrompt: null
activeJob: null
})
vi.mock('@/stores/executionStore', () => ({
useExecutionStore: () => executionStore
@@ -76,7 +76,7 @@ describe('useBrowserTabTitle', () => {
executionStore.executingNode = null
executionStore.executingNodeProgress = 0
executionStore.nodeProgressStates = {}
executionStore.activePrompt = null
executionStore.activeJob = null
// reset setting and workflow stores
vi.mocked(settingStore.get).mockReturnValue('Enabled')
@@ -187,7 +187,7 @@ describe('useBrowserTabTitle', () => {
executionStore.nodeProgressStates = {
'1': { state: 'running', value: 5, max: 10, node: '1', prompt_id: 'test' }
}
executionStore.activePrompt = {
executionStore.activeJob = {
workflow: {
changeTracker: {
activeState: {

View File

@@ -77,7 +77,7 @@ export const useBrowserTabTitle = () => {
const [nodeId, state] = runningNodes[0]
const progress = Math.round((state.value / state.max) * 100)
const nodeType =
executionStore.activePrompt?.workflow?.changeTracker?.activeState.nodes.find(
executionStore.activeJob?.workflow?.changeTracker?.activeState.nodes.find(
(n) => String(n.id) === nodeId
)?.type || 'Node'

View File

@@ -312,7 +312,7 @@ export function useCoreCommands(): ComfyCommand[] {
label: 'Interrupt',
category: 'essentials' as const,
function: async () => {
await api.interrupt(executionStore.activePromptId)
await api.interrupt(executionStore.activeJobId)
toastStore.add({
severity: 'info',
summary: t('g.interrupted'),