mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
merge with main
This commit is contained in:
@ -3,7 +3,13 @@
|
||||
from typing import Any, Optional
|
||||
|
||||
from invokeai.app.models.image import ProgressImage
|
||||
from invokeai.app.services.session_queue.session_queue_common import EnqueueBatchResult, SessionQueueItem
|
||||
from invokeai.app.services.model_record_service import BaseModelType, ModelType, SubModelType
|
||||
from invokeai.app.services.session_queue.session_queue_common import (
|
||||
BatchStatus,
|
||||
EnqueueBatchResult,
|
||||
SessionQueueItem,
|
||||
SessionQueueStatus,
|
||||
)
|
||||
from invokeai.app.util.misc import get_timestamp
|
||||
from invokeai.backend.model_manager import SubModelType
|
||||
from invokeai.backend.model_manager.download import DownloadJobBase
|
||||
@ -256,21 +262,31 @@ class EventServiceBase:
|
||||
),
|
||||
)
|
||||
|
||||
def emit_queue_item_status_changed(self, session_queue_item: SessionQueueItem) -> None:
|
||||
def emit_queue_item_status_changed(
|
||||
self,
|
||||
session_queue_item: SessionQueueItem,
|
||||
batch_status: BatchStatus,
|
||||
queue_status: SessionQueueStatus,
|
||||
) -> None:
|
||||
"""Emitted when a queue item's status changes"""
|
||||
self.__emit_queue_event(
|
||||
event_name="queue_item_status_changed",
|
||||
payload=dict(
|
||||
queue_id=session_queue_item.queue_id,
|
||||
queue_item_id=session_queue_item.item_id,
|
||||
status=session_queue_item.status,
|
||||
batch_id=session_queue_item.batch_id,
|
||||
session_id=session_queue_item.session_id,
|
||||
error=session_queue_item.error,
|
||||
created_at=str(session_queue_item.created_at) if session_queue_item.created_at else None,
|
||||
updated_at=str(session_queue_item.updated_at) if session_queue_item.updated_at else None,
|
||||
started_at=str(session_queue_item.started_at) if session_queue_item.started_at else None,
|
||||
completed_at=str(session_queue_item.completed_at) if session_queue_item.completed_at else None,
|
||||
queue_id=queue_status.queue_id,
|
||||
queue_item=dict(
|
||||
queue_id=session_queue_item.queue_id,
|
||||
item_id=session_queue_item.item_id,
|
||||
status=session_queue_item.status,
|
||||
batch_id=session_queue_item.batch_id,
|
||||
session_id=session_queue_item.session_id,
|
||||
error=session_queue_item.error,
|
||||
created_at=str(session_queue_item.created_at) if session_queue_item.created_at else None,
|
||||
updated_at=str(session_queue_item.updated_at) if session_queue_item.updated_at else None,
|
||||
started_at=str(session_queue_item.started_at) if session_queue_item.started_at else None,
|
||||
completed_at=str(session_queue_item.completed_at) if session_queue_item.completed_at else None,
|
||||
),
|
||||
batch_status=batch_status.dict(),
|
||||
queue_status=queue_status.dict(),
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -8,7 +8,7 @@ from abc import abstractmethod
|
||||
from pathlib import Path
|
||||
from typing import Optional, Union
|
||||
|
||||
from invokeai.backend.model_manager import ModelConfigBase, ModelType, SubModelType
|
||||
from invokeai.backend.model_manager import ModelConfigBase, BaseModelType, ModelType, SubModelType
|
||||
|
||||
from invokeai.backend.model_manager.storage import (
|
||||
ModelConfigStore,
|
||||
|
@ -427,7 +427,13 @@ class SqliteSessionQueue(SessionQueueBase):
|
||||
finally:
|
||||
self.__lock.release()
|
||||
queue_item = self.get_queue_item(item_id)
|
||||
self.__invoker.services.events.emit_queue_item_status_changed(queue_item)
|
||||
batch_status = self.get_batch_status(queue_id=queue_item.queue_id, batch_id=queue_item.batch_id)
|
||||
queue_status = self.get_queue_status(queue_id=queue_item.queue_id)
|
||||
self.__invoker.services.events.emit_queue_item_status_changed(
|
||||
session_queue_item=queue_item,
|
||||
batch_status=batch_status,
|
||||
queue_status=queue_status,
|
||||
)
|
||||
return queue_item
|
||||
|
||||
def is_empty(self, queue_id: str) -> IsEmptyResult:
|
||||
@ -609,7 +615,13 @@ class SqliteSessionQueue(SessionQueueBase):
|
||||
queue_batch_id=current_queue_item.batch_id,
|
||||
graph_execution_state_id=current_queue_item.session_id,
|
||||
)
|
||||
self.__invoker.services.events.emit_queue_item_status_changed(current_queue_item)
|
||||
batch_status = self.get_batch_status(queue_id=queue_id, batch_id=current_queue_item.batch_id)
|
||||
queue_status = self.get_queue_status(queue_id=queue_id)
|
||||
self.__invoker.services.events.emit_queue_item_status_changed(
|
||||
session_queue_item=current_queue_item,
|
||||
batch_status=batch_status,
|
||||
queue_status=queue_status,
|
||||
)
|
||||
except Exception:
|
||||
self.__conn.rollback()
|
||||
raise
|
||||
@ -655,7 +667,13 @@ class SqliteSessionQueue(SessionQueueBase):
|
||||
queue_batch_id=current_queue_item.batch_id,
|
||||
graph_execution_state_id=current_queue_item.session_id,
|
||||
)
|
||||
self.__invoker.services.events.emit_queue_item_status_changed(current_queue_item)
|
||||
batch_status = self.get_batch_status(queue_id=queue_id, batch_id=current_queue_item.batch_id)
|
||||
queue_status = self.get_queue_status(queue_id=queue_id)
|
||||
self.__invoker.services.events.emit_queue_item_status_changed(
|
||||
session_queue_item=current_queue_item,
|
||||
batch_status=batch_status,
|
||||
queue_status=queue_status,
|
||||
)
|
||||
except Exception:
|
||||
self.__conn.rollback()
|
||||
raise
|
||||
|
@ -11,44 +11,70 @@ export const addSocketQueueItemStatusChangedEventListener = () => {
|
||||
actionCreator: socketQueueItemStatusChanged,
|
||||
effect: async (action, { dispatch }) => {
|
||||
const log = logger('socketio');
|
||||
const {
|
||||
queue_item_id: item_id,
|
||||
queue_batch_id,
|
||||
status,
|
||||
} = action.payload.data;
|
||||
|
||||
// we've got new status for the queue item, batch and queue
|
||||
const { queue_item, batch_status, queue_status } = action.payload.data;
|
||||
|
||||
log.debug(
|
||||
action.payload,
|
||||
`Queue item ${item_id} status updated: ${status}`
|
||||
`Queue item ${queue_item.item_id} status updated: ${queue_item.status}`
|
||||
);
|
||||
dispatch(appSocketQueueItemStatusChanged(action.payload));
|
||||
|
||||
// Update this specific queue item in the list of queue items (this is the queue item DTO, without the session)
|
||||
dispatch(
|
||||
queueApi.util.updateQueryData('listQueueItems', undefined, (draft) => {
|
||||
queueItemsAdapter.updateOne(draft, {
|
||||
id: item_id,
|
||||
changes: action.payload.data,
|
||||
id: queue_item.item_id,
|
||||
changes: queue_item,
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
// Update the queue status (we do not get the processor status here)
|
||||
dispatch(
|
||||
queueApi.util.updateQueryData('getQueueStatus', undefined, (draft) => {
|
||||
if (!draft) {
|
||||
return;
|
||||
}
|
||||
Object.assign(draft.queue, queue_status);
|
||||
})
|
||||
);
|
||||
|
||||
// Update the batch status
|
||||
dispatch(
|
||||
queueApi.util.updateQueryData(
|
||||
'getBatchStatus',
|
||||
{ batch_id: batch_status.batch_id },
|
||||
() => batch_status
|
||||
)
|
||||
);
|
||||
|
||||
// Update the queue item status (this is the full queue item, including the session)
|
||||
dispatch(
|
||||
queueApi.util.updateQueryData(
|
||||
'getQueueItem',
|
||||
queue_item.item_id,
|
||||
(draft) => {
|
||||
if (!draft) {
|
||||
return;
|
||||
}
|
||||
Object.assign(draft, queue_item);
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Invalidate caches for things we cannot update
|
||||
// TODO: technically, we could possibly update the current session queue item, but feels safer to just request it again
|
||||
dispatch(
|
||||
queueApi.util.invalidateTags([
|
||||
'CurrentSessionQueueItem',
|
||||
'NextSessionQueueItem',
|
||||
'InvocationCacheStatus',
|
||||
{ type: 'SessionQueueItem', id: item_id },
|
||||
{ type: 'SessionQueueItemDTO', id: item_id },
|
||||
{ type: 'BatchStatus', id: queue_batch_id },
|
||||
])
|
||||
);
|
||||
|
||||
const req = dispatch(
|
||||
queueApi.endpoints.getQueueStatus.initiate(undefined, {
|
||||
forceRefetch: true,
|
||||
})
|
||||
);
|
||||
await req.unwrap();
|
||||
req.unsubscribe();
|
||||
// Pass the event along
|
||||
dispatch(appSocketQueueItemStatusChanged(action.payload));
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -29,6 +29,7 @@ import {
|
||||
isCanvasBaseImage,
|
||||
isCanvasMaskLine,
|
||||
} from './canvasTypes';
|
||||
import { appSocketQueueItemStatusChanged } from 'services/events/actions';
|
||||
|
||||
export const initialLayerState: CanvasLayerState = {
|
||||
objects: [],
|
||||
@ -786,6 +787,18 @@ export const canvasSlice = createSlice({
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(appSocketQueueItemStatusChanged, (state, action) => {
|
||||
const batch_status = action.payload.data.batch_status;
|
||||
if (!state.batchIds.includes(batch_status.batch_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (batch_status.in_progress === 0 && batch_status.pending === 0) {
|
||||
state.batchIds = state.batchIds.filter(
|
||||
(id) => id !== batch_status.batch_id
|
||||
);
|
||||
}
|
||||
});
|
||||
builder.addCase(setAspectRatio, (state, action) => {
|
||||
const ratio = action.payload;
|
||||
if (ratio) {
|
||||
|
@ -134,13 +134,7 @@ const CurrentImageButtons = () => {
|
||||
recallAllParameters(metadata);
|
||||
}, [metadata, recallAllParameters]);
|
||||
|
||||
useHotkeys(
|
||||
'a',
|
||||
() => {
|
||||
handleClickUseAllParameters;
|
||||
},
|
||||
[metadata, recallAllParameters]
|
||||
);
|
||||
useHotkeys('a', handleClickUseAllParameters, [metadata]);
|
||||
|
||||
const handleUseSeed = useCallback(() => {
|
||||
recallSeed(metadata?.seed);
|
||||
|
@ -984,7 +984,7 @@ const nodesSlice = createSlice({
|
||||
}
|
||||
});
|
||||
builder.addCase(appSocketQueueItemStatusChanged, (state, action) => {
|
||||
if (['in_progress'].includes(action.payload.data.status)) {
|
||||
if (['in_progress'].includes(action.payload.data.queue_item.status)) {
|
||||
forEach(state.nodeExecutionStates, (nes) => {
|
||||
nes.status = NodeStatus.PENDING;
|
||||
nes.error = null;
|
||||
|
@ -164,7 +164,9 @@ export const systemSlice = createSlice({
|
||||
|
||||
builder.addCase(appSocketQueueItemStatusChanged, (state, action) => {
|
||||
if (
|
||||
['completed', 'canceled', 'failed'].includes(action.payload.data.status)
|
||||
['completed', 'canceled', 'failed'].includes(
|
||||
action.payload.data.queue_item.status
|
||||
)
|
||||
) {
|
||||
state.status = 'CONNECTED';
|
||||
state.denoiseProgress = null;
|
||||
|
@ -135,12 +135,7 @@ export const queueApi = api.injectEndpoints({
|
||||
url: `queue/${$queueId.get()}/prune`,
|
||||
method: 'PUT',
|
||||
}),
|
||||
invalidatesTags: [
|
||||
'SessionQueueStatus',
|
||||
'BatchStatus',
|
||||
'SessionQueueItem',
|
||||
'SessionQueueItemDTO',
|
||||
],
|
||||
invalidatesTags: ['SessionQueueStatus', 'BatchStatus'],
|
||||
onQueryStarted: async (arg, api) => {
|
||||
const { dispatch, queryFulfilled } = api;
|
||||
try {
|
||||
@ -165,8 +160,6 @@ export const queueApi = api.injectEndpoints({
|
||||
'BatchStatus',
|
||||
'CurrentSessionQueueItem',
|
||||
'NextSessionQueueItem',
|
||||
'SessionQueueItem',
|
||||
'SessionQueueItemDTO',
|
||||
],
|
||||
onQueryStarted: async (arg, api) => {
|
||||
const { dispatch, queryFulfilled } = api;
|
||||
@ -218,7 +211,6 @@ export const queueApi = api.injectEndpoints({
|
||||
url: `queue/${$queueId.get()}/status`,
|
||||
method: 'GET',
|
||||
}),
|
||||
|
||||
providesTags: ['SessionQueueStatus'],
|
||||
}),
|
||||
getBatchStatus: build.query<
|
||||
@ -269,7 +261,11 @@ export const queueApi = api.injectEndpoints({
|
||||
(draft) => {
|
||||
queueItemsAdapter.updateOne(draft, {
|
||||
id: item_id,
|
||||
changes: { status: data.status },
|
||||
changes: {
|
||||
status: data.status,
|
||||
completed_at: data.completed_at,
|
||||
updated_at: data.updated_at,
|
||||
},
|
||||
});
|
||||
}
|
||||
)
|
||||
@ -284,7 +280,6 @@ export const queueApi = api.injectEndpoints({
|
||||
}
|
||||
return [
|
||||
{ type: 'SessionQueueItem', id: result.item_id },
|
||||
{ type: 'SessionQueueItemDTO', id: result.item_id },
|
||||
{ type: 'BatchStatus', id: result.batch_id },
|
||||
];
|
||||
},
|
||||
@ -307,11 +302,7 @@ export const queueApi = api.injectEndpoints({
|
||||
// no-op
|
||||
}
|
||||
},
|
||||
invalidatesTags: [
|
||||
'SessionQueueItem',
|
||||
'SessionQueueItemDTO',
|
||||
'BatchStatus',
|
||||
],
|
||||
invalidatesTags: ['SessionQueueStatus', 'BatchStatus'],
|
||||
}),
|
||||
listQueueItems: build.query<
|
||||
EntityState<components['schemas']['SessionQueueItemDTO']> & {
|
||||
|
@ -21,8 +21,6 @@ export const tagTypes = [
|
||||
'ImageMetadataFromFile',
|
||||
'IntermediatesCount',
|
||||
'SessionQueueItem',
|
||||
'SessionQueueItemDTO',
|
||||
'SessionQueueItemDTOList',
|
||||
'SessionQueueStatus',
|
||||
'SessionProcessorStatus',
|
||||
'CurrentSessionQueueItem',
|
||||
|
@ -9701,11 +9701,23 @@ export type components = {
|
||||
ui_order?: number;
|
||||
};
|
||||
/**
|
||||
* StableDiffusionOnnxModelFormat
|
||||
* T2IAdapterModelFormat
|
||||
* @description An enumeration.
|
||||
* @enum {string}
|
||||
*/
|
||||
StableDiffusionOnnxModelFormat: "olive" | "onnx";
|
||||
T2IAdapterModelFormat: "diffusers";
|
||||
/**
|
||||
* ControlNetModelFormat
|
||||
* @description An enumeration.
|
||||
* @enum {string}
|
||||
*/
|
||||
ControlNetModelFormat: "checkpoint" | "diffusers";
|
||||
/**
|
||||
* StableDiffusion2ModelFormat
|
||||
* @description An enumeration.
|
||||
* @enum {string}
|
||||
*/
|
||||
StableDiffusion2ModelFormat: "checkpoint" | "diffusers";
|
||||
/**
|
||||
* StableDiffusionXLModelFormat
|
||||
* @description An enumeration.
|
||||
@ -9713,11 +9725,11 @@ export type components = {
|
||||
*/
|
||||
StableDiffusionXLModelFormat: "checkpoint" | "diffusers";
|
||||
/**
|
||||
* StableDiffusion2ModelFormat
|
||||
* StableDiffusionOnnxModelFormat
|
||||
* @description An enumeration.
|
||||
* @enum {string}
|
||||
*/
|
||||
StableDiffusion2ModelFormat: "checkpoint" | "diffusers";
|
||||
StableDiffusionOnnxModelFormat: "olive" | "onnx";
|
||||
/**
|
||||
* CLIPVisionModelFormat
|
||||
* @description An enumeration.
|
||||
@ -9736,18 +9748,6 @@ export type components = {
|
||||
* @enum {string}
|
||||
*/
|
||||
StableDiffusion1ModelFormat: "checkpoint" | "diffusers";
|
||||
/**
|
||||
* T2IAdapterModelFormat
|
||||
* @description An enumeration.
|
||||
* @enum {string}
|
||||
*/
|
||||
T2IAdapterModelFormat: "diffusers";
|
||||
/**
|
||||
* ControlNetModelFormat
|
||||
* @description An enumeration.
|
||||
* @enum {string}
|
||||
*/
|
||||
ControlNetModelFormat: "checkpoint" | "diffusers";
|
||||
};
|
||||
responses: never;
|
||||
parameters: never;
|
||||
|
@ -170,16 +170,40 @@ export type InvocationRetrievalErrorEvent = {
|
||||
*/
|
||||
export type QueueItemStatusChangedEvent = {
|
||||
queue_id: string;
|
||||
queue_item_id: number;
|
||||
queue_batch_id: string;
|
||||
session_id: string;
|
||||
graph_execution_state_id: string;
|
||||
status: components['schemas']['SessionQueueItemDTO']['status'];
|
||||
error: string | undefined;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
started_at: string | undefined;
|
||||
completed_at: string | undefined;
|
||||
queue_item: {
|
||||
queue_id: string;
|
||||
item_id: number;
|
||||
batch_id: string;
|
||||
session_id: string;
|
||||
status: components['schemas']['SessionQueueItemDTO']['status'];
|
||||
error: string | undefined;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
started_at: string | undefined;
|
||||
completed_at: string | undefined;
|
||||
};
|
||||
batch_status: {
|
||||
queue_id: string;
|
||||
batch_id: string;
|
||||
pending: number;
|
||||
in_progress: number;
|
||||
completed: number;
|
||||
failed: number;
|
||||
canceled: number;
|
||||
total: number;
|
||||
};
|
||||
queue_status: {
|
||||
queue_id: string;
|
||||
item_id?: number;
|
||||
batch_id?: string;
|
||||
session_id?: string;
|
||||
pending: number;
|
||||
in_progress: number;
|
||||
completed: number;
|
||||
failed: number;
|
||||
canceled: number;
|
||||
total: number;
|
||||
};
|
||||
};
|
||||
|
||||
export type ClientEmitSubscribeQueue = {
|
||||
|
Reference in New Issue
Block a user