feat(ui): logging cleanup

- simplify access to app logger
- spruce up and make consistent log format
- improve messaging
This commit is contained in:
psychedelicious 2023-07-22 21:03:56 +10:00
parent 907ff165be
commit 75863e7181
65 changed files with 480 additions and 573 deletions

View File

@ -69,6 +69,7 @@
"@mantine/core": "^6.0.14",
"@mantine/form": "^6.0.15",
"@mantine/hooks": "^6.0.14",
"@nanostores/react": "^0.7.1",
"@reduxjs/toolkit": "^1.9.5",
"@roarr/browser-log-writer": "^1.1.5",
"chakra-ui-contextmenu": "^1.0.5",

View File

@ -14,6 +14,7 @@ import FloatingParametersPanelButtons from 'features/ui/components/FloatingParam
import InvokeTabs from 'features/ui/components/InvokeTabs';
import ParametersDrawer from 'features/ui/components/ParametersDrawer';
import i18n from 'i18n';
import { size } from 'lodash-es';
import { ReactNode, memo, useEffect } from 'react';
import UpdateImageBoardModal from '../../features/gallery/components/Boards/UpdateImageBoardModal';
import GlobalHotkeys from './GlobalHotkeys';
@ -29,8 +30,7 @@ interface Props {
const App = ({ config = DEFAULT_CONFIG, headerComponent }: Props) => {
const language = useAppSelector(languageSelector);
const log = useLogger();
const logger = useLogger();
const dispatch = useAppDispatch();
useEffect(() => {
@ -38,9 +38,11 @@ const App = ({ config = DEFAULT_CONFIG, headerComponent }: Props) => {
}, [language]);
useEffect(() => {
log.info({ namespace: 'App', data: config }, 'Received config');
if (size(config)) {
logger.info({ namespace: 'App', config }, 'Received config');
dispatch(configChanged(config));
}, [dispatch, config, log]);
}
}, [dispatch, config, logger]);
useEffect(() => {
dispatch(appStarted());

View File

@ -0,0 +1,46 @@
import { createLogWriter } from '@roarr/browser-log-writer';
import { atom } from 'nanostores';
import { Logger, ROARR, Roarr } from 'roarr';
ROARR.write = createLogWriter();
export const BASE_CONTEXT = {};
export const log = Roarr.child(BASE_CONTEXT);
export const $logger = atom<Logger>(Roarr.child(BASE_CONTEXT));
type LoggerNamespace =
| 'images'
| 'models'
| 'config'
| 'canvas'
| 'txt2img'
| 'img2img'
| 'nodes'
| 'system'
| 'socketio'
| 'session';
export const logger = (namespace: LoggerNamespace) =>
$logger.get().child({ namespace });
export const VALID_LOG_LEVELS = [
'trace',
'debug',
'info',
'warn',
'error',
'fatal',
] as const;
export type InvokeLogLevel = (typeof VALID_LOG_LEVELS)[number];
// Translate human-readable log levels to numbers, used for log filtering
export const LOG_LEVEL_MAP: Record<InvokeLogLevel, number> = {
trace: 10,
debug: 20,
info: 30,
warn: 40,
error: 50,
fatal: 60,
};

View File

@ -1,48 +1,19 @@
import { useStore } from '@nanostores/react';
import { createSelector } from '@reduxjs/toolkit';
import { createLogWriter } from '@roarr/browser-log-writer';
import { useAppSelector } from 'app/store/storeHooks';
import { systemSelector } from 'features/system/store/systemSelectors';
import { isEqual } from 'lodash-es';
import { useEffect } from 'react';
import { LogLevelName, ROARR, Roarr } from 'roarr';
import { createLogWriter } from '@roarr/browser-log-writer';
// Base logging context includes only the package name
const baseContext = { package: '@invoke-ai/invoke-ai-ui' };
// Create browser log writer
ROARR.write = createLogWriter();
// Module-scoped logger - can be imported and used anywhere
export let log = Roarr.child(baseContext);
// Translate human-readable log levels to numbers, used for log filtering
export const LOG_LEVEL_MAP: Record<LogLevelName, number> = {
trace: 10,
debug: 20,
info: 30,
warn: 40,
error: 50,
fatal: 60,
};
export const VALID_LOG_LEVELS = [
'trace',
'debug',
'info',
'warn',
'error',
'fatal',
] as const;
export type InvokeLogLevel = (typeof VALID_LOG_LEVELS)[number];
import { ROARR, Roarr } from 'roarr';
import { $logger, BASE_CONTEXT, LOG_LEVEL_MAP } from './logger';
const selector = createSelector(
systemSelector,
(system) => {
const { app_version, consoleLogLevel, shouldLogToConsole } = system;
const { consoleLogLevel, shouldLogToConsole } = system;
return {
version: app_version,
consoleLogLevel,
shouldLogToConsole,
};
@ -55,8 +26,7 @@ const selector = createSelector(
);
export const useLogger = () => {
const { version, consoleLogLevel, shouldLogToConsole } =
useAppSelector(selector);
const { consoleLogLevel, shouldLogToConsole } = useAppSelector(selector);
// The provided Roarr browser log writer uses localStorage to config logging to console
useEffect(() => {
@ -79,16 +49,13 @@ export const useLogger = () => {
// Update the module-scoped logger context as needed
useEffect(() => {
const newContext: Record<string, any> = {
...baseContext,
...BASE_CONTEXT,
};
if (version) {
newContext.version = version;
}
$logger.set(Roarr.child(newContext));
}, []);
log = Roarr.child(newContext);
}, [version]);
const logger = useStore($logger);
// Use the logger within components - no different than just importing it directly
return log;
return logger;
};

View File

@ -8,10 +8,11 @@ import {
import type { AppDispatch, RootState } from '../../store';
import { addCommitStagingAreaImageListener } from './listeners/addCommitStagingAreaImageListener';
import { addFirstListImagesListener } from './listeners/addFirstListImagesListener.ts';
import { addAppConfigReceivedListener } from './listeners/appConfigReceived';
import { addAppStartedListener } from './listeners/appStarted';
import { addBoardIdSelectedListener } from './listeners/boardIdSelected';
import { addDeleteBoardAndImagesFulfilledListener } from './listeners/boardAndImagesDeleted';
import { addBoardIdSelectedListener } from './listeners/boardIdSelected';
import { addCanvasCopiedToClipboardListener } from './listeners/canvasCopiedToClipboard';
import { addCanvasDownloadedAsImageListener } from './listeners/canvasDownloadedAsImage';
import { addCanvasMergedListener } from './listeners/canvasMerged';
@ -34,10 +35,6 @@ import {
addImageRemovedFromBoardRejectedListener,
} from './listeners/imageRemovedFromBoard';
import { addImageToDeleteSelectedListener } from './listeners/imageToDeleteSelected';
import {
addImageUpdatedFulfilledListener,
addImageUpdatedRejectedListener,
} from './listeners/imageUpdated';
import {
addImageUploadedFulfilledListener,
addImageUploadedRejectedListener,
@ -69,17 +66,15 @@ import { addGraphExecutionStateCompleteEventListener as addGraphExecutionStateCo
import { addInvocationCompleteEventListener as addInvocationCompleteListener } from './listeners/socketio/socketInvocationComplete';
import { addInvocationErrorEventListener as addInvocationErrorListener } from './listeners/socketio/socketInvocationError';
import { addInvocationStartedEventListener as addInvocationStartedListener } from './listeners/socketio/socketInvocationStarted';
import { addModelLoadEventListener } from './listeners/socketio/socketModelLoad';
import { addSocketSubscribedEventListener as addSocketSubscribedListener } from './listeners/socketio/socketSubscribed';
import { addSocketUnsubscribedEventListener as addSocketUnsubscribedListener } from './listeners/socketio/socketUnsubscribed';
import { addStagingAreaImageSavedListener } from './listeners/stagingAreaImageSaved';
import { addUpscaleRequestedListener } from './listeners/upscaleRequested';
import { addUserInvokedCanvasListener } from './listeners/userInvokedCanvas';
import { addUserInvokedImageToImageListener } from './listeners/userInvokedImageToImage';
import { addUserInvokedNodesListener } from './listeners/userInvokedNodes';
import { addUserInvokedTextToImageListener } from './listeners/userInvokedTextToImage';
import { addModelLoadStartedEventListener } from './listeners/socketio/socketModelLoadStarted';
import { addModelLoadCompletedEventListener } from './listeners/socketio/socketModelLoadCompleted';
import { addUpscaleRequestedListener } from './listeners/upscaleRequested';
import { addFirstListImagesListener } from './listeners/addFirstListImagesListener.ts';
export const listenerMiddleware = createListenerMiddleware();
@ -109,10 +104,6 @@ export type AppListenerEffect = ListenerEffect<
addImageUploadedFulfilledListener();
addImageUploadedRejectedListener();
// Image updated
addImageUpdatedFulfilledListener();
addImageUpdatedRejectedListener();
// Image selected
addInitialImageSelectedListener();
@ -161,8 +152,7 @@ addSocketConnectedListener();
addSocketDisconnectedListener();
addSocketSubscribedListener();
addSocketUnsubscribedListener();
addModelLoadStartedEventListener();
addModelLoadCompletedEventListener();
addModelLoadEventListener();
// Session Created
addSessionCreatedPendingListener();

View File

@ -1,14 +1,13 @@
import { startAppListening } from '..';
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { commitStagingAreaImage } from 'features/canvas/store/canvasSlice';
import { sessionCanceled } from 'services/api/thunks/session';
const moduleLog = log.child({ namespace: 'canvas' });
import { startAppListening } from '..';
export const addCommitStagingAreaImageListener = () => {
startAppListening({
actionCreator: commitStagingAreaImage,
effect: async (action, { dispatch, getState }) => {
const log = logger('canvas');
const state = getState();
const { sessionId: session_id, isProcessing } = state.system;
const canvasSessionId = action.payload;
@ -19,18 +18,16 @@ export const addCommitStagingAreaImageListener = () => {
}
if (!canvasSessionId) {
moduleLog.debug('No canvas session, skipping cancel');
log.debug('No canvas session, skipping cancel');
return;
}
if (canvasSessionId !== session_id) {
moduleLog.debug(
log.debug(
{
data: {
canvasSessionId,
session_id,
},
},
'Canvas session does not match global session, skipping cancel'
);
return;

View File

@ -1,4 +1,4 @@
import { log } from 'app/logging/useLogger';
import { isAnyOf } from '@reduxjs/toolkit';
import {
ASSETS_CATEGORIES,
IMAGE_CATEGORIES,
@ -8,9 +8,6 @@ import {
} from 'features/gallery/store/gallerySlice';
import { imagesApi } from 'services/api/endpoints/images';
import { startAppListening } from '..';
import { isAnyOf } from '@reduxjs/toolkit';
const moduleLog = log.child({ namespace: 'boards' });
export const addBoardIdSelectedListener = () => {
startAppListening({

View File

@ -1,16 +1,17 @@
import { canvasCopiedToClipboard } from 'features/canvas/store/actions';
import { startAppListening } from '..';
import { log } from 'app/logging/useLogger';
import { $logger } from 'app/logging/logger';
import { getBaseLayerBlob } from 'features/canvas/util/getBaseLayerBlob';
import { addToast } from 'features/system/store/systemSlice';
import { copyBlobToClipboard } from 'features/canvas/util/copyBlobToClipboard';
const moduleLog = log.child({ namespace: 'canvasCopiedToClipboardListener' });
export const addCanvasCopiedToClipboardListener = () => {
startAppListening({
actionCreator: canvasCopiedToClipboard,
effect: async (action, { dispatch, getState }) => {
const moduleLog = $logger
.get()
.child({ namespace: 'canvasCopiedToClipboardListener' });
const state = getState();
const blob = await getBaseLayerBlob(state);

View File

@ -1,16 +1,17 @@
import { canvasDownloadedAsImage } from 'features/canvas/store/actions';
import { startAppListening } from '..';
import { log } from 'app/logging/useLogger';
import { $logger } from 'app/logging/logger';
import { downloadBlob } from 'features/canvas/util/downloadBlob';
import { getBaseLayerBlob } from 'features/canvas/util/getBaseLayerBlob';
import { addToast } from 'features/system/store/systemSlice';
const moduleLog = log.child({ namespace: 'canvasSavedToGalleryListener' });
export const addCanvasDownloadedAsImageListener = () => {
startAppListening({
actionCreator: canvasDownloadedAsImage,
effect: async (action, { dispatch, getState }) => {
const moduleLog = $logger
.get()
.child({ namespace: 'canvasSavedToGalleryListener' });
const state = getState();
const blob = await getBaseLayerBlob(state);

View File

@ -1,4 +1,4 @@
import { log } from 'app/logging/useLogger';
import { $logger } from 'app/logging/logger';
import { canvasMerged } from 'features/canvas/store/actions';
import { setMergedCanvas } from 'features/canvas/store/canvasSlice';
import { getFullBaseLayerBlob } from 'features/canvas/util/getFullBaseLayerBlob';
@ -7,12 +7,13 @@ import { addToast } from 'features/system/store/systemSlice';
import { imagesApi } from 'services/api/endpoints/images';
import { startAppListening } from '..';
const moduleLog = log.child({ namespace: 'canvasCopiedToClipboardListener' });
export const addCanvasMergedListener = () => {
startAppListening({
actionCreator: canvasMerged,
effect: async (action, { dispatch, getState, take }) => {
const moduleLog = $logger
.get()
.child({ namespace: 'canvasCopiedToClipboardListener' });
const blob = await getFullBaseLayerBlob();
if (!blob) {

View File

@ -1,22 +1,21 @@
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { canvasSavedToGallery } from 'features/canvas/store/actions';
import { getBaseLayerBlob } from 'features/canvas/util/getBaseLayerBlob';
import { addToast } from 'features/system/store/systemSlice';
import { imagesApi } from 'services/api/endpoints/images';
import { startAppListening } from '..';
const moduleLog = log.child({ namespace: 'canvasSavedToGalleryListener' });
export const addCanvasSavedToGalleryListener = () => {
startAppListening({
actionCreator: canvasSavedToGallery,
effect: async (action, { dispatch, getState, take }) => {
const log = logger('canvas');
const state = getState();
const blob = await getBaseLayerBlob(state);
if (!blob) {
moduleLog.error('Problem getting base layer blob');
log.error('Problem getting base layer blob');
dispatch(
addToast({
title: 'Problem Saving Canvas',

View File

@ -1,6 +1,6 @@
import { AnyListenerPredicate } from '@reduxjs/toolkit';
import { startAppListening } from '..';
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { RootState } from 'app/store/store';
import { controlNetImageProcessed } from 'features/controlNet/store/actions';
import {
controlNetAutoConfigToggled,
@ -9,9 +9,7 @@ import {
controlNetProcessorParamsChanged,
controlNetProcessorTypeChanged,
} from 'features/controlNet/store/controlNetSlice';
import { RootState } from 'app/store/store';
const moduleLog = log.child({ namespace: 'controlNet' });
import { startAppListening } from '..';
const predicate: AnyListenerPredicate<RootState> = (
action,
@ -68,14 +66,12 @@ export const addControlNetAutoProcessListener = () => {
action,
{ dispatch, getState, cancelActiveListeners, delay }
) => {
const log = logger('session');
const { controlNetId } = action.payload;
// Cancel any in-progress instances of this listener
cancelActiveListeners();
moduleLog.trace(
{ data: action.payload },
'ControlNet auto-process triggered'
);
log.trace('ControlNet auto-process triggered');
// Delay before starting actual work
await delay(300);

View File

@ -1,4 +1,4 @@
import { log } from 'app/logging/useLogger';
import { $logger, logger } from 'app/logging/logger';
import { controlNetImageProcessed } from 'features/controlNet/store/actions';
import { controlNetProcessedImageChanged } from 'features/controlNet/store/controlNetSlice';
import { sessionReadyToInvoke } from 'features/system/store/actions';
@ -9,8 +9,6 @@ import { Graph, ImageDTO } from 'services/api/types';
import { socketInvocationComplete } from 'services/events/actions';
import { startAppListening } from '..';
const moduleLog = log.child({ namespace: 'controlNet' });
export const addControlNetImageProcessedListener = () => {
startAppListening({
actionCreator: controlNetImageProcessed,
@ -18,11 +16,12 @@ export const addControlNetImageProcessedListener = () => {
action,
{ dispatch, getState, take, unsubscribe, subscribe }
) => {
const log = logger('session');
const { controlNetId } = action.payload;
const controlNet = getState().controlNet.controlNets[controlNetId];
if (!controlNet.controlImage) {
moduleLog.error('Unable to process ControlNet image');
log.error('Unable to process ControlNet image');
return;
}
@ -70,8 +69,8 @@ export const addControlNetImageProcessedListener = () => {
const processedControlImage = payload as ImageDTO;
moduleLog.debug(
{ data: { arg: action.payload, processedControlImage } },
log.debug(
{ controlNetId: action.payload, processedControlImage },
'ControlNet image processed'
);

View File

@ -1,18 +1,17 @@
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { imagesApi } from 'services/api/endpoints/images';
import { startAppListening } from '..';
const moduleLog = log.child({ namespace: 'boards' });
export const addImageAddedToBoardFulfilledListener = () => {
startAppListening({
matcher: imagesApi.endpoints.addImageToBoard.matchFulfilled,
effect: (action, { getState, dispatch }) => {
const log = logger('images');
const { board_id, imageDTO } = action.meta.arg.originalArgs;
// TODO: update listImages cache for this board
moduleLog.debug({ data: { board_id, imageDTO } }, 'Image added to board');
log.debug({ board_id, imageDTO }, 'Image added to board');
},
});
};
@ -21,12 +20,10 @@ export const addImageAddedToBoardRejectedListener = () => {
startAppListening({
matcher: imagesApi.endpoints.addImageToBoard.matchRejected,
effect: (action, { getState, dispatch }) => {
const log = logger('images');
const { board_id, imageDTO } = action.meta.arg.originalArgs;
moduleLog.debug(
{ data: { board_id, imageDTO } },
'Problem adding image to board'
);
log.debug({ board_id, imageDTO }, 'Problem adding image to board');
},
});
};

View File

@ -1,4 +1,4 @@
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { resetCanvas } from 'features/canvas/store/canvasSlice';
import { controlNetReset } from 'features/controlNet/store/controlNetSlice';
import { selectListImagesBaseQueryArgs } from 'features/gallery/store/gallerySelectors';
@ -14,8 +14,6 @@ import { api } from 'services/api';
import { imagesApi } from 'services/api/endpoints/images';
import { startAppListening } from '..';
const moduleLog = log.child({ namespace: 'image' });
/**
* Called when the user requests an image deletion
*/
@ -23,6 +21,7 @@ export const addRequestedImageDeletionListener = () => {
startAppListening({
actionCreator: imageDeletionConfirmed,
effect: async (action, { dispatch, getState, condition }) => {
const log = logger('images');
const { imageDTO, imageUsage } = action.payload;
dispatch(isModalOpenChanged(false));
@ -108,6 +107,7 @@ export const addImageDeletedPendingListener = () => {
startAppListening({
matcher: imagesApi.endpoints.deleteImage.matchPending,
effect: (action, { dispatch, getState }) => {
const log = logger('images');
//
},
});
@ -120,10 +120,8 @@ export const addImageDeletedFulfilledListener = () => {
startAppListening({
matcher: imagesApi.endpoints.deleteImage.matchFulfilled,
effect: (action, { dispatch, getState }) => {
moduleLog.debug(
{ data: { image: action.meta.arg.originalArgs } },
'Image deleted'
);
const log = logger('images');
log.debug({ imageDTO: action.meta.arg.originalArgs }, 'Image deleted');
},
});
};
@ -135,8 +133,9 @@ export const addImageDeletedRejectedListener = () => {
startAppListening({
matcher: imagesApi.endpoints.deleteImage.matchRejected,
effect: (action, { dispatch, getState }) => {
moduleLog.debug(
{ data: { image: action.meta.arg.originalArgs } },
const log = logger('images');
log.debug(
{ imageDTO: action.meta.arg.originalArgs },
'Unable to delete image'
);
},

View File

@ -3,7 +3,7 @@ import {
TypesafeDraggableData,
TypesafeDroppableData,
} from 'app/components/ImageDnd/typesafeDnd';
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
import { controlNetImageChanged } from 'features/controlNet/store/controlNetSlice';
import {
@ -15,8 +15,6 @@ import { initialImageChanged } from 'features/parameters/store/generationSlice';
import { imagesApi } from 'services/api/endpoints/images';
import { startAppListening } from '../';
const moduleLog = log.child({ namespace: 'dnd' });
export const dndDropped = createAction<{
overData: TypesafeDroppableData;
activeData: TypesafeDraggableData;
@ -26,13 +24,10 @@ export const addImageDroppedListener = () => {
startAppListening({
actionCreator: dndDropped,
effect: async (action, { dispatch, getState, take }) => {
const log = logger('images');
const { activeData, overData } = action.payload;
const state = getState();
moduleLog.debug(
{ data: { activeData, overData } },
'Image or selection dropped'
);
log.debug({ activeData, overData }, 'Image or selection dropped');
// set current image
if (

View File

@ -1,19 +1,15 @@
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { imagesApi } from 'services/api/endpoints/images';
import { startAppListening } from '..';
const moduleLog = log.child({ namespace: 'boards' });
export const addImageRemovedFromBoardFulfilledListener = () => {
startAppListening({
matcher: imagesApi.endpoints.removeImageFromBoard.matchFulfilled,
effect: (action, { getState, dispatch }) => {
const { board_id, image_name } = action.meta.arg.originalArgs;
const log = logger('images');
const imageDTO = action.meta.arg.originalArgs;
moduleLog.debug(
{ data: { board_id, image_name } },
'Image added to board'
);
log.debug({ imageDTO }, 'Image removed from board');
},
});
};
@ -22,12 +18,10 @@ export const addImageRemovedFromBoardRejectedListener = () => {
startAppListening({
matcher: imagesApi.endpoints.removeImageFromBoard.matchRejected,
effect: (action, { getState, dispatch }) => {
const { board_id, image_name } = action.meta.arg.originalArgs;
const log = logger('images');
const imageDTO = action.meta.arg.originalArgs;
moduleLog.debug(
{ data: { board_id, image_name } },
'Problem adding image to board'
);
log.debug({ imageDTO }, 'Problem removing image from board');
},
});
};

View File

@ -1,13 +1,10 @@
import { startAppListening } from '..';
import { log } from 'app/logging/useLogger';
import {
imageDeletionConfirmed,
imageToDeleteSelected,
isModalOpenChanged,
selectImageUsage,
} from 'features/imageDeletion/store/imageDeletionSlice';
const moduleLog = log.child({ namespace: 'image' });
import { startAppListening } from '..';
export const addImageToDeleteSelectedListener = () => {
startAppListening({

View File

@ -1,34 +0,0 @@
import { log } from 'app/logging/useLogger';
import { imagesApi } from 'services/api/endpoints/images';
import { startAppListening } from '..';
const moduleLog = log.child({ namespace: 'image' });
export const addImageUpdatedFulfilledListener = () => {
// startAppListening({
// matcher: imagesApi.endpoints.updateImage.matchFulfilled,
// effect: (action, { dispatch, getState }) => {
// moduleLog.debug(
// {
// data: {
// oldImage: action.meta.arg.originalArgs,
// updatedImage: action.payload,
// },
// },
// 'Image updated'
// );
// },
// });
};
export const addImageUpdatedRejectedListener = () => {
// startAppListening({
// matcher: imagesApi.endpoints.updateImage.matchRejected,
// effect: (action, { dispatch }) => {
// moduleLog.debug(
// { data: action.meta.arg.originalArgs },
// 'Image update failed'
// );
// },
// });
};

View File

@ -1,5 +1,5 @@
import { UseToastOptions } from '@chakra-ui/react';
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
import { controlNetImageChanged } from 'features/controlNet/store/controlNetSlice';
import { imagesAddedToBatch } from 'features/gallery/store/gallerySlice';
@ -10,8 +10,6 @@ import { boardsApi } from 'services/api/endpoints/boards';
import { startAppListening } from '..';
import { imagesApi } from '../../../../../services/api/endpoints/images';
const moduleLog = log.child({ namespace: 'image' });
const DEFAULT_UPLOADED_TOAST: UseToastOptions = {
title: 'Image Uploaded',
status: 'success',
@ -21,11 +19,12 @@ export const addImageUploadedFulfilledListener = () => {
startAppListening({
matcher: imagesApi.endpoints.uploadImage.matchFulfilled,
effect: (action, { dispatch, getState }) => {
const log = logger('images');
const imageDTO = action.payload;
const state = getState();
const { selectedBoardId, autoAddBoardId } = state.gallery;
moduleLog.debug({ arg: '<Blob>', imageDTO }, 'Image uploaded');
log.debug({ imageDTO }, 'Image uploaded');
const { postUploadAction } = action.meta.arg.originalArgs;
@ -140,9 +139,10 @@ export const addImageUploadedRejectedListener = () => {
startAppListening({
matcher: imagesApi.endpoints.uploadImage.matchRejected,
effect: (action, { dispatch }) => {
const log = logger('images');
const { file, postUploadAction, ...rest } = action.meta.arg.originalArgs;
const sanitizedData = { arg: { ...rest, file: '<Blob>' } };
moduleLog.error({ data: sanitizedData }, 'Image upload failed');
log.error({ ...sanitizedData }, 'Image upload failed');
dispatch(
addToast({
title: 'Image Upload Failed',

View File

@ -1,5 +1,5 @@
import { makeToast } from 'app/components/Toaster';
import { log } from 'app/logging/useLogger';
import { $logger, logger } from 'app/logging/logger';
import { loraRemoved } from 'features/lora/store/loraSlice';
import { modelSelected } from 'features/parameters/store/actions';
import {
@ -12,17 +12,17 @@ import { forEach } from 'lodash-es';
import { startAppListening } from '..';
import { controlNetRemoved } from 'features/controlNet/store/controlNetSlice';
const moduleLog = log.child({ module: 'models' });
export const addModelSelectedListener = () => {
startAppListening({
actionCreator: modelSelected,
effect: (action, { getState, dispatch }) => {
const log = logger('models');
const state = getState();
const result = zMainModel.safeParse(action.payload);
if (!result.success) {
moduleLog.error(
log.error(
{ error: result.error.format() },
'Failed to parse main model'
);

View File

@ -1,4 +1,4 @@
import { log } from 'app/logging/useLogger';
import { $logger, logger } from 'app/logging/logger';
import { loraRemoved } from 'features/lora/store/loraSlice';
import {
modelChanged,
@ -13,13 +13,16 @@ import { modelsApi } from 'services/api/endpoints/models';
import { startAppListening } from '..';
import { controlNetRemoved } from 'features/controlNet/store/controlNetSlice';
const moduleLog = log.child({ module: 'models' });
export const addModelsLoadedListener = () => {
startAppListening({
matcher: modelsApi.endpoints.getMainModels.matchFulfilled,
effect: async (action, { getState, dispatch }) => {
// models loaded, we need to ensure the selected model is available and if not, select the first one
const log = logger('models');
log.info(
{ models: action.payload.entities },
`Main models loaded (${action.payload.ids.length})`
);
const currentModel = getState().generation.model;
@ -46,7 +49,7 @@ export const addModelsLoadedListener = () => {
const result = zMainModel.safeParse(firstModel);
if (!result.success) {
moduleLog.error(
log.error(
{ error: result.error.format() },
'Failed to parse main model'
);
@ -60,6 +63,11 @@ export const addModelsLoadedListener = () => {
matcher: modelsApi.endpoints.getVaeModels.matchFulfilled,
effect: async (action, { getState, dispatch }) => {
// VAEs loaded, need to reset the VAE is it's no longer available
const log = logger('models');
log.info(
{ models: action.payload.entities },
`VAEs loaded (${action.payload.ids.length})`
);
const currentVae = getState().generation.vae;
@ -91,7 +99,7 @@ export const addModelsLoadedListener = () => {
const result = zVaeModel.safeParse(firstModel);
if (!result.success) {
moduleLog.error(
log.error(
{ error: result.error.format() },
'Failed to parse VAE model'
);
@ -105,6 +113,11 @@ export const addModelsLoadedListener = () => {
matcher: modelsApi.endpoints.getLoRAModels.matchFulfilled,
effect: async (action, { getState, dispatch }) => {
// LoRA models loaded - need to remove missing LoRAs from state
const log = logger('models');
log.info(
{ models: action.payload.entities },
`LoRAs loaded (${action.payload.ids.length})`
);
const loras = getState().lora.loras;
@ -128,6 +141,12 @@ export const addModelsLoadedListener = () => {
matcher: modelsApi.endpoints.getControlNetModels.matchFulfilled,
effect: async (action, { getState, dispatch }) => {
// ControlNet models loaded - need to remove missing ControlNets from state
const log = logger('models');
log.info(
{ models: action.payload.entities },
`ControlNet models loaded (${action.payload.ids.length})`
);
const controlNets = getState().controlNet.controlNets;
forEach(controlNets, (controlNet, controlNetId) => {
@ -146,4 +165,14 @@ export const addModelsLoadedListener = () => {
});
},
});
startAppListening({
matcher: modelsApi.endpoints.getTextualInversionModels.matchFulfilled,
effect: async (action, { getState, dispatch }) => {
const log = logger('models');
log.info(
{ models: action.payload.entities },
`Embeddings loaded (${action.payload.ids.length})`
);
},
});
};

View File

@ -1,24 +1,24 @@
import { logger } from 'app/logging/logger';
import { nodeTemplatesBuilt } from 'features/nodes/store/nodesSlice';
import { parseSchema } from 'features/nodes/util/parseSchema';
import { size } from 'lodash-es';
import { receivedOpenAPISchema } from 'services/api/thunks/schema';
import { startAppListening } from '..';
import { log } from 'app/logging/useLogger';
import { parseSchema } from 'features/nodes/util/parseSchema';
import { nodeTemplatesBuilt } from 'features/nodes/store/nodesSlice';
import { size } from 'lodash-es';
const schemaLog = log.child({ namespace: 'schema' });
import { parseify } from 'common/util/serialize';
export const addReceivedOpenAPISchemaListener = () => {
startAppListening({
actionCreator: receivedOpenAPISchema.fulfilled,
effect: (action, { dispatch, getState }) => {
const log = logger('system');
const schemaJSON = action.payload;
schemaLog.info({ data: { schemaJSON } }, 'Dereferenced OpenAPI schema');
log.debug({ schemaJSON }, 'Dereferenced OpenAPI schema');
const nodeTemplates = parseSchema(schemaJSON);
schemaLog.info(
{ data: { nodeTemplates } },
log.debug(
{ nodeTemplates: parseify(nodeTemplates) },
`Built ${size(nodeTemplates)} node templates`
);
@ -29,7 +29,8 @@ export const addReceivedOpenAPISchemaListener = () => {
startAppListening({
actionCreator: receivedOpenAPISchema.rejected,
effect: (action, { dispatch, getState }) => {
schemaLog.error('Problem dereferencing OpenAPI Schema');
const log = logger('system');
log.error('Problem dereferencing OpenAPI Schema');
},
});
};

View File

@ -1,14 +1,13 @@
import { log } from 'app/logging/useLogger';
import { startAppListening } from '..';
import { sessionCanceled } from 'services/api/thunks/session';
import { logger } from 'app/logging/logger';
import { serializeError } from 'serialize-error';
const moduleLog = log.child({ namespace: 'session' });
import { sessionCanceled } from 'services/api/thunks/session';
import { startAppListening } from '..';
export const addSessionCanceledPendingListener = () => {
startAppListening({
actionCreator: sessionCanceled.pending,
effect: (action, { getState, dispatch }) => {
const log = logger('session');
//
},
});
@ -18,11 +17,9 @@ export const addSessionCanceledFulfilledListener = () => {
startAppListening({
actionCreator: sessionCanceled.fulfilled,
effect: (action, { getState, dispatch }) => {
const log = logger('session');
const { session_id } = action.meta.arg;
moduleLog.debug(
{ data: { session_id } },
`Session canceled (${session_id})`
);
log.debug({ session_id }, `Session canceled (${session_id})`);
},
});
};
@ -31,15 +28,15 @@ export const addSessionCanceledRejectedListener = () => {
startAppListening({
actionCreator: sessionCanceled.rejected,
effect: (action, { getState, dispatch }) => {
const log = logger('session');
const { session_id } = action.meta.arg;
if (action.payload) {
const { arg, error } = action.payload;
moduleLog.error(
const { error } = action.payload;
log.error(
{
data: {
arg,
session_id,
error: serializeError(error),
},
},
`Problem canceling session`
);
}

View File

@ -1,14 +1,14 @@
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { parseify } from 'common/util/serialize';
import { serializeError } from 'serialize-error';
import { sessionCreated } from 'services/api/thunks/session';
import { startAppListening } from '..';
const moduleLog = log.child({ namespace: 'session' });
export const addSessionCreatedPendingListener = () => {
startAppListening({
actionCreator: sessionCreated.pending,
effect: (action, { getState, dispatch }) => {
const log = logger('session');
//
},
});
@ -18,8 +18,12 @@ export const addSessionCreatedFulfilledListener = () => {
startAppListening({
actionCreator: sessionCreated.fulfilled,
effect: (action, { getState, dispatch }) => {
const log = logger('session');
const session = action.payload;
moduleLog.debug({ data: { session } }, `Session created (${session.id})`);
log.debug(
{ session: parseify(session) },
`Session created (${session.id})`
);
},
});
};
@ -28,16 +32,13 @@ export const addSessionCreatedRejectedListener = () => {
startAppListening({
actionCreator: sessionCreated.rejected,
effect: (action, { getState, dispatch }) => {
const log = logger('session');
if (action.payload) {
const { arg, error } = action.payload;
const graph = parseify(action.meta.arg);
const stringifiedError = JSON.stringify(error);
moduleLog.error(
{
data: {
arg,
error: serializeError(error),
},
},
log.error(
{ graph, error: serializeError(error) },
`Problem creating session: ${stringifiedError}`
);
}

View File

@ -1,14 +1,13 @@
import { log } from 'app/logging/useLogger';
import { startAppListening } from '..';
import { sessionInvoked } from 'services/api/thunks/session';
import { logger } from 'app/logging/logger';
import { serializeError } from 'serialize-error';
const moduleLog = log.child({ namespace: 'session' });
import { sessionInvoked } from 'services/api/thunks/session';
import { startAppListening } from '..';
export const addSessionInvokedPendingListener = () => {
startAppListening({
actionCreator: sessionInvoked.pending,
effect: (action, { getState, dispatch }) => {
const log = logger('session');
//
},
});
@ -18,11 +17,9 @@ export const addSessionInvokedFulfilledListener = () => {
startAppListening({
actionCreator: sessionInvoked.fulfilled,
effect: (action, { getState, dispatch }) => {
const log = logger('session');
const { session_id } = action.meta.arg;
moduleLog.debug(
{ data: { session_id } },
`Session invoked (${session_id})`
);
log.debug({ session_id }, `Session invoked (${session_id})`);
},
});
};
@ -31,16 +28,16 @@ export const addSessionInvokedRejectedListener = () => {
startAppListening({
actionCreator: sessionInvoked.rejected,
effect: (action, { getState, dispatch }) => {
const log = logger('session');
const { session_id } = action.meta.arg;
if (action.payload) {
const { arg, error } = action.payload;
const stringifiedError = JSON.stringify(error);
moduleLog.error(
log.error(
{
data: {
arg,
session_id,
error: serializeError(error),
},
},
`Problem invoking session: ${stringifiedError}`
);
}

View File

@ -1,20 +1,16 @@
import { startAppListening } from '..';
import { sessionInvoked } from 'services/api/thunks/session';
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { sessionReadyToInvoke } from 'features/system/store/actions';
const moduleLog = log.child({ namespace: 'session' });
import { sessionInvoked } from 'services/api/thunks/session';
import { startAppListening } from '..';
export const addSessionReadyToInvokeListener = () => {
startAppListening({
actionCreator: sessionReadyToInvoke,
effect: (action, { getState, dispatch }) => {
const log = logger('session');
const { sessionId: session_id } = getState().system;
if (session_id) {
moduleLog.debug(
{ session_id },
`Session ready to invoke (${session_id})})`
);
log.debug({ session_id }, `Session ready to invoke (${session_id})})`);
dispatch(sessionInvoked({ session_id }));
}
},

View File

@ -1,18 +1,16 @@
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { modelsApi } from 'services/api/endpoints/models';
import { receivedOpenAPISchema } from 'services/api/thunks/schema';
import { appSocketConnected, socketConnected } from 'services/events/actions';
import { startAppListening } from '../..';
const moduleLog = log.child({ namespace: 'socketio' });
export const addSocketConnectedEventListener = () => {
startAppListening({
actionCreator: socketConnected,
effect: (action, { dispatch, getState }) => {
const { timestamp } = action.payload;
const log = logger('socketio');
moduleLog.debug({ timestamp }, 'Connected');
log.debug('Connected');
const { nodes, config } = getState();

View File

@ -1,17 +1,16 @@
import { startAppListening } from '../..';
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import {
socketDisconnected,
appSocketDisconnected,
socketDisconnected,
} from 'services/events/actions';
const moduleLog = log.child({ namespace: 'socketio' });
import { startAppListening } from '../..';
export const addSocketDisconnectedEventListener = () => {
startAppListening({
actionCreator: socketDisconnected,
effect: (action, { dispatch, getState }) => {
moduleLog.debug(action.payload, 'Disconnected');
const log = logger('socketio');
log.debug('Disconnected');
// pass along the socket event as an application action
dispatch(appSocketDisconnected(action.payload));
},

View File

@ -1,28 +1,27 @@
import { startAppListening } from '../..';
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import {
appSocketGeneratorProgress,
socketGeneratorProgress,
} from 'services/events/actions';
const moduleLog = log.child({ namespace: 'socketio' });
import { startAppListening } from '../..';
export const addGeneratorProgressEventListener = () => {
startAppListening({
actionCreator: socketGeneratorProgress,
effect: (action, { dispatch, getState }) => {
const log = logger('socketio');
if (
getState().system.canceledSession ===
action.payload.data.graph_execution_state_id
) {
moduleLog.trace(
log.trace(
action.payload,
'Ignored generator progress for canceled session'
);
return;
}
moduleLog.trace(
log.trace(
action.payload,
`Generator progress (${action.payload.data.node.type})`
);

View File

@ -1,20 +1,16 @@
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import {
appSocketGraphExecutionStateComplete,
socketGraphExecutionStateComplete,
} from 'services/events/actions';
import { startAppListening } from '../..';
const moduleLog = log.child({ namespace: 'socketio' });
export const addGraphExecutionStateCompleteEventListener = () => {
startAppListening({
actionCreator: socketGraphExecutionStateComplete,
effect: (action, { dispatch, getState }) => {
moduleLog.debug(
action.payload,
`Session invocation complete (${action.payload.data.graph_execution_state_id})`
);
const log = logger('socketio');
log.debug(action.payload, 'Session complete');
// pass along the socket event as an application action
dispatch(appSocketGraphExecutionStateComplete(action.payload));
},

View File

@ -1,4 +1,5 @@
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { parseify } from 'common/util/serialize';
import { addImageToStagingArea } from 'features/canvas/store/canvasSlice';
import {
IMAGE_CATEGORIES,
@ -16,15 +17,16 @@ import {
} from 'services/events/actions';
import { startAppListening } from '../..';
const moduleLog = log.child({ namespace: 'socketio' });
const nodeDenylist = ['dataURL_image'];
export const addInvocationCompleteEventListener = () => {
startAppListening({
actionCreator: socketInvocationComplete,
effect: async (action, { dispatch, getState, take }) => {
moduleLog.debug(
{ data: action.payload },
const log = logger('socketio');
const { data } = action.payload;
log.debug(
{ data: parseify(data) },
`Invocation complete (${action.payload.data.node.type})`
);
const session_id = action.payload.data.graph_execution_state_id;
@ -36,7 +38,6 @@ export const addInvocationCompleteEventListener = () => {
dispatch(sessionCanceled({ session_id }));
}
const { data } = action.payload;
const { result, node, graph_execution_state_id } = data;
// This complete event has an associated image output

View File

@ -1,19 +1,18 @@
import { startAppListening } from '../..';
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import {
appSocketInvocationError,
socketInvocationError,
} from 'services/events/actions';
const moduleLog = log.child({ namespace: 'socketio' });
import { startAppListening } from '../..';
export const addInvocationErrorEventListener = () => {
startAppListening({
actionCreator: socketInvocationError,
effect: (action, { dispatch, getState }) => {
moduleLog.error(
const log = logger('socketio');
log.error(
action.payload,
`Invocation error (${action.payload.data.node.type}): ${action.payload.data.error}`
`Invocation error (${action.payload.data.node.type})`
);
dispatch(appSocketInvocationError(action.payload));
},

View File

@ -1,31 +1,27 @@
import { startAppListening } from '../..';
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import {
appSocketInvocationStarted,
socketInvocationStarted,
} from 'services/events/actions';
const moduleLog = log.child({ namespace: 'socketio' });
import { startAppListening } from '../..';
export const addInvocationStartedEventListener = () => {
startAppListening({
actionCreator: socketInvocationStarted,
effect: (action, { dispatch, getState }) => {
const log = logger('socketio');
if (
getState().system.canceledSession ===
action.payload.data.graph_execution_state_id
) {
moduleLog.trace(
log.trace(
action.payload,
'Ignored invocation started for canceled session'
);
return;
}
moduleLog.debug(
action.payload,
`Invocation started (${action.payload.data.node.type})`
);
log.debug(action.payload, 'Invocation started');
dispatch(appSocketInvocationStarted(action.payload));
},
});

View File

@ -0,0 +1,58 @@
import { logger } from 'app/logging/logger';
import { ModelType } from 'services/api/types';
import {
appSocketModelLoadCompleted,
appSocketModelLoadStarted,
socketModelLoadCompleted,
socketModelLoadStarted,
} from 'services/events/actions';
import { startAppListening } from '../..';
const MODEL_TYPES: Record<ModelType, string> = {
main: 'main',
vae: 'VAE',
lora: 'LoRA',
controlnet: 'ControlNet',
embedding: 'embedding',
};
export const addModelLoadEventListener = () => {
startAppListening({
actionCreator: socketModelLoadStarted,
effect: (action, { dispatch, getState }) => {
const log = logger('socketio');
const { base_model, model_name, model_type, submodel } =
action.payload.data;
let message = `Model load started: ${base_model}/${model_type}/${model_name}`;
if (submodel) {
message = message.concat(`/${submodel}`);
}
log.debug(action.payload, message);
// pass along the socket event as an application action
dispatch(appSocketModelLoadStarted(action.payload));
},
});
startAppListening({
actionCreator: socketModelLoadCompleted,
effect: (action, { dispatch, getState }) => {
const log = logger('socketio');
const { base_model, model_name, model_type, submodel } =
action.payload.data;
let message = `Model load complete: ${base_model}/${model_type}/${model_name}`;
if (submodel) {
message = message.concat(`/${submodel}`);
}
log.debug(action.payload, message);
// pass along the socket event as an application action
dispatch(appSocketModelLoadCompleted(action.payload));
},
});
};

View File

@ -1,28 +0,0 @@
import { log } from 'app/logging/useLogger';
import {
appSocketModelLoadCompleted,
socketModelLoadCompleted,
} from 'services/events/actions';
import { startAppListening } from '../..';
const moduleLog = log.child({ namespace: 'socketio' });
export const addModelLoadCompletedEventListener = () => {
startAppListening({
actionCreator: socketModelLoadCompleted,
effect: (action, { dispatch, getState }) => {
const { model_name, model_type, submodel } = action.payload.data;
let modelString = `${model_type} model: ${model_name}`;
if (submodel) {
modelString = modelString.concat(`, submodel: ${submodel}`);
}
moduleLog.debug(action.payload, `Model load completed (${modelString})`);
// pass along the socket event as an application action
dispatch(appSocketModelLoadCompleted(action.payload));
},
});
};

View File

@ -1,28 +0,0 @@
import { log } from 'app/logging/useLogger';
import {
appSocketModelLoadStarted,
socketModelLoadStarted,
} from 'services/events/actions';
import { startAppListening } from '../..';
const moduleLog = log.child({ namespace: 'socketio' });
export const addModelLoadStartedEventListener = () => {
startAppListening({
actionCreator: socketModelLoadStarted,
effect: (action, { dispatch, getState }) => {
const { model_name, model_type, submodel } = action.payload.data;
let modelString = `${model_type} model: ${model_name}`;
if (submodel) {
modelString = modelString.concat(`, submodel: ${submodel}`);
}
moduleLog.debug(action.payload, `Model load started (${modelString})`);
// pass along the socket event as an application action
dispatch(appSocketModelLoadStarted(action.payload));
},
});
};

View File

@ -1,17 +1,13 @@
import { startAppListening } from '../..';
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { appSocketSubscribed, socketSubscribed } from 'services/events/actions';
const moduleLog = log.child({ namespace: 'socketio' });
import { startAppListening } from '../..';
export const addSocketSubscribedEventListener = () => {
startAppListening({
actionCreator: socketSubscribed,
effect: (action, { dispatch, getState }) => {
moduleLog.debug(
action.payload,
`Subscribed (${action.payload.sessionId}))`
);
const log = logger('socketio');
log.debug(action.payload, 'Subscribed');
dispatch(appSocketSubscribed(action.payload));
},
});

View File

@ -1,20 +1,16 @@
import { startAppListening } from '../..';
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import {
appSocketUnsubscribed,
socketUnsubscribed,
} from 'services/events/actions';
const moduleLog = log.child({ namespace: 'socketio' });
import { startAppListening } from '../..';
export const addSocketUnsubscribedEventListener = () => {
startAppListening({
actionCreator: socketUnsubscribed,
effect: (action, { dispatch, getState }) => {
moduleLog.debug(
action.payload,
`Unsubscribed (${action.payload.sessionId})`
);
const log = logger('socketio');
log.debug(action.payload, 'Unsubscribed');
dispatch(appSocketUnsubscribed(action.payload));
},
});

View File

@ -1,15 +1,14 @@
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { stagingAreaImageSaved } from 'features/canvas/store/actions';
import { addToast } from 'features/system/store/systemSlice';
import { imagesApi } from 'services/api/endpoints/images';
import { startAppListening } from '..';
const moduleLog = log.child({ namespace: 'canvas' });
export const addStagingAreaImageSavedListener = () => {
startAppListening({
actionCreator: stagingAreaImageSaved,
effect: async (action, { dispatch, getState, take }) => {
const log = logger('canvas');
const { imageDTO } = action.payload;
try {

View File

@ -1,12 +1,9 @@
import { createAction } from '@reduxjs/toolkit';
import { log } from 'app/logging/useLogger';
import { buildAdHocUpscaleGraph } from 'features/nodes/util/graphBuilders/buildAdHocUpscaleGraph';
import { sessionReadyToInvoke } from 'features/system/store/actions';
import { sessionCreated } from 'services/api/thunks/session';
import { startAppListening } from '..';
const moduleLog = log.child({ namespace: 'upscale' });
export const upscaleRequested = createAction<{ image_name: string }>(
`upscale/upscaleRequested`
);

View File

@ -1,4 +1,4 @@
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { userInvoked } from 'app/store/actions';
import openBase64ImageInTab from 'common/util/openBase64ImageInTab';
import {
@ -15,8 +15,7 @@ import { imagesApi } from 'services/api/endpoints/images';
import { sessionCreated } from 'services/api/thunks/session';
import { ImageDTO } from 'services/api/types';
import { startAppListening } from '..';
const moduleLog = log.child({ namespace: 'invoke' });
import { parseify } from 'common/util/serialize';
/**
* This listener is responsible invoking the canvas. This involves a number of steps:
@ -36,13 +35,15 @@ export const addUserInvokedCanvasListener = () => {
predicate: (action): action is ReturnType<typeof userInvoked> =>
userInvoked.match(action) && action.payload === 'unifiedCanvas',
effect: async (action, { getState, dispatch, take }) => {
const log = logger('session');
const state = getState();
// Build canvas blobs
const canvasBlobsAndImageData = await getCanvasData(state);
if (!canvasBlobsAndImageData) {
moduleLog.error('Unable to create canvas data');
log.error('Unable to create canvas data');
return;
}
@ -64,7 +65,7 @@ export const addUserInvokedCanvasListener = () => {
]);
}
moduleLog.debug(`Generation mode: ${generationMode}`);
log.debug(`Generation mode: ${generationMode}`);
// Temp placeholders for the init and mask images
let canvasInitImage: ImageDTO | undefined;
@ -105,7 +106,7 @@ export const addUserInvokedCanvasListener = () => {
canvasMaskImage
);
moduleLog.debug({ graph }, `Canvas graph built`);
log.debug({ graph: parseify(graph) }, `Canvas graph built`);
// currently this action is just listened to for logging
dispatch(canvasGraphBuilt(graph));

View File

@ -1,23 +1,23 @@
import { startAppListening } from '..';
import { sessionCreated } from 'services/api/thunks/session';
import { log } from 'app/logging/useLogger';
import { imageToImageGraphBuilt } from 'features/nodes/store/actions';
import { logger } from 'app/logging/logger';
import { userInvoked } from 'app/store/actions';
import { sessionReadyToInvoke } from 'features/system/store/actions';
import { parseify } from 'common/util/serialize';
import { imageToImageGraphBuilt } from 'features/nodes/store/actions';
import { buildLinearImageToImageGraph } from 'features/nodes/util/graphBuilders/buildLinearImageToImageGraph';
const moduleLog = log.child({ namespace: 'invoke' });
import { sessionReadyToInvoke } from 'features/system/store/actions';
import { sessionCreated } from 'services/api/thunks/session';
import { startAppListening } from '..';
export const addUserInvokedImageToImageListener = () => {
startAppListening({
predicate: (action): action is ReturnType<typeof userInvoked> =>
userInvoked.match(action) && action.payload === 'img2img',
effect: async (action, { getState, dispatch, take }) => {
const log = logger('session');
const state = getState();
const graph = buildLinearImageToImageGraph(state);
dispatch(imageToImageGraphBuilt(graph));
moduleLog.debug({ data: graph }, 'Image to Image graph built');
log.debug({ graph: parseify(graph) }, 'Image to Image graph built');
dispatch(sessionCreated({ graph }));

View File

@ -1,23 +1,23 @@
import { startAppListening } from '..';
import { sessionCreated } from 'services/api/thunks/session';
import { buildNodesGraph } from 'features/nodes/util/graphBuilders/buildNodesGraph';
import { log } from 'app/logging/useLogger';
import { nodesGraphBuilt } from 'features/nodes/store/actions';
import { logger } from 'app/logging/logger';
import { userInvoked } from 'app/store/actions';
import { parseify } from 'common/util/serialize';
import { nodesGraphBuilt } from 'features/nodes/store/actions';
import { buildNodesGraph } from 'features/nodes/util/graphBuilders/buildNodesGraph';
import { sessionReadyToInvoke } from 'features/system/store/actions';
const moduleLog = log.child({ namespace: 'invoke' });
import { sessionCreated } from 'services/api/thunks/session';
import { startAppListening } from '..';
export const addUserInvokedNodesListener = () => {
startAppListening({
predicate: (action): action is ReturnType<typeof userInvoked> =>
userInvoked.match(action) && action.payload === 'nodes',
effect: async (action, { getState, dispatch, take }) => {
const log = logger('session');
const state = getState();
const graph = buildNodesGraph(state);
dispatch(nodesGraphBuilt(graph));
moduleLog.debug({ data: graph }, 'Nodes graph built');
log.debug({ graph: parseify(graph) }, 'Nodes graph built');
dispatch(sessionCreated({ graph }));

View File

@ -1,25 +1,25 @@
import { startAppListening } from '..';
import { sessionCreated } from 'services/api/thunks/session';
import { log } from 'app/logging/useLogger';
import { textToImageGraphBuilt } from 'features/nodes/store/actions';
import { logger } from 'app/logging/logger';
import { userInvoked } from 'app/store/actions';
import { sessionReadyToInvoke } from 'features/system/store/actions';
import { parseify } from 'common/util/serialize';
import { textToImageGraphBuilt } from 'features/nodes/store/actions';
import { buildLinearTextToImageGraph } from 'features/nodes/util/graphBuilders/buildLinearTextToImageGraph';
const moduleLog = log.child({ namespace: 'invoke' });
import { sessionReadyToInvoke } from 'features/system/store/actions';
import { sessionCreated } from 'services/api/thunks/session';
import { startAppListening } from '..';
export const addUserInvokedTextToImageListener = () => {
startAppListening({
predicate: (action): action is ReturnType<typeof userInvoked> =>
userInvoked.match(action) && action.payload === 'txt2img',
effect: async (action, { getState, dispatch, take }) => {
const log = logger('session');
const state = getState();
const graph = buildLinearTextToImageGraph(state);
dispatch(textToImageGraphBuilt(graph));
moduleLog.debug({ data: graph }, 'Text to Image graph built');
log.debug({ graph: parseify(graph) }, 'Text to Image graph built');
dispatch(sessionCreated({ graph }));

View File

@ -0,0 +1,4 @@
/**
* Serialize an object to JSON and back to a new object
*/
export const parseify = (obj: unknown) => JSON.parse(JSON.stringify(obj));

View File

@ -1,22 +1,22 @@
import { logger } from 'app/logging/logger';
import { RootState } from 'app/store/store';
import { getCanvasBaseLayer, getCanvasStage } from './konvaInstanceProvider';
import { isCanvasMaskLine } from '../store/canvasTypes';
import { log } from 'app/logging/useLogger';
import createMaskStage from './createMaskStage';
import { konvaNodeToImageData } from './konvaNodeToImageData';
import { getCanvasBaseLayer, getCanvasStage } from './konvaInstanceProvider';
import { konvaNodeToBlob } from './konvaNodeToBlob';
const moduleLog = log.child({ namespace: 'getCanvasDataURLs' });
import { konvaNodeToImageData } from './konvaNodeToImageData';
/**
* Gets Blob and ImageData objects for the base and mask layers
*/
export const getCanvasData = async (state: RootState) => {
const log = logger('canvas');
const canvasBaseLayer = getCanvasBaseLayer();
const canvasStage = getCanvasStage();
if (!canvasBaseLayer || !canvasStage) {
moduleLog.error('Unable to find canvas / stage');
log.error('Unable to find canvas / stage');
return;
}

View File

@ -1,4 +1,3 @@
import { log } from 'app/logging/useLogger';
import { RootState } from 'app/store/store';
import { NonNullableGraph } from 'features/nodes/types/types';
import { ImageDTO } from 'services/api/types';
@ -6,8 +5,6 @@ import { buildCanvasImageToImageGraph } from './buildCanvasImageToImageGraph';
import { buildCanvasInpaintGraph } from './buildCanvasInpaintGraph';
import { buildCanvasTextToImageGraph } from './buildCanvasTextToImageGraph';
const moduleLog = log.child({ namespace: 'nodes' });
export const buildCanvasGraph = (
state: RootState,
generationMode: 'txt2img' | 'img2img' | 'inpaint' | 'outpaint',

View File

@ -1,4 +1,4 @@
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { RootState } from 'app/store/store';
import { NonNullableGraph } from 'features/nodes/types/types';
import { initialGenerationState } from 'features/parameters/store/generationSlice';
@ -25,8 +25,6 @@ import {
RESIZE,
} from './constants';
const moduleLog = log.child({ namespace: 'nodes' });
/**
* Builds the Canvas tab's Image to Image graph.
*/
@ -34,6 +32,7 @@ export const buildCanvasImageToImageGraph = (
state: RootState,
initialImage: ImageDTO
): NonNullableGraph => {
const log = logger('nodes');
const {
positivePrompt,
negativePrompt,
@ -53,7 +52,7 @@ export const buildCanvasImageToImageGraph = (
const { shouldAutoSave } = state.canvas;
if (!model) {
moduleLog.error('No model found in state');
log.error('No model found in state');
throw new Error('No model found in state');
}

View File

@ -1,4 +1,4 @@
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { RootState } from 'app/store/store';
import { NonNullableGraph } from 'features/nodes/types/types';
import {
@ -21,8 +21,6 @@ import {
RANGE_OF_SIZE,
} from './constants';
const moduleLog = log.child({ namespace: 'nodes' });
/**
* Builds the Canvas tab's Inpaint graph.
*/
@ -31,6 +29,7 @@ export const buildCanvasInpaintGraph = (
canvasInitImage: ImageDTO,
canvasMaskImage: ImageDTO
): NonNullableGraph => {
const log = logger('nodes');
const {
positivePrompt,
negativePrompt,
@ -53,7 +52,7 @@ export const buildCanvasInpaintGraph = (
} = state.generation;
if (!model) {
moduleLog.error('No model found in state');
log.error('No model found in state');
throw new Error('No model found in state');
}

View File

@ -1,4 +1,4 @@
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { RootState } from 'app/store/store';
import { NonNullableGraph } from 'features/nodes/types/types';
import { initialGenerationState } from 'features/parameters/store/generationSlice';
@ -18,14 +18,13 @@ import {
TEXT_TO_LATENTS,
} from './constants';
const moduleLog = log.child({ namespace: 'nodes' });
/**
* Builds the Canvas tab's Text to Image graph.
*/
export const buildCanvasTextToImageGraph = (
state: RootState
): NonNullableGraph => {
const log = logger('nodes');
const {
positivePrompt,
negativePrompt,
@ -44,7 +43,7 @@ export const buildCanvasTextToImageGraph = (
const { shouldAutoSave } = state.canvas;
if (!model) {
moduleLog.error('No model found in state');
log.error('No model found in state');
throw new Error('No model found in state');
}

View File

@ -1,4 +1,4 @@
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { RootState } from 'app/store/store';
import { NonNullableGraph } from 'features/nodes/types/types';
import { initialGenerationState } from 'features/parameters/store/generationSlice';
@ -24,14 +24,13 @@ import {
RESIZE,
} from './constants';
const moduleLog = log.child({ namespace: 'nodes' });
/**
* Builds the Image to Image tab graph.
*/
export const buildLinearImageToImageGraph = (
state: RootState
): NonNullableGraph => {
const log = logger('nodes');
const {
positivePrompt,
negativePrompt,
@ -69,12 +68,12 @@ export const buildLinearImageToImageGraph = (
*/
if (!initialImage) {
moduleLog.error('No initial image found in state');
log.error('No initial image found in state');
throw new Error('No initial image found in state');
}
if (!model) {
moduleLog.error('No model found in state');
log.error('No model found in state');
throw new Error('No model found in state');
}

View File

@ -1,4 +1,4 @@
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { RootState } from 'app/store/store';
import { NonNullableGraph } from 'features/nodes/types/types';
import { initialGenerationState } from 'features/parameters/store/generationSlice';
@ -18,11 +18,10 @@ import {
TEXT_TO_LATENTS,
} from './constants';
const moduleLog = log.child({ namespace: 'nodes' });
export const buildLinearTextToImageGraph = (
state: RootState
): NonNullableGraph => {
const log = logger('nodes');
const {
positivePrompt,
negativePrompt,
@ -42,7 +41,7 @@ export const buildLinearTextToImageGraph = (
: initialGenerationState.shouldUseCpuNoise;
if (!model) {
moduleLog.error('No model found in state');
log.error('No model found in state');
throw new Error('No model found in state');
}

View File

@ -1,12 +1,11 @@
import { log } from 'app/logging/useLogger';
import { logger } from 'app/logging/logger';
import { zControlNetModel } from 'features/parameters/types/parameterSchemas';
import { ControlNetModelField } from 'services/api/types';
const moduleLog = log.child({ module: 'models' });
export const modelIdToControlNetModelParam = (
controlNetModelId: string
): ControlNetModelField | undefined => {
const log = logger('models');
const [base_model, model_type, model_name] = controlNetModelId.split('/');
const result = zControlNetModel.safeParse({
@ -15,7 +14,7 @@ export const modelIdToControlNetModelParam = (
});
if (!result.success) {
moduleLog.error(
log.error(
{
controlNetModelId,
errors: result.error.format(),

View File

@ -1,11 +1,11 @@
import { logger } from 'app/logging/logger';
import { LoRAModelParam, zLoRAModel } from '../types/parameterSchemas';
import { log } from 'app/logging/useLogger';
const moduleLog = log.child({ module: 'models' });
export const modelIdToLoRAModelParam = (
loraModelId: string
): LoRAModelParam | undefined => {
const log = logger('models');
const [base_model, model_type, model_name] = loraModelId.split('/');
const result = zLoRAModel.safeParse({
@ -14,7 +14,7 @@ export const modelIdToLoRAModelParam = (
});
if (!result.success) {
moduleLog.error(
log.error(
{
loraModelId,
errors: result.error.format(),

View File

@ -1,14 +1,13 @@
import { logger } from 'app/logging/logger';
import {
MainModelParam,
zMainModel,
} from 'features/parameters/types/parameterSchemas';
import { log } from 'app/logging/useLogger';
const moduleLog = log.child({ module: 'models' });
export const modelIdToMainModelParam = (
mainModelId: string
): MainModelParam | undefined => {
const log = logger('models');
const [base_model, model_type, model_name] = mainModelId.split('/');
const result = zMainModel.safeParse({
@ -17,7 +16,7 @@ export const modelIdToMainModelParam = (
});
if (!result.success) {
moduleLog.error(
log.error(
{
mainModelId,
errors: result.error.format(),

View File

@ -1,11 +1,10 @@
import { logger } from 'app/logging/logger';
import { VaeModelParam, zVaeModel } from '../types/parameterSchemas';
import { log } from 'app/logging/useLogger';
const moduleLog = log.child({ module: 'models' });
export const modelIdToVAEModelParam = (
vaeModelId: string
): VaeModelParam | undefined => {
const log = logger('models');
const [base_model, model_type, model_name] = vaeModelId.split('/');
const result = zVaeModel.safeParse({
@ -14,7 +13,7 @@ export const modelIdToVAEModelParam = (
});
if (!result.success) {
moduleLog.error(
log.error(
{
vaeModelId,
errors: result.error.format(),

View File

@ -12,7 +12,7 @@ import {
useDisclosure,
} from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import { VALID_LOG_LEVELS } from 'app/logging/useLogger';
import { VALID_LOG_LEVELS } from 'app/logging/logger';
import { LOCALSTORAGE_KEYS, LOCALSTORAGE_PREFIX } from 'app/store/constants';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAIButton from 'common/components/IAIButton';

View File

@ -1,7 +1,7 @@
import { UseToastOptions } from '@chakra-ui/react';
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
import { InvokeLogLevel } from 'app/logging/useLogger';
import { InvokeLogLevel } from 'app/logging/logger';
import { userInvoked } from 'app/store/actions';
import { nodeTemplatesBuilt } from 'features/nodes/store/nodesSlice';
import { t } from 'i18next';

View File

@ -1,7 +1,5 @@
import { createAsyncThunk } from '@reduxjs/toolkit';
import { log } from 'app/logging/useLogger';
const schemaLog = log.child({ namespace: 'schema' });
import { logger } from 'app/logging/logger';
function getCircularReplacer() {
const ancestors: Record<string, any>[] = [];
@ -26,11 +24,12 @@ function getCircularReplacer() {
export const receivedOpenAPISchema = createAsyncThunk(
'nodes/receivedOpenAPISchema',
async (_, { dispatch, rejectWithValue }) => {
const log = logger('system');
try {
const response = await fetch(`openapi.json`);
const openAPISchema = await response.json();
schemaLog.info({ openAPISchema }, 'Received OpenAPI schema');
log.info({ openAPISchema }, 'Received OpenAPI schema');
const schemaJSON = JSON.parse(
JSON.stringify(openAPISchema, getCircularReplacer())

View File

@ -1,13 +1,10 @@
import { createAppAsyncThunk } from 'app/store/storeUtils';
import { log } from 'app/logging/useLogger';
import { isObject } from 'lodash-es';
import { isAnyOf } from '@reduxjs/toolkit';
import { paths } from 'services/api/schema';
import { createAppAsyncThunk } from 'app/store/storeUtils';
import { isObject } from 'lodash-es';
import { $client } from 'services/api/client';
import { paths } from 'services/api/schema';
import { O } from 'ts-toolbelt';
const sessionLog = log.child({ namespace: 'session' });
type CreateSessionArg = {
graph: NonNullable<
paths['/api/v1/sessions/']['post']['requestBody']

View File

@ -9,11 +9,6 @@ import {
ModelLoadStartedEvent,
} from 'services/events/types';
// Common socket action payload data
type BaseSocketPayload = {
timestamp: string;
};
// Create actions for each socket
// Middleware and redux can then respond to them as needed
@ -22,30 +17,24 @@ type BaseSocketPayload = {
*
* Do not use. Only for use in middleware.
*/
export const socketConnected = createAction<BaseSocketPayload>(
'socket/socketConnected'
);
export const socketConnected = createAction('socket/socketConnected');
/**
* App-level Socket.IO Connected
*/
export const appSocketConnected = createAction<BaseSocketPayload>(
'socket/appSocketConnected'
);
export const appSocketConnected = createAction('socket/appSocketConnected');
/**
* Socket.IO Disconnect
*
* Do not use. Only for use in middleware.
*/
export const socketDisconnected = createAction<BaseSocketPayload>(
'socket/socketDisconnected'
);
export const socketDisconnected = createAction('socket/socketDisconnected');
/**
* App-level Socket.IO Disconnected
*/
export const appSocketDisconnected = createAction<BaseSocketPayload>(
export const appSocketDisconnected = createAction(
'socket/appSocketDisconnected'
);
@ -54,145 +43,141 @@ export const appSocketDisconnected = createAction<BaseSocketPayload>(
*
* Do not use. Only for use in middleware.
*/
export const socketSubscribed = createAction<
BaseSocketPayload & { sessionId: string; boardId: string | undefined }
>('socket/socketSubscribed');
export const socketSubscribed = createAction<{
sessionId: string;
}>('socket/socketSubscribed');
/**
* App-level Socket.IO Subscribed
*/
export const appSocketSubscribed = createAction<
BaseSocketPayload & { sessionId: string; boardId: string | undefined }
>('socket/appSocketSubscribed');
export const appSocketSubscribed = createAction<{
sessionId: string;
}>('socket/appSocketSubscribed');
/**
* Socket.IO Unsubscribed
*
* Do not use. Only for use in middleware.
*/
export const socketUnsubscribed = createAction<
BaseSocketPayload & { sessionId: string }
>('socket/socketUnsubscribed');
export const socketUnsubscribed = createAction<{ sessionId: string }>(
'socket/socketUnsubscribed'
);
/**
* App-level Socket.IO Unsubscribed
*/
export const appSocketUnsubscribed = createAction<
BaseSocketPayload & { sessionId: string }
>('socket/appSocketUnsubscribed');
export const appSocketUnsubscribed = createAction<{ sessionId: string }>(
'socket/appSocketUnsubscribed'
);
/**
* Socket.IO Invocation Started
*
* Do not use. Only for use in middleware.
*/
export const socketInvocationStarted = createAction<
BaseSocketPayload & { data: InvocationStartedEvent }
>('socket/socketInvocationStarted');
export const socketInvocationStarted = createAction<{
data: InvocationStartedEvent;
}>('socket/socketInvocationStarted');
/**
* App-level Socket.IO Invocation Started
*/
export const appSocketInvocationStarted = createAction<
BaseSocketPayload & { data: InvocationStartedEvent }
>('socket/appSocketInvocationStarted');
export const appSocketInvocationStarted = createAction<{
data: InvocationStartedEvent;
}>('socket/appSocketInvocationStarted');
/**
* Socket.IO Invocation Complete
*
* Do not use. Only for use in middleware.
*/
export const socketInvocationComplete = createAction<
BaseSocketPayload & {
export const socketInvocationComplete = createAction<{
data: InvocationCompleteEvent;
}
>('socket/socketInvocationComplete');
}>('socket/socketInvocationComplete');
/**
* App-level Socket.IO Invocation Complete
*/
export const appSocketInvocationComplete = createAction<
BaseSocketPayload & {
export const appSocketInvocationComplete = createAction<{
data: InvocationCompleteEvent;
}
>('socket/appSocketInvocationComplete');
}>('socket/appSocketInvocationComplete');
/**
* Socket.IO Invocation Error
*
* Do not use. Only for use in middleware.
*/
export const socketInvocationError = createAction<
BaseSocketPayload & { data: InvocationErrorEvent }
>('socket/socketInvocationError');
export const socketInvocationError = createAction<{
data: InvocationErrorEvent;
}>('socket/socketInvocationError');
/**
* App-level Socket.IO Invocation Error
*/
export const appSocketInvocationError = createAction<
BaseSocketPayload & { data: InvocationErrorEvent }
>('socket/appSocketInvocationError');
export const appSocketInvocationError = createAction<{
data: InvocationErrorEvent;
}>('socket/appSocketInvocationError');
/**
* Socket.IO Graph Execution State Complete
*
* Do not use. Only for use in middleware.
*/
export const socketGraphExecutionStateComplete = createAction<
BaseSocketPayload & { data: GraphExecutionStateCompleteEvent }
>('socket/socketGraphExecutionStateComplete');
export const socketGraphExecutionStateComplete = createAction<{
data: GraphExecutionStateCompleteEvent;
}>('socket/socketGraphExecutionStateComplete');
/**
* App-level Socket.IO Graph Execution State Complete
*/
export const appSocketGraphExecutionStateComplete = createAction<
BaseSocketPayload & { data: GraphExecutionStateCompleteEvent }
>('socket/appSocketGraphExecutionStateComplete');
export const appSocketGraphExecutionStateComplete = createAction<{
data: GraphExecutionStateCompleteEvent;
}>('socket/appSocketGraphExecutionStateComplete');
/**
* Socket.IO Generator Progress
*
* Do not use. Only for use in middleware.
*/
export const socketGeneratorProgress = createAction<
BaseSocketPayload & { data: GeneratorProgressEvent }
>('socket/socketGeneratorProgress');
export const socketGeneratorProgress = createAction<{
data: GeneratorProgressEvent;
}>('socket/socketGeneratorProgress');
/**
* App-level Socket.IO Generator Progress
*/
export const appSocketGeneratorProgress = createAction<
BaseSocketPayload & { data: GeneratorProgressEvent }
>('socket/appSocketGeneratorProgress');
export const appSocketGeneratorProgress = createAction<{
data: GeneratorProgressEvent;
}>('socket/appSocketGeneratorProgress');
/**
* Socket.IO Model Load Started
*
* Do not use. Only for use in middleware.
*/
export const socketModelLoadStarted = createAction<
BaseSocketPayload & { data: ModelLoadStartedEvent }
>('socket/socketModelLoadStarted');
export const socketModelLoadStarted = createAction<{
data: ModelLoadStartedEvent;
}>('socket/socketModelLoadStarted');
/**
* App-level Model Load Started
*/
export const appSocketModelLoadStarted = createAction<
BaseSocketPayload & { data: ModelLoadStartedEvent }
>('socket/appSocketModelLoadStarted');
export const appSocketModelLoadStarted = createAction<{
data: ModelLoadStartedEvent;
}>('socket/appSocketModelLoadStarted');
/**
* Socket.IO Model Load Started
*
* Do not use. Only for use in middleware.
*/
export const socketModelLoadCompleted = createAction<
BaseSocketPayload & { data: ModelLoadCompletedEvent }
>('socket/socketModelLoadCompleted');
export const socketModelLoadCompleted = createAction<{
data: ModelLoadCompletedEvent;
}>('socket/socketModelLoadCompleted');
/**
* App-level Model Load Completed
*/
export const appSocketModelLoadCompleted = createAction<
BaseSocketPayload & { data: ModelLoadCompletedEvent }
>('socket/appSocketModelLoadCompleted');
export const appSocketModelLoadCompleted = createAction<{
data: ModelLoadCompletedEvent;
}>('socket/appSocketModelLoadCompleted');

View File

@ -1,20 +1,14 @@
import { Middleware, MiddlewareAPI } from '@reduxjs/toolkit';
import { Socket, io } from 'socket.io-client';
import { AppThunkDispatch, RootState } from 'app/store/store';
import { getTimestamp } from 'common/util/getTimestamp';
import { $authToken, $baseUrl } from 'services/api/client';
import { sessionCreated } from 'services/api/thunks/session';
import {
ClientToServerEvents,
ServerToClientEvents,
} from 'services/events/types';
import { socketSubscribed, socketUnsubscribed } from './actions';
// import { OpenAPI } from 'services/api/types';
import { log } from 'app/logging/useLogger';
import { $authToken, $baseUrl } from 'services/api/client';
import { setEventListeners } from 'services/events/util/setEventListeners';
const socketioLog = log.child({ namespace: 'socketio' });
import { Socket, io } from 'socket.io-client';
import { socketSubscribed, socketUnsubscribed } from './actions';
export const socketMiddleware = () => {
let areListenersSet = false;
@ -58,7 +52,7 @@ export const socketMiddleware = () => {
// Set listeners for `connect` and `disconnect` events once
// Must happen in middleware to get access to `dispatch`
if (!areListenersSet) {
setEventListeners({ storeApi, socket, log: socketioLog });
setEventListeners({ storeApi, socket });
areListenersSet = true;
@ -77,7 +71,6 @@ export const socketMiddleware = () => {
dispatch(
socketUnsubscribed({
sessionId: oldSessionId,
timestamp: getTimestamp(),
})
);
}
@ -87,8 +80,6 @@ export const socketMiddleware = () => {
dispatch(
socketSubscribed({
sessionId: sessionId,
timestamp: getTimestamp(),
boardId: getState().gallery.selectedBoardId,
})
);
}

View File

@ -1,42 +1,40 @@
import { MiddlewareAPI } from '@reduxjs/toolkit';
import { logger } from 'app/logging/logger';
import { AppDispatch, RootState } from 'app/store/store';
import { getTimestamp } from 'common/util/getTimestamp';
import { Socket } from 'socket.io-client';
import { makeToast } from '../../../app/components/Toaster';
import { addToast } from '../../../features/system/store/systemSlice';
import {
socketConnected,
socketDisconnected,
socketGeneratorProgress,
socketGraphExecutionStateComplete,
socketInvocationComplete,
socketInvocationError,
socketInvocationStarted,
socketConnected,
socketDisconnected,
socketSubscribed,
socketModelLoadStarted,
socketModelLoadCompleted,
socketModelLoadStarted,
socketSubscribed,
} from '../actions';
import { ClientToServerEvents, ServerToClientEvents } from '../types';
import { Logger } from 'roarr';
import { JsonObject } from 'roarr/dist/types';
import { makeToast } from '../../../app/components/Toaster';
import { addToast } from '../../../features/system/store/systemSlice';
type SetEventListenersArg = {
socket: Socket<ServerToClientEvents, ClientToServerEvents>;
storeApi: MiddlewareAPI<AppDispatch, RootState>;
log: Logger<JsonObject>;
};
export const setEventListeners = (arg: SetEventListenersArg) => {
const { socket, storeApi, log } = arg;
const { socket, storeApi } = arg;
const { dispatch, getState } = storeApi;
/**
* Connect
*/
socket.on('connect', () => {
const log = logger('socketio');
log.debug('Connected');
dispatch(socketConnected({ timestamp: getTimestamp() }));
dispatch(socketConnected());
const { sessionId } = getState().system;
@ -45,8 +43,6 @@ export const setEventListeners = (arg: SetEventListenersArg) => {
dispatch(
socketSubscribed({
sessionId,
timestamp: getTimestamp(),
boardId: getState().gallery.selectedBoardId,
})
);
}
@ -73,28 +69,28 @@ export const setEventListeners = (arg: SetEventListenersArg) => {
* Disconnect
*/
socket.on('disconnect', () => {
dispatch(socketDisconnected({ timestamp: getTimestamp() }));
dispatch(socketDisconnected());
});
/**
* Invocation started
*/
socket.on('invocation_started', (data) => {
dispatch(socketInvocationStarted({ data, timestamp: getTimestamp() }));
dispatch(socketInvocationStarted({ data }));
});
/**
* Generator progress
*/
socket.on('generator_progress', (data) => {
dispatch(socketGeneratorProgress({ data, timestamp: getTimestamp() }));
dispatch(socketGeneratorProgress({ data }));
});
/**
* Invocation error
*/
socket.on('invocation_error', (data) => {
dispatch(socketInvocationError({ data, timestamp: getTimestamp() }));
dispatch(socketInvocationError({ data }));
});
/**
@ -104,7 +100,6 @@ export const setEventListeners = (arg: SetEventListenersArg) => {
dispatch(
socketInvocationComplete({
data,
timestamp: getTimestamp(),
})
);
});
@ -116,7 +111,6 @@ export const setEventListeners = (arg: SetEventListenersArg) => {
dispatch(
socketGraphExecutionStateComplete({
data,
timestamp: getTimestamp(),
})
);
});
@ -128,7 +122,6 @@ export const setEventListeners = (arg: SetEventListenersArg) => {
dispatch(
socketModelLoadStarted({
data,
timestamp: getTimestamp(),
})
);
});
@ -140,7 +133,6 @@ export const setEventListeners = (arg: SetEventListenersArg) => {
dispatch(
socketModelLoadCompleted({
data,
timestamp: getTimestamp(),
})
);
});

View File

@ -1511,6 +1511,11 @@
resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz#c3ec604a0b54b9a9b87e9735dfc59e1a5da6a5fb"
integrity sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==
"@nanostores/react@^0.7.1":
version "0.7.1"
resolved "https://registry.yarnpkg.com/@nanostores/react/-/react-0.7.1.tgz#e0446f5cacc9fa53448c454f5d00ddb0f906a37a"
integrity sha512-EXQg9N4MdI4eJQz/AZLIx3hxQ6BuBmV4Q55bCd5YCSgEOAW7tGTsIZxpRXxvxLXzflNvHTBvfrDNY38TlSVBkQ==
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"