mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-29 18:52:19 +00:00
[manager] Update composables and state management
Updated manager queue composable, server logs composable, workflow packs composable, and manager store to support the new manager API structure and state management patterns.
This commit is contained in:
@@ -7,7 +7,7 @@ import { app } from '@/scripts/app'
|
|||||||
import { useComfyRegistryStore } from '@/stores/comfyRegistryStore'
|
import { useComfyRegistryStore } from '@/stores/comfyRegistryStore'
|
||||||
import { useNodeDefStore } from '@/stores/nodeDefStore'
|
import { useNodeDefStore } from '@/stores/nodeDefStore'
|
||||||
import { useSystemStatsStore } from '@/stores/systemStatsStore'
|
import { useSystemStatsStore } from '@/stores/systemStatsStore'
|
||||||
import { SelectedVersion, UseNodePacksOptions } from '@/types/comfyManagerTypes'
|
import { UseNodePacksOptions } from '@/types/comfyManagerTypes'
|
||||||
import type { components } from '@/types/comfyRegistryTypes'
|
import type { components } from '@/types/comfyRegistryTypes'
|
||||||
import { collectAllNodes } from '@/utils/graphTraversalUtil'
|
import { collectAllNodes } from '@/utils/graphTraversalUtil'
|
||||||
|
|
||||||
@@ -66,8 +66,7 @@ export const useWorkflowPacks = (options: UseNodePacksOptions = {}) => {
|
|||||||
return {
|
return {
|
||||||
id: CORE_NODES_PACK_NAME,
|
id: CORE_NODES_PACK_NAME,
|
||||||
version:
|
version:
|
||||||
systemStatsStore.systemStats?.system?.comfyui_version ??
|
systemStatsStore.systemStats?.system?.comfyui_version ?? 'nightly'
|
||||||
SelectedVersion.NIGHTLY
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +76,7 @@ export const useWorkflowPacks = (options: UseNodePacksOptions = {}) => {
|
|||||||
if (pack) {
|
if (pack) {
|
||||||
return {
|
return {
|
||||||
id: pack.id,
|
id: pack.id,
|
||||||
version: pack.latest_version?.version ?? SelectedVersion.NIGHTLY
|
version: pack.latest_version?.version ?? 'nightly'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,101 +1,114 @@
|
|||||||
import { useEventListener, whenever } from '@vueuse/core'
|
import { useEventListener, whenever } from '@vueuse/core'
|
||||||
import { computed, readonly, ref } from 'vue'
|
import { Ref, computed, ref } from 'vue'
|
||||||
|
|
||||||
import { api } from '@/scripts/api'
|
import { api } from '@/scripts/api'
|
||||||
import { ManagerWsQueueStatus } from '@/types/comfyManagerTypes'
|
import { useDialogService } from '@/services/dialogService'
|
||||||
|
import { components } from '@/types/generatedManagerTypes'
|
||||||
|
|
||||||
type QueuedTask<T> = {
|
type ManagerTaskHistory = Record<
|
||||||
task: () => Promise<T>
|
string,
|
||||||
onComplete?: () => void
|
components['schemas']['TaskHistoryItem']
|
||||||
}
|
>
|
||||||
|
type ManagerTaskQueue = components['schemas']['TaskStateMessage']
|
||||||
|
type ManagerWsTaskDoneMsg = components['schemas']['MessageTaskDone']
|
||||||
|
type ManagerWsTaskStartedMsg = components['schemas']['MessageTaskStarted']
|
||||||
|
|
||||||
const MANAGER_WS_MSG_TYPE = 'cm-queue-status'
|
const MANAGER_WS_TASK_DONE_NAME = 'cm-task-completed'
|
||||||
|
const MANAGER_WS_TASK_STARTED_NAME = 'cm-task-started'
|
||||||
|
|
||||||
export const useManagerQueue = () => {
|
export const useManagerQueue = (
|
||||||
const clientQueueItems = ref<QueuedTask<unknown>[]>([])
|
taskHistory: Ref<ManagerTaskHistory>,
|
||||||
const clientQueueLength = computed(() => clientQueueItems.value.length)
|
taskQueue: Ref<ManagerTaskQueue>,
|
||||||
const onCompletedQueue = ref<((() => void) | undefined)[]>([])
|
installedPacks: Ref<Record<string, any>>
|
||||||
const onCompleteWaitingCount = ref(0)
|
) => {
|
||||||
const uncompletedCount = computed(
|
const { showManagerProgressDialog } = useDialogService()
|
||||||
() => clientQueueLength.value + onCompleteWaitingCount.value
|
|
||||||
|
// Task queue state (read-only from server)
|
||||||
|
const maxHistoryItems = ref(64)
|
||||||
|
const isLoading = ref(false)
|
||||||
|
const isProcessing = ref(false)
|
||||||
|
|
||||||
|
// Computed values
|
||||||
|
const currentQueueLength = computed(
|
||||||
|
() =>
|
||||||
|
taskQueue.value.running_queue.length +
|
||||||
|
taskQueue.value.pending_queue.length
|
||||||
)
|
)
|
||||||
|
|
||||||
const serverQueueStatus = ref<ManagerWsQueueStatus>(ManagerWsQueueStatus.DONE)
|
const updateProcessingState = () => {
|
||||||
const isServerIdle = computed(
|
isProcessing.value = currentQueueLength.value > 0
|
||||||
() => serverQueueStatus.value === ManagerWsQueueStatus.DONE
|
}
|
||||||
)
|
|
||||||
|
|
||||||
const allTasksDone = computed(
|
const allTasksDone = computed(
|
||||||
() => isServerIdle.value && clientQueueLength.value === 0
|
() => !isProcessing.value && currentQueueLength.value === 0
|
||||||
)
|
|
||||||
const nextTaskReady = computed(
|
|
||||||
() => isServerIdle.value && clientQueueLength.value > 0
|
|
||||||
)
|
)
|
||||||
|
const historyCount = computed(() => Object.keys(taskHistory.value).length)
|
||||||
|
|
||||||
const cleanupListener = useEventListener(
|
// WebSocket event listener for task done
|
||||||
|
const cleanupTaskDoneListener = useEventListener(
|
||||||
api,
|
api,
|
||||||
MANAGER_WS_MSG_TYPE,
|
MANAGER_WS_TASK_DONE_NAME,
|
||||||
(event: CustomEvent<{ status: ManagerWsQueueStatus }>) => {
|
(event: CustomEvent<ManagerWsTaskDoneMsg>) => {
|
||||||
if (event?.type === MANAGER_WS_MSG_TYPE && event.detail?.status) {
|
if (event?.type === MANAGER_WS_TASK_DONE_NAME) {
|
||||||
serverQueueStatus.value = event.detail.status
|
const { state } = event.detail
|
||||||
|
taskQueue.value.running_queue = state.running_queue
|
||||||
|
taskQueue.value.pending_queue = state.pending_queue
|
||||||
|
taskHistory.value = state.history
|
||||||
|
if (state.installed_packs) {
|
||||||
|
console.log(
|
||||||
|
'Updating installedPacks from WebSocket:',
|
||||||
|
Object.keys(state.installed_packs)
|
||||||
|
)
|
||||||
|
installedPacks.value = state.installed_packs
|
||||||
|
}
|
||||||
|
updateProcessingState()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const startNextTask = () => {
|
// WebSocket event listener for task started
|
||||||
const nextTask = clientQueueItems.value.shift()
|
const cleanupTaskStartedListener = useEventListener(
|
||||||
if (!nextTask) return
|
api,
|
||||||
|
MANAGER_WS_TASK_STARTED_NAME,
|
||||||
const { task, onComplete } = nextTask
|
(event: CustomEvent<ManagerWsTaskStartedMsg>) => {
|
||||||
if (onComplete) {
|
if (event?.type === MANAGER_WS_TASK_STARTED_NAME) {
|
||||||
// Set the task's onComplete to be executed the next time the server is idle
|
const { state } = event.detail
|
||||||
onCompletedQueue.value.push(onComplete)
|
taskQueue.value.running_queue = state.running_queue
|
||||||
onCompleteWaitingCount.value++
|
taskQueue.value.pending_queue = state.pending_queue
|
||||||
}
|
taskHistory.value = state.history
|
||||||
|
if (state.installed_packs) {
|
||||||
task().catch((e) => {
|
console.log(
|
||||||
const message = `Error enqueuing task for ComfyUI Manager: ${e}`
|
'Updating installedPacks from WebSocket:',
|
||||||
console.error(message)
|
Object.keys(state.installed_packs)
|
||||||
})
|
)
|
||||||
}
|
installedPacks.value = state.installed_packs
|
||||||
|
}
|
||||||
const enqueueTask = <T>(task: QueuedTask<T>): void => {
|
updateProcessingState()
|
||||||
clientQueueItems.value.push(task)
|
|
||||||
}
|
|
||||||
|
|
||||||
const clearQueue = () => {
|
|
||||||
clientQueueItems.value = []
|
|
||||||
onCompletedQueue.value = []
|
|
||||||
onCompleteWaitingCount.value = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
const cleanup = () => {
|
|
||||||
clearQueue()
|
|
||||||
cleanupListener()
|
|
||||||
}
|
|
||||||
|
|
||||||
whenever(nextTaskReady, startNextTask)
|
|
||||||
whenever(isServerIdle, () => {
|
|
||||||
if (onCompletedQueue.value?.length) {
|
|
||||||
while (
|
|
||||||
onCompleteWaitingCount.value > 0 &&
|
|
||||||
onCompletedQueue.value.length > 0
|
|
||||||
) {
|
|
||||||
const onComplete = onCompletedQueue.value.shift()
|
|
||||||
onComplete?.()
|
|
||||||
onCompleteWaitingCount.value--
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
|
|
||||||
|
whenever(currentQueueLength, () => showManagerProgressDialog())
|
||||||
|
|
||||||
|
const stopListening = () => {
|
||||||
|
cleanupTaskDoneListener()
|
||||||
|
cleanupTaskStartedListener()
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
allTasksDone,
|
// Queue state (read-only from server)
|
||||||
statusMessage: readonly(serverQueueStatus),
|
taskHistory,
|
||||||
queueLength: clientQueueLength,
|
taskQueue,
|
||||||
uncompletedCount,
|
maxHistoryItems,
|
||||||
|
isLoading,
|
||||||
|
|
||||||
enqueueTask,
|
// Computed state
|
||||||
clearQueue,
|
allTasksDone,
|
||||||
cleanup
|
isProcessing,
|
||||||
|
queueLength: currentQueueLength,
|
||||||
|
historyCount,
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
stopListening
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,30 @@
|
|||||||
import { useEventListener } from '@vueuse/core'
|
import { useEventListener } from '@vueuse/core'
|
||||||
import { onUnmounted, ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
import { LogsWsMessage } from '@/schemas/apiSchema'
|
import { LogsWsMessage } from '@/schemas/apiSchema'
|
||||||
import { api } from '@/scripts/api'
|
import { api } from '@/scripts/api'
|
||||||
|
import { components } from '@/types/generatedManagerTypes'
|
||||||
|
|
||||||
const LOGS_MESSAGE_TYPE = 'logs'
|
const LOGS_MESSAGE_TYPE = 'logs'
|
||||||
|
const MANAGER_WS_TASK_DONE_NAME = 'cm-task-completed'
|
||||||
|
|
||||||
|
type ManagerWsTaskDoneMsg = components['schemas']['MessageTaskDone']
|
||||||
|
|
||||||
interface UseServerLogsOptions {
|
interface UseServerLogsOptions {
|
||||||
|
ui_id: string
|
||||||
immediate?: boolean
|
immediate?: boolean
|
||||||
messageFilter?: (message: string) => boolean
|
messageFilter?: (message: string) => boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useServerLogs = (options: UseServerLogsOptions = {}) => {
|
export const useServerLogs = (options: UseServerLogsOptions) => {
|
||||||
const {
|
const {
|
||||||
immediate = false,
|
immediate = false,
|
||||||
messageFilter = (msg: string) => Boolean(msg.trim())
|
messageFilter = (msg: string) => Boolean(msg.trim())
|
||||||
} = options
|
} = options
|
||||||
|
|
||||||
const logs = ref<string[]>([])
|
const logs = ref<string[]>([])
|
||||||
let stop: ReturnType<typeof useEventListener> | null = null
|
let stopLogs: ReturnType<typeof useEventListener> | null = null
|
||||||
|
let stopTaskDone: ReturnType<typeof useEventListener> | null = null
|
||||||
|
|
||||||
const isValidLogEvent = (event: CustomEvent<LogsWsMessage>) =>
|
const isValidLogEvent = (event: CustomEvent<LogsWsMessage>) =>
|
||||||
event?.type === LOGS_MESSAGE_TYPE && event.detail?.entries?.length > 0
|
event?.type === LOGS_MESSAGE_TYPE && event.detail?.entries?.length > 0
|
||||||
@@ -28,33 +34,55 @@ export const useServerLogs = (options: UseServerLogsOptions = {}) => {
|
|||||||
|
|
||||||
const handleLogMessage = (event: CustomEvent<LogsWsMessage>) => {
|
const handleLogMessage = (event: CustomEvent<LogsWsMessage>) => {
|
||||||
if (isValidLogEvent(event)) {
|
if (isValidLogEvent(event)) {
|
||||||
logs.value.push(...parseLogMessage(event))
|
const messages = parseLogMessage(event)
|
||||||
|
if (messages.length > 0) {
|
||||||
|
logs.value.push(...messages)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const start = async () => {
|
const handleTaskDone = (event: CustomEvent<ManagerWsTaskDoneMsg>) => {
|
||||||
|
if (event?.type === MANAGER_WS_TASK_DONE_NAME) {
|
||||||
|
const { state } = event.detail
|
||||||
|
// Check if our task is now in the history (completed)
|
||||||
|
if (state.history[options.ui_id]) {
|
||||||
|
void stopListening()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const startListening = async () => {
|
||||||
await api.subscribeLogs(true)
|
await api.subscribeLogs(true)
|
||||||
stop = useEventListener(api, LOGS_MESSAGE_TYPE, handleLogMessage)
|
stopLogs = useEventListener(api, LOGS_MESSAGE_TYPE, handleLogMessage)
|
||||||
|
stopTaskDone = useEventListener(
|
||||||
|
api,
|
||||||
|
MANAGER_WS_TASK_DONE_NAME,
|
||||||
|
handleTaskDone
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const stopListening = async () => {
|
const stopListening = async () => {
|
||||||
stop?.()
|
console.log('stopListening')
|
||||||
stop = null
|
stopLogs?.()
|
||||||
|
stopTaskDone?.()
|
||||||
|
stopLogs = null
|
||||||
|
stopTaskDone = null
|
||||||
await api.subscribeLogs(false)
|
await api.subscribeLogs(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (immediate) {
|
if (immediate) {
|
||||||
void start()
|
void startListening()
|
||||||
}
|
}
|
||||||
|
|
||||||
onUnmounted(async () => {
|
const cleanup = async () => {
|
||||||
await stopListening()
|
await stopListening()
|
||||||
logs.value = []
|
logs.value = []
|
||||||
})
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
logs,
|
logs,
|
||||||
startListening: start,
|
startListening,
|
||||||
stopListening
|
stopListening,
|
||||||
|
cleanup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,28 @@
|
|||||||
import { whenever } from '@vueuse/core'
|
import { whenever } from '@vueuse/core'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import { useCachedRequest } from '@/composables/useCachedRequest'
|
import { useCachedRequest } from '@/composables/useCachedRequest'
|
||||||
import { useManagerQueue } from '@/composables/useManagerQueue'
|
import { useManagerQueue } from '@/composables/useManagerQueue'
|
||||||
import { useServerLogs } from '@/composables/useServerLogs'
|
import { useServerLogs } from '@/composables/useServerLogs'
|
||||||
|
import { api } from '@/scripts/api'
|
||||||
import { useComfyManagerService } from '@/services/comfyManagerService'
|
import { useComfyManagerService } from '@/services/comfyManagerService'
|
||||||
import { useDialogService } from '@/services/dialogService'
|
import { useDialogService } from '@/services/dialogService'
|
||||||
import {
|
import { TaskLog } from '@/types/comfyManagerTypes'
|
||||||
InstallPackParams,
|
import { components } from '@/types/generatedManagerTypes'
|
||||||
InstalledPacksResponse,
|
|
||||||
ManagerPackInfo,
|
type InstallPackParams = components['schemas']['InstallPackParams']
|
||||||
ManagerPackInstalled,
|
type InstalledPacksResponse = components['schemas']['InstalledPacksResponse']
|
||||||
TaskLog,
|
type ManagerPackInfo = components['schemas']['ManagerPackInfo']
|
||||||
UpdateAllPacksParams
|
type ManagerPackInstalled = components['schemas']['ManagerPackInstalled']
|
||||||
} from '@/types/comfyManagerTypes'
|
type ManagerTaskHistory = Record<
|
||||||
|
string,
|
||||||
|
components['schemas']['TaskHistoryItem']
|
||||||
|
>
|
||||||
|
type ManagerTaskQueue = components['schemas']['TaskStateMessage']
|
||||||
|
type UpdateAllPacksParams = components['schemas']['UpdateAllPacksParams']
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store for state of installed node packs
|
* Store for state of installed node packs
|
||||||
@@ -31,14 +38,63 @@ export const useComfyManagerStore = defineStore('comfyManager', () => {
|
|||||||
const installedPacksIds = ref<Set<string>>(new Set())
|
const installedPacksIds = ref<Set<string>>(new Set())
|
||||||
const isStale = ref(true)
|
const isStale = ref(true)
|
||||||
const taskLogs = ref<TaskLog[]>([])
|
const taskLogs = ref<TaskLog[]>([])
|
||||||
|
const succeededTasksLogs = ref<TaskLog[]>([])
|
||||||
|
const failedTasksLogs = ref<TaskLog[]>([])
|
||||||
|
|
||||||
const { statusMessage, allTasksDone, enqueueTask, uncompletedCount } =
|
const taskHistory = ref<ManagerTaskHistory>({})
|
||||||
useManagerQueue()
|
const succeededTasksIds = ref<string[]>([])
|
||||||
|
const failedTasksIds = ref<string[]>([])
|
||||||
|
const taskQueue = ref<ManagerTaskQueue>({
|
||||||
|
history: {},
|
||||||
|
running_queue: [],
|
||||||
|
pending_queue: [],
|
||||||
|
installed_packs: {}
|
||||||
|
})
|
||||||
|
|
||||||
|
const managerQueue = useManagerQueue(taskHistory, taskQueue, installedPacks)
|
||||||
|
|
||||||
const setStale = () => {
|
const setStale = () => {
|
||||||
isStale.value = true
|
isStale.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const partitionTaskLogs = () => {
|
||||||
|
const successTaskLogs: TaskLog[] = []
|
||||||
|
const failTaskLogs: TaskLog[] = []
|
||||||
|
for (const log of taskLogs.value) {
|
||||||
|
if (failedTasksIds.value.includes(log.taskId)) {
|
||||||
|
failTaskLogs.push(log)
|
||||||
|
} else {
|
||||||
|
successTaskLogs.push(log)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
succeededTasksLogs.value = successTaskLogs
|
||||||
|
failedTasksLogs.value = failTaskLogs
|
||||||
|
}
|
||||||
|
|
||||||
|
const partitionTasks = () => {
|
||||||
|
const successTasksIds = []
|
||||||
|
const failTasksIds = []
|
||||||
|
for (const task of Object.values(taskHistory.value)) {
|
||||||
|
if (task.status?.status_str === 'success') {
|
||||||
|
successTasksIds.push(task.ui_id)
|
||||||
|
} else {
|
||||||
|
failTasksIds.push(task.ui_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
succeededTasksIds.value = successTasksIds
|
||||||
|
failedTasksIds.value = failTasksIds
|
||||||
|
}
|
||||||
|
|
||||||
|
whenever(
|
||||||
|
taskHistory,
|
||||||
|
() => {
|
||||||
|
partitionTasks()
|
||||||
|
partitionTaskLogs()
|
||||||
|
console.log('installed pack ids', installedPacksIds.value)
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
const getPackId = (pack: ManagerPackInstalled) => pack.cnr_id || pack.aux_id
|
const getPackId = (pack: ManagerPackInstalled) => pack.cnr_id || pack.aux_id
|
||||||
|
|
||||||
const isInstalledPackId = (packName: string | undefined): boolean =>
|
const isInstalledPackId = (packName: string | undefined): boolean =>
|
||||||
@@ -97,11 +153,27 @@ export const useComfyManagerStore = defineStore('comfyManager', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const updateInstalledIds = (packs: ManagerPackInstalled[]) => {
|
const updateInstalledIds = (packs: ManagerPackInstalled[]) => {
|
||||||
installedPacksIds.value = packsToIdSet(packs)
|
const newIds = packsToIdSet(packs)
|
||||||
|
console.log('updateInstalledIds: creating set with:', Array.from(newIds))
|
||||||
|
installedPacksIds.value = newIds
|
||||||
|
console.log(
|
||||||
|
'updateInstalledIds: final installedPacksIds:',
|
||||||
|
Array.from(installedPacksIds.value)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onPacksChanged = () => {
|
const onPacksChanged = () => {
|
||||||
const packs = Object.values(installedPacks.value)
|
const packs = Object.values(installedPacks.value)
|
||||||
|
console.log(
|
||||||
|
'onPacksChanged called with packs:',
|
||||||
|
packs.map((p) => ({
|
||||||
|
key: Object.keys(installedPacks.value).find(
|
||||||
|
(k) => installedPacks.value[k] === p
|
||||||
|
),
|
||||||
|
cnr_id: p.cnr_id,
|
||||||
|
aux_id: p.aux_id
|
||||||
|
}))
|
||||||
|
)
|
||||||
updateDisabledIds(packs)
|
updateDisabledIds(packs)
|
||||||
updateInstalledIds(packs)
|
updateInstalledIds(packs)
|
||||||
}
|
}
|
||||||
@@ -115,23 +187,46 @@ export const useComfyManagerStore = defineStore('comfyManager', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
whenever(isStale, refreshInstalledList, { immediate: true })
|
whenever(isStale, refreshInstalledList, { immediate: true })
|
||||||
whenever(uncompletedCount, () => showManagerProgressDialog())
|
|
||||||
|
|
||||||
const withLogs = (task: () => Promise<null>, taskName: string) => {
|
const enqueueTaskWithLogs = async (
|
||||||
const { startListening, stopListening, logs } = useServerLogs()
|
task: (taskId: string) => Promise<null>,
|
||||||
|
taskName: string
|
||||||
|
) => {
|
||||||
|
const taskId = uuidv4()
|
||||||
|
const { startListening, logs } = useServerLogs({
|
||||||
|
ui_id: taskId
|
||||||
|
})
|
||||||
|
|
||||||
const loggedTask = async () => {
|
try {
|
||||||
taskLogs.value.push({ taskName, logs: logs.value })
|
// Show progress dialog immediately when task is queued
|
||||||
|
showManagerProgressDialog()
|
||||||
|
managerQueue.isProcessing.value = true
|
||||||
|
|
||||||
|
// Prepare logging hook
|
||||||
|
taskLogs.value.push({ taskName, taskId, logs: logs.value })
|
||||||
await startListening()
|
await startListening()
|
||||||
return task()
|
|
||||||
}
|
|
||||||
|
|
||||||
const onComplete = async () => {
|
// Queue the task to the server
|
||||||
await stopListening()
|
await task(taskId)
|
||||||
setStale()
|
} catch (error) {
|
||||||
}
|
// Reset processing state on error
|
||||||
|
managerQueue.isProcessing.value = false
|
||||||
|
|
||||||
return { task: loggedTask, onComplete }
|
// The server has authority over task history in general, but in rare
|
||||||
|
// case of client-side error, we add that to failed tasks from the client side
|
||||||
|
taskHistory.value[taskId] = {
|
||||||
|
ui_id: taskId,
|
||||||
|
client_id: api.clientId || 'unknown',
|
||||||
|
kind: 'error',
|
||||||
|
result: 'failed',
|
||||||
|
status: {
|
||||||
|
status_str: 'error',
|
||||||
|
completed: false,
|
||||||
|
messages: [error instanceof Error ? error.message : String(error)]
|
||||||
|
},
|
||||||
|
timestamp: new Date().toISOString()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const installPack = useCachedRequest<InstallPackParams, void>(
|
const installPack = useCachedRequest<InstallPackParams, void>(
|
||||||
@@ -152,39 +247,62 @@ export const useComfyManagerStore = defineStore('comfyManager', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const task = () => managerService.installPack(params, signal)
|
const task = (taskId: string) =>
|
||||||
enqueueTask(withLogs(task, `${actionDescription} ${params.id}`))
|
managerService.installPack(params, taskId, signal)
|
||||||
|
await enqueueTaskWithLogs(task, `${actionDescription} ${params.id}`)
|
||||||
},
|
},
|
||||||
{ maxSize: 1 }
|
{ maxSize: 1 }
|
||||||
)
|
)
|
||||||
|
|
||||||
const uninstallPack = (params: ManagerPackInfo, signal?: AbortSignal) => {
|
const uninstallPack = async (
|
||||||
|
params: ManagerPackInfo,
|
||||||
|
signal?: AbortSignal
|
||||||
|
) => {
|
||||||
installPack.clear()
|
installPack.clear()
|
||||||
installPack.cancel()
|
installPack.cancel()
|
||||||
const task = () => managerService.uninstallPack(params, signal)
|
const uninstallParams: components['schemas']['UninstallPackParams'] = {
|
||||||
enqueueTask(withLogs(task, t('manager.uninstalling', { id: params.id })))
|
node_name: params.id,
|
||||||
|
is_unknown: false
|
||||||
|
}
|
||||||
|
const task = (taskId: string) =>
|
||||||
|
managerService.uninstallPack(uninstallParams, taskId, signal)
|
||||||
|
await enqueueTaskWithLogs(
|
||||||
|
task,
|
||||||
|
t('manager.uninstalling', { id: params.id })
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatePack = useCachedRequest<ManagerPackInfo, void>(
|
const updatePack = useCachedRequest<ManagerPackInfo, void>(
|
||||||
async (params: ManagerPackInfo, signal?: AbortSignal) => {
|
async (params: ManagerPackInfo, signal?: AbortSignal) => {
|
||||||
updateAllPacks.cancel()
|
updateAllPacks.cancel()
|
||||||
const task = () => managerService.updatePack(params, signal)
|
const updateParams: components['schemas']['UpdatePackParams'] = {
|
||||||
enqueueTask(withLogs(task, t('g.updating', { id: params.id })))
|
node_name: params.id,
|
||||||
|
node_ver: params.version
|
||||||
|
}
|
||||||
|
const task = (taskId: string) =>
|
||||||
|
managerService.updatePack(updateParams, taskId, signal)
|
||||||
|
await enqueueTaskWithLogs(task, t('g.updating', { id: params.id }))
|
||||||
},
|
},
|
||||||
{ maxSize: 1 }
|
{ maxSize: 1 }
|
||||||
)
|
)
|
||||||
|
|
||||||
const updateAllPacks = useCachedRequest<UpdateAllPacksParams, void>(
|
const updateAllPacks = useCachedRequest<UpdateAllPacksParams, void>(
|
||||||
async (params: UpdateAllPacksParams, signal?: AbortSignal) => {
|
async (params: UpdateAllPacksParams, signal?: AbortSignal) => {
|
||||||
const task = () => managerService.updateAllPacks(params, signal)
|
const task = (taskId: string) =>
|
||||||
enqueueTask(withLogs(task, t('manager.updatingAllPacks')))
|
managerService.updateAllPacks(params, taskId, signal)
|
||||||
|
await enqueueTaskWithLogs(task, t('manager.updatingAllPacks'))
|
||||||
},
|
},
|
||||||
{ maxSize: 1 }
|
{ maxSize: 1 }
|
||||||
)
|
)
|
||||||
|
|
||||||
const disablePack = (params: ManagerPackInfo, signal?: AbortSignal) => {
|
const disablePack = async (params: ManagerPackInfo, signal?: AbortSignal) => {
|
||||||
const task = () => managerService.disablePack(params, signal)
|
const disableParams: components['schemas']['DisablePackParams'] = {
|
||||||
enqueueTask(withLogs(task, t('g.disabling', { id: params.id })))
|
node_name: params.id,
|
||||||
|
is_unknown: false
|
||||||
|
}
|
||||||
|
const task = (taskId: string) =>
|
||||||
|
managerService.disablePack(disableParams, taskId, signal)
|
||||||
|
await enqueueTaskWithLogs(task, t('g.disabling', { id: params.id }))
|
||||||
}
|
}
|
||||||
|
|
||||||
const getInstalledPackVersion = (packId: string) => {
|
const getInstalledPackVersion = (packId: string) => {
|
||||||
@@ -200,9 +318,6 @@ export const useComfyManagerStore = defineStore('comfyManager', () => {
|
|||||||
// Manager state
|
// Manager state
|
||||||
isLoading: managerService.isLoading,
|
isLoading: managerService.isLoading,
|
||||||
error: managerService.error,
|
error: managerService.error,
|
||||||
statusMessage,
|
|
||||||
allTasksDone,
|
|
||||||
uncompletedCount,
|
|
||||||
taskLogs,
|
taskLogs,
|
||||||
clearLogs,
|
clearLogs,
|
||||||
setStale,
|
setStale,
|
||||||
@@ -215,6 +330,15 @@ export const useComfyManagerStore = defineStore('comfyManager', () => {
|
|||||||
getInstalledPackVersion,
|
getInstalledPackVersion,
|
||||||
refreshInstalledList,
|
refreshInstalledList,
|
||||||
|
|
||||||
|
// Task queue state and actions
|
||||||
|
taskHistory,
|
||||||
|
isProcessingTasks: managerQueue.isProcessing,
|
||||||
|
succeededTasksIds,
|
||||||
|
failedTasksIds,
|
||||||
|
succeededTasksLogs,
|
||||||
|
failedTasksLogs,
|
||||||
|
managerQueue, // Expose full queue composable for advanced usage
|
||||||
|
|
||||||
// Pack actions
|
// Pack actions
|
||||||
installPack,
|
installPack,
|
||||||
uninstallPack,
|
uninstallPack,
|
||||||
@@ -234,6 +358,15 @@ export const useManagerProgressDialogStore = defineStore(
|
|||||||
'managerProgressDialog',
|
'managerProgressDialog',
|
||||||
() => {
|
() => {
|
||||||
const isExpanded = ref(false)
|
const isExpanded = ref(false)
|
||||||
|
const activeTabIndex = ref(0)
|
||||||
|
|
||||||
|
const setActiveTabIndex = (index: number) => {
|
||||||
|
activeTabIndex.value = index
|
||||||
|
}
|
||||||
|
|
||||||
|
const getActiveTabIndex = () => {
|
||||||
|
return activeTabIndex.value
|
||||||
|
}
|
||||||
|
|
||||||
const toggle = () => {
|
const toggle = () => {
|
||||||
isExpanded.value = !isExpanded.value
|
isExpanded.value = !isExpanded.value
|
||||||
@@ -250,7 +383,9 @@ export const useManagerProgressDialogStore = defineStore(
|
|||||||
isExpanded,
|
isExpanded,
|
||||||
toggle,
|
toggle,
|
||||||
collapse,
|
collapse,
|
||||||
expand
|
expand,
|
||||||
|
setActiveTabIndex,
|
||||||
|
getActiveTabIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user