fix(ui): add additional socket event layer to gate handling socket events

Some socket events should not be handled by the slice reducers. For example generation progress should not be handled for a canceled session.

Added another layer of socket actions.

Example:
- `socketGeneratorProgress` is dispatched when the actual socket event is received
- Listener middleware exclusively handles this event and determines if the application should also handle it
- If so, it dispatches `appSocketGeneratorProgress`, which the slices can handle

Needed to fix issues related to canceling invocations.
This commit is contained in:
psychedelicious 2023-05-29 17:18:13 +10:00 committed by Kent Keirsey
parent 6764b2a854
commit e4705d5ce7
13 changed files with 249 additions and 88 deletions

View File

@ -26,15 +26,15 @@ import { addCanvasSavedToGalleryListener } from './listeners/canvasSavedToGaller
import { addCanvasDownloadedAsImageListener } from './listeners/canvasDownloadedAsImage'; import { addCanvasDownloadedAsImageListener } from './listeners/canvasDownloadedAsImage';
import { addCanvasCopiedToClipboardListener } from './listeners/canvasCopiedToClipboard'; import { addCanvasCopiedToClipboardListener } from './listeners/canvasCopiedToClipboard';
import { addCanvasMergedListener } from './listeners/canvasMerged'; import { addCanvasMergedListener } from './listeners/canvasMerged';
import { addGeneratorProgressListener } from './listeners/socketio/generatorProgress'; import { addGeneratorProgressEventListener as addGeneratorProgressListener } from './listeners/socketio/socketGeneratorProgress';
import { addGraphExecutionStateCompleteListener } from './listeners/socketio/graphExecutionStateComplete'; import { addGraphExecutionStateCompleteEventListener as addGraphExecutionStateCompleteListener } from './listeners/socketio/socketGraphExecutionStateComplete';
import { addInvocationCompleteListener } from './listeners/socketio/invocationComplete'; import { addInvocationCompleteEventListener as addInvocationCompleteListener } from './listeners/socketio/socketInvocationComplete';
import { addInvocationErrorListener } from './listeners/socketio/invocationError'; import { addInvocationErrorEventListener as addInvocationErrorListener } from './listeners/socketio/socketInvocationError';
import { addInvocationStartedListener } from './listeners/socketio/invocationStarted'; import { addInvocationStartedEventListener as addInvocationStartedListener } from './listeners/socketio/socketInvocationStarted';
import { addSocketConnectedListener } from './listeners/socketio/socketConnected'; import { addSocketConnectedEventListener as addSocketConnectedListener } from './listeners/socketio/socketConnected';
import { addSocketDisconnectedListener } from './listeners/socketio/socketDisconnected'; import { addSocketDisconnectedEventListener as addSocketDisconnectedListener } from './listeners/socketio/socketDisconnected';
import { addSocketSubscribedListener } from './listeners/socketio/socketSubscribed'; import { addSocketSubscribedEventListener as addSocketSubscribedListener } from './listeners/socketio/socketSubscribed';
import { addSocketUnsubscribedListener } from './listeners/socketio/socketUnsubscribed'; import { addSocketUnsubscribedEventListener as addSocketUnsubscribedListener } from './listeners/socketio/socketUnsubscribed';
import { addSessionReadyToInvokeListener } from './listeners/sessionReadyToInvoke'; import { addSessionReadyToInvokeListener } from './listeners/sessionReadyToInvoke';
import { import {
addImageMetadataReceivedFulfilledListener, addImageMetadataReceivedFulfilledListener,
@ -126,7 +126,19 @@ addCanvasCopiedToClipboardListener();
addCanvasMergedListener(); addCanvasMergedListener();
addStagingAreaImageSavedListener(); addStagingAreaImageSavedListener();
// socketio /**
* Socket.IO Events - these handle SIO events directly and pass on internal application actions.
* We don't handle SIO events in slices via `extraReducers` because some of these events shouldn't
* actually be handled at all.
*
* For example, we don't want to respond to progress events for canceled sessions. To avoid
* duplicating the logic to determine if an event should be responded to, we handle all of that
* "is this session canceled?" logic in these listeners.
*
* The `socketGeneratorProgress` listener will then only dispatch the `appSocketGeneratorProgress`
* action if it should be handled by the rest of the application. It is this `appSocketGeneratorProgress`
* action that is handled by reducers in slices.
*/
addGeneratorProgressListener(); addGeneratorProgressListener();
addGraphExecutionStateCompleteListener(); addGraphExecutionStateCompleteListener();
addInvocationCompleteListener(); addInvocationCompleteListener();

View File

@ -1,13 +1,13 @@
import { startAppListening } from '../..'; import { startAppListening } from '../..';
import { log } from 'app/logging/useLogger'; import { log } from 'app/logging/useLogger';
import { socketConnected } from 'services/events/actions'; import { appSocketConnected, socketConnected } from 'services/events/actions';
import { receivedPageOfImages } from 'services/thunks/image'; import { receivedPageOfImages } from 'services/thunks/image';
import { receivedModels } from 'services/thunks/model'; import { receivedModels } from 'services/thunks/model';
import { receivedOpenAPISchema } from 'services/thunks/schema'; import { receivedOpenAPISchema } from 'services/thunks/schema';
const moduleLog = log.child({ namespace: 'socketio' }); const moduleLog = log.child({ namespace: 'socketio' });
export const addSocketConnectedListener = () => { export const addSocketConnectedEventListener = () => {
startAppListening({ startAppListening({
actionCreator: socketConnected, actionCreator: socketConnected,
effect: (action, { dispatch, getState }) => { effect: (action, { dispatch, getState }) => {
@ -30,6 +30,9 @@ export const addSocketConnectedListener = () => {
if (!nodes.schema && !disabledTabs.includes('nodes')) { if (!nodes.schema && !disabledTabs.includes('nodes')) {
dispatch(receivedOpenAPISchema()); dispatch(receivedOpenAPISchema());
} }
// pass along the socket event as an application action
dispatch(appSocketConnected(action.payload));
}, },
}); });
}; };

View File

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

View File

@ -1,12 +1,15 @@
import { startAppListening } from '../..'; import { startAppListening } from '../..';
import { log } from 'app/logging/useLogger'; import { log } from 'app/logging/useLogger';
import { generatorProgress } from 'services/events/actions'; import {
appSocketGeneratorProgress,
socketGeneratorProgress,
} from 'services/events/actions';
const moduleLog = log.child({ namespace: 'socketio' }); const moduleLog = log.child({ namespace: 'socketio' });
export const addGeneratorProgressListener = () => { export const addGeneratorProgressEventListener = () => {
startAppListening({ startAppListening({
actionCreator: generatorProgress, actionCreator: socketGeneratorProgress,
effect: (action, { dispatch, getState }) => { effect: (action, { dispatch, getState }) => {
if ( if (
getState().system.canceledSession === getState().system.canceledSession ===
@ -23,6 +26,9 @@ export const addGeneratorProgressListener = () => {
action.payload, action.payload,
`Generator progress (${action.payload.data.node.type})` `Generator progress (${action.payload.data.node.type})`
); );
// pass along the socket event as an application action
dispatch(appSocketGeneratorProgress(action.payload));
}, },
}); });
}; };

View File

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

View File

@ -1,7 +1,10 @@
import { addImageToStagingArea } from 'features/canvas/store/canvasSlice'; import { addImageToStagingArea } from 'features/canvas/store/canvasSlice';
import { startAppListening } from '../..'; import { startAppListening } from '../..';
import { log } from 'app/logging/useLogger'; import { log } from 'app/logging/useLogger';
import { invocationComplete } from 'services/events/actions'; import {
appSocketInvocationComplete,
socketInvocationComplete,
} from 'services/events/actions';
import { imageMetadataReceived } from 'services/thunks/image'; import { imageMetadataReceived } from 'services/thunks/image';
import { sessionCanceled } from 'services/thunks/session'; import { sessionCanceled } from 'services/thunks/session';
import { isImageOutput } from 'services/types/guards'; import { isImageOutput } from 'services/types/guards';
@ -10,9 +13,9 @@ import { progressImageSet } from 'features/system/store/systemSlice';
const moduleLog = log.child({ namespace: 'socketio' }); const moduleLog = log.child({ namespace: 'socketio' });
const nodeDenylist = ['dataURL_image']; const nodeDenylist = ['dataURL_image'];
export const addInvocationCompleteListener = () => { export const addInvocationCompleteEventListener = () => {
startAppListening({ startAppListening({
actionCreator: invocationComplete, actionCreator: socketInvocationComplete,
effect: async (action, { dispatch, getState, take }) => { effect: async (action, { dispatch, getState, take }) => {
moduleLog.debug( moduleLog.debug(
action.payload, action.payload,
@ -57,6 +60,8 @@ export const addInvocationCompleteListener = () => {
dispatch(progressImageSet(null)); dispatch(progressImageSet(null));
} }
// pass along the socket event as an application action
dispatch(appSocketInvocationComplete(action.payload));
}, },
}); });
}; };

View File

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

View File

@ -1,12 +1,15 @@
import { startAppListening } from '../..'; import { startAppListening } from '../..';
import { log } from 'app/logging/useLogger'; import { log } from 'app/logging/useLogger';
import { invocationStarted } from 'services/events/actions'; import {
appSocketInvocationStarted,
socketInvocationStarted,
} from 'services/events/actions';
const moduleLog = log.child({ namespace: 'socketio' }); const moduleLog = log.child({ namespace: 'socketio' });
export const addInvocationStartedListener = () => { export const addInvocationStartedEventListener = () => {
startAppListening({ startAppListening({
actionCreator: invocationStarted, actionCreator: socketInvocationStarted,
effect: (action, { dispatch, getState }) => { effect: (action, { dispatch, getState }) => {
if ( if (
getState().system.canceledSession === getState().system.canceledSession ===
@ -23,6 +26,7 @@ export const addInvocationStartedListener = () => {
action.payload, action.payload,
`Invocation started (${action.payload.data.node.type})` `Invocation started (${action.payload.data.node.type})`
); );
dispatch(appSocketInvocationStarted(action.payload));
}, },
}); });
}; };

View File

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

View File

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

View File

@ -2,17 +2,6 @@ import { UseToastOptions } from '@chakra-ui/react';
import { PayloadAction, isAnyOf } from '@reduxjs/toolkit'; import { PayloadAction, isAnyOf } from '@reduxjs/toolkit';
import { createSlice } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit';
import * as InvokeAI from 'app/types/invokeai'; import * as InvokeAI from 'app/types/invokeai';
import {
generatorProgress,
graphExecutionStateComplete,
invocationComplete,
invocationError,
invocationStarted,
socketConnected,
socketDisconnected,
socketSubscribed,
socketUnsubscribed,
} from 'services/events/actions';
import { ProgressImage } from 'services/events/types'; import { ProgressImage } from 'services/events/types';
import { makeToast } from '../../../app/components/Toaster'; import { makeToast } from '../../../app/components/Toaster';
@ -30,6 +19,17 @@ import { t } from 'i18next';
import { userInvoked } from 'app/store/actions'; import { userInvoked } from 'app/store/actions';
import { LANGUAGES } from '../components/LanguagePicker'; import { LANGUAGES } from '../components/LanguagePicker';
import { imageUploaded } from 'services/thunks/image'; import { imageUploaded } from 'services/thunks/image';
import {
appSocketConnected,
appSocketDisconnected,
appSocketGeneratorProgress,
appSocketGraphExecutionStateComplete,
appSocketInvocationComplete,
appSocketInvocationError,
appSocketInvocationStarted,
appSocketSubscribed,
appSocketUnsubscribed,
} from 'services/events/actions';
export type CancelStrategy = 'immediate' | 'scheduled'; export type CancelStrategy = 'immediate' | 'scheduled';
@ -227,7 +227,7 @@ export const systemSlice = createSlice({
/** /**
* Socket Subscribed * Socket Subscribed
*/ */
builder.addCase(socketSubscribed, (state, action) => { builder.addCase(appSocketSubscribed, (state, action) => {
state.sessionId = action.payload.sessionId; state.sessionId = action.payload.sessionId;
state.canceledSession = ''; state.canceledSession = '';
}); });
@ -235,14 +235,14 @@ export const systemSlice = createSlice({
/** /**
* Socket Unsubscribed * Socket Unsubscribed
*/ */
builder.addCase(socketUnsubscribed, (state) => { builder.addCase(appSocketUnsubscribed, (state) => {
state.sessionId = null; state.sessionId = null;
}); });
/** /**
* Socket Connected * Socket Connected
*/ */
builder.addCase(socketConnected, (state) => { builder.addCase(appSocketConnected, (state) => {
state.isConnected = true; state.isConnected = true;
state.isCancelable = true; state.isCancelable = true;
state.isProcessing = false; state.isProcessing = false;
@ -257,7 +257,7 @@ export const systemSlice = createSlice({
/** /**
* Socket Disconnected * Socket Disconnected
*/ */
builder.addCase(socketDisconnected, (state) => { builder.addCase(appSocketDisconnected, (state) => {
state.isConnected = false; state.isConnected = false;
state.isProcessing = false; state.isProcessing = false;
state.isCancelable = true; state.isCancelable = true;
@ -272,7 +272,7 @@ export const systemSlice = createSlice({
/** /**
* Invocation Started * Invocation Started
*/ */
builder.addCase(invocationStarted, (state) => { builder.addCase(appSocketInvocationStarted, (state) => {
state.isCancelable = true; state.isCancelable = true;
state.isProcessing = true; state.isProcessing = true;
state.currentStatusHasSteps = false; state.currentStatusHasSteps = false;
@ -286,7 +286,7 @@ export const systemSlice = createSlice({
/** /**
* Generator Progress * Generator Progress
*/ */
builder.addCase(generatorProgress, (state, action) => { builder.addCase(appSocketGeneratorProgress, (state, action) => {
const { step, total_steps, progress_image } = action.payload.data; const { step, total_steps, progress_image } = action.payload.data;
state.isProcessing = true; state.isProcessing = true;
@ -303,7 +303,7 @@ export const systemSlice = createSlice({
/** /**
* Invocation Complete * Invocation Complete
*/ */
builder.addCase(invocationComplete, (state, action) => { builder.addCase(appSocketInvocationComplete, (state, action) => {
const { data } = action.payload; const { data } = action.payload;
// state.currentIteration = 0; // state.currentIteration = 0;
@ -322,7 +322,7 @@ export const systemSlice = createSlice({
/** /**
* Invocation Error * Invocation Error
*/ */
builder.addCase(invocationError, (state) => { builder.addCase(appSocketInvocationError, (state) => {
state.isProcessing = false; state.isProcessing = false;
state.isCancelable = true; state.isCancelable = true;
// state.currentIteration = 0; // state.currentIteration = 0;
@ -338,6 +338,18 @@ export const systemSlice = createSlice({
); );
}); });
/**
* Graph Execution State Complete
*/
builder.addCase(appSocketGraphExecutionStateComplete, (state) => {
state.isProcessing = false;
state.isCancelable = false;
state.isCancelScheduled = false;
state.currentStep = 0;
state.totalSteps = 0;
state.statusTranslationKey = 'common.statusConnected';
});
/** /**
* Session Invoked - PENDING * Session Invoked - PENDING
*/ */
@ -367,18 +379,6 @@ export const systemSlice = createSlice({
); );
}); });
/**
* Session Canceled
*/
builder.addCase(graphExecutionStateComplete, (state) => {
state.isProcessing = false;
state.isCancelable = false;
state.isCancelScheduled = false;
state.currentStep = 0;
state.totalSteps = 0;
state.statusTranslationKey = 'common.statusConnected';
});
/** /**
* Received available models from the backend * Received available models from the backend
*/ */

View File

@ -12,46 +12,153 @@ type BaseSocketPayload = {
timestamp: string; timestamp: string;
}; };
// Create actions for each socket event // Create actions for each socket
// Middleware and redux can then respond to them as needed // Middleware and redux can then respond to them as needed
/**
* Socket.IO Connected
*
* Do not use. Only for use in middleware.
*/
export const socketConnected = createAction<BaseSocketPayload>( export const socketConnected = createAction<BaseSocketPayload>(
'socket/socketConnected' 'socket/socketConnected'
); );
/**
* App-level Socket.IO Connected
*/
export const appSocketConnected = createAction<BaseSocketPayload>(
'socket/appSocketConnected'
);
/**
* Socket.IO Disconnect
*
* Do not use. Only for use in middleware.
*/
export const socketDisconnected = createAction<BaseSocketPayload>( export const socketDisconnected = createAction<BaseSocketPayload>(
'socket/socketDisconnected' 'socket/socketDisconnected'
); );
/**
* App-level Socket.IO Disconnected
*/
export const appSocketDisconnected = createAction<BaseSocketPayload>(
'socket/appSocketDisconnected'
);
/**
* Socket.IO Subscribed
*
* Do not use. Only for use in middleware.
*/
export const socketSubscribed = createAction< export const socketSubscribed = createAction<
BaseSocketPayload & { sessionId: string } BaseSocketPayload & { sessionId: string }
>('socket/socketSubscribed'); >('socket/socketSubscribed');
/**
* App-level Socket.IO Subscribed
*/
export const appSocketSubscribed = createAction<
BaseSocketPayload & { sessionId: string }
>('socket/appSocketSubscribed');
/**
* Socket.IO Unsubscribed
*
* Do not use. Only for use in middleware.
*/
export const socketUnsubscribed = createAction< export const socketUnsubscribed = createAction<
BaseSocketPayload & { sessionId: string } BaseSocketPayload & { sessionId: string }
>('socket/socketUnsubscribed'); >('socket/socketUnsubscribed');
export const invocationStarted = createAction< /**
BaseSocketPayload & { data: InvocationStartedEvent } * App-level Socket.IO Unsubscribed
>('socket/invocationStarted'); */
export const appSocketUnsubscribed = createAction<
BaseSocketPayload & { sessionId: string }
>('socket/appSocketUnsubscribed');
export const invocationComplete = createAction< /**
* Socket.IO Invocation Started
*
* Do not use. Only for use in middleware.
*/
export const socketInvocationStarted = createAction<
BaseSocketPayload & { data: InvocationStartedEvent }
>('socket/socketInvocationStarted');
/**
* App-level Socket.IO Invocation Started
*/
export const appSocketInvocationStarted = createAction<
BaseSocketPayload & { data: InvocationStartedEvent }
>('socket/appSocketInvocationStarted');
/**
* Socket.IO Invocation Complete
*
* Do not use. Only for use in middleware.
*/
export const socketInvocationComplete = createAction<
BaseSocketPayload & { BaseSocketPayload & {
data: InvocationCompleteEvent; data: InvocationCompleteEvent;
} }
>('socket/invocationComplete'); >('socket/socketInvocationComplete');
export const invocationError = createAction< /**
* App-level Socket.IO Invocation Complete
*/
export const appSocketInvocationComplete = createAction<
BaseSocketPayload & {
data: InvocationCompleteEvent;
}
>('socket/appSocketInvocationComplete');
/**
* Socket.IO Invocation Error
*
* Do not use. Only for use in middleware.
*/
export const socketInvocationError = createAction<
BaseSocketPayload & { data: InvocationErrorEvent } BaseSocketPayload & { data: InvocationErrorEvent }
>('socket/invocationError'); >('socket/socketInvocationError');
export const graphExecutionStateComplete = createAction< /**
* App-level Socket.IO Invocation Error
*/
export const appSocketInvocationError = createAction<
BaseSocketPayload & { 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 } BaseSocketPayload & { data: GraphExecutionStateCompleteEvent }
>('socket/graphExecutionStateComplete'); >('socket/socketGraphExecutionStateComplete');
export const generatorProgress = createAction< /**
* App-level Socket.IO Graph Execution State Complete
*/
export const appSocketGraphExecutionStateComplete = createAction<
BaseSocketPayload & { data: GraphExecutionStateCompleteEvent }
>('socket/appSocketGraphExecutionStateComplete');
/**
* Socket.IO Generator Progress
*
* Do not use. Only for use in middleware.
*/
export const socketGeneratorProgress = createAction<
BaseSocketPayload & { data: GeneratorProgressEvent } BaseSocketPayload & { data: GeneratorProgressEvent }
>('socket/generatorProgress'); >('socket/socketGeneratorProgress');
// dispatch this when we need to fully reset the socket connection /**
export const socketReset = createAction('socket/socketReset'); * App-level Socket.IO Generator Progress
*/
export const appSocketGeneratorProgress = createAction<
BaseSocketPayload & { data: GeneratorProgressEvent }
>('socket/appSocketGeneratorProgress');

View File

@ -3,11 +3,11 @@ import { AppDispatch, RootState } from 'app/store/store';
import { getTimestamp } from 'common/util/getTimestamp'; import { getTimestamp } from 'common/util/getTimestamp';
import { Socket } from 'socket.io-client'; import { Socket } from 'socket.io-client';
import { import {
generatorProgress, socketGeneratorProgress,
graphExecutionStateComplete, socketGraphExecutionStateComplete,
invocationComplete, socketInvocationComplete,
invocationError, socketInvocationError,
invocationStarted, socketInvocationStarted,
socketConnected, socketConnected,
socketDisconnected, socketDisconnected,
socketSubscribed, socketSubscribed,
@ -77,21 +77,21 @@ export const setEventListeners = (arg: SetEventListenersArg) => {
* Invocation started * Invocation started
*/ */
socket.on('invocation_started', (data) => { socket.on('invocation_started', (data) => {
dispatch(invocationStarted({ data, timestamp: getTimestamp() })); dispatch(socketInvocationStarted({ data, timestamp: getTimestamp() }));
}); });
/** /**
* Generator progress * Generator progress
*/ */
socket.on('generator_progress', (data) => { socket.on('generator_progress', (data) => {
dispatch(generatorProgress({ data, timestamp: getTimestamp() })); dispatch(socketGeneratorProgress({ data, timestamp: getTimestamp() }));
}); });
/** /**
* Invocation error * Invocation error
*/ */
socket.on('invocation_error', (data) => { socket.on('invocation_error', (data) => {
dispatch(invocationError({ data, timestamp: getTimestamp() })); dispatch(socketInvocationError({ data, timestamp: getTimestamp() }));
}); });
/** /**
@ -99,7 +99,7 @@ export const setEventListeners = (arg: SetEventListenersArg) => {
*/ */
socket.on('invocation_complete', (data) => { socket.on('invocation_complete', (data) => {
dispatch( dispatch(
invocationComplete({ socketInvocationComplete({
data, data,
timestamp: getTimestamp(), timestamp: getTimestamp(),
}) })
@ -110,6 +110,11 @@ export const setEventListeners = (arg: SetEventListenersArg) => {
* Graph complete * Graph complete
*/ */
socket.on('graph_execution_state_complete', (data) => { socket.on('graph_execution_state_complete', (data) => {
dispatch(graphExecutionStateComplete({ data, timestamp: getTimestamp() })); dispatch(
socketGraphExecutionStateComplete({
data,
timestamp: getTimestamp(),
})
);
}); });
}; };