fix: render run immediately
This commit is contained in:
@@ -333,6 +333,12 @@ async function processRunExecution(job: Job<ExecuteRunData>) {
|
|||||||
// Schedule updates for Google Sheets and Airtable
|
// Schedule updates for Google Sheets and Airtable
|
||||||
await triggerIntegrationUpdates(plainRun.runId, plainRun.robotMetaId);
|
await triggerIntegrationUpdates(plainRun.runId, plainRun.robotMetaId);
|
||||||
|
|
||||||
|
// Flush any remaining persistence buffer before emitting socket event
|
||||||
|
if (browser && browser.interpreter) {
|
||||||
|
await browser.interpreter.flushPersistenceBuffer();
|
||||||
|
logger.log('debug', `Flushed persistence buffer before emitting run-completed for run ${data.runId}`);
|
||||||
|
}
|
||||||
|
|
||||||
const completionData = {
|
const completionData = {
|
||||||
runId: data.runId,
|
runId: data.runId,
|
||||||
robotMetaId: plainRun.robotMetaId,
|
robotMetaId: plainRun.robotMetaId,
|
||||||
|
|||||||
@@ -300,6 +300,10 @@ export class WorkflowInterpreter {
|
|||||||
this.socket.emit('log', `----- The interpretation finished with status: ${status} -----`, false);
|
this.socket.emit('log', `----- The interpretation finished with status: ${status} -----`, false);
|
||||||
|
|
||||||
logger.log('debug', `Interpretation finished`);
|
logger.log('debug', `Interpretation finished`);
|
||||||
|
|
||||||
|
// Flush any remaining data in persistence buffer before completing
|
||||||
|
await this.flushPersistenceBuffer();
|
||||||
|
|
||||||
this.interpreter = null;
|
this.interpreter = null;
|
||||||
this.socket.emit('activePairId', -1);
|
this.socket.emit('activePairId', -1);
|
||||||
this.interpretationIsPaused = false;
|
this.interpretationIsPaused = false;
|
||||||
@@ -606,9 +610,9 @@ export class WorkflowInterpreter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Flushes persistence buffer to database in a single transaction
|
* Flushes persistence buffer to database in a single transaction
|
||||||
* @private
|
* @public - Made public to allow external flush before socket emission
|
||||||
*/
|
*/
|
||||||
private async flushPersistenceBuffer(): Promise<void> {
|
public async flushPersistenceBuffer(): Promise<void> {
|
||||||
if (this.persistenceBuffer.length === 0 || this.persistenceInProgress || !this.currentRunId) {
|
if (this.persistenceBuffer.length === 0 || this.persistenceInProgress || !this.currentRunId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -276,12 +276,14 @@ export const RunsTable: React.FC<RunsTableProps> = ({
|
|||||||
}, [debouncedSearch]);
|
}, [debouncedSearch]);
|
||||||
|
|
||||||
|
|
||||||
|
// Handle rerender requests using cache invalidation
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (rerenderRuns) {
|
if (rerenderRuns) {
|
||||||
|
// Invalidate cache to force refetch
|
||||||
refetch();
|
refetch();
|
||||||
setRerenderRuns(false);
|
setRerenderRuns(false);
|
||||||
}
|
}
|
||||||
}, [rerenderRuns, setRerenderRuns, refetch]);
|
}, [rerenderRuns, refetch, setRerenderRuns]);
|
||||||
|
|
||||||
const handleDelete = useCallback(() => {
|
const handleDelete = useCallback(() => {
|
||||||
notify('success', t('runstable.notifications.delete_success'));
|
notify('success', t('runstable.notifications.delete_success'));
|
||||||
@@ -373,7 +375,7 @@ export const RunsTable: React.FC<RunsTableProps> = ({
|
|||||||
urlRunId={urlRunId}
|
urlRunId={urlRunId}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
}, [getPaginationState, accordionSortConfigs, expandedRows, handleRowExpand, handleDelete, currentInterpretationLog, abortRunHandler, runningRecordingName, urlRunId]);
|
}, [paginationStates, runId, runningRecordingName, currentInterpretationLog, abortRunHandler, handleDelete, accordionSortConfigs]);
|
||||||
|
|
||||||
const renderSortIcon = useCallback((column: Column, robotMetaId: string) => {
|
const renderSortIcon = useCallback((column: Column, robotMetaId: string) => {
|
||||||
const sortConfig = accordionSortConfigs[robotMetaId];
|
const sortConfig = accordionSortConfigs[robotMetaId];
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ export const SocketProvider = ({ children }: { children: JSX.Element }) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
socketStore.queueSocket = null;
|
socketStore.queueSocket = null;
|
||||||
|
runStartedCallbackRef.current = null;
|
||||||
runCompletedCallbackRef.current = null;
|
runCompletedCallbackRef.current = null;
|
||||||
runRecoveredCallbackRef.current = null;
|
runRecoveredCallbackRef.current = null;
|
||||||
runScheduledCallbackRef.current = null;
|
runScheduledCallbackRef.current = null;
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps)
|
|||||||
let aborted = false;
|
let aborted = false;
|
||||||
|
|
||||||
const { notify, setRerenderRuns, setRecordingId } = useGlobalInfoStore();
|
const { notify, setRerenderRuns, setRecordingId } = useGlobalInfoStore();
|
||||||
const { invalidateRuns } = useCacheInvalidation();
|
const { invalidateRuns, addOptimisticRun } = useCacheInvalidation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const { state } = useContext(AuthContext);
|
const { state } = useContext(AuthContext);
|
||||||
@@ -132,7 +132,7 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps)
|
|||||||
setRerenderRuns(true);
|
setRerenderRuns(true);
|
||||||
invalidateRuns();
|
invalidateRuns();
|
||||||
})
|
})
|
||||||
}, [runningRecordingName, aborted, currentInterpretationLog, notify, setRerenderRuns, invalidateRuns]);
|
}, [runningRecordingName, aborted, currentInterpretationLog, notify, setRerenderRuns]);
|
||||||
|
|
||||||
const debugMessageHandler = useCallback((msg: string) => {
|
const debugMessageHandler = useCallback((msg: string) => {
|
||||||
setCurrentInterpretationLog((prevState) =>
|
setCurrentInterpretationLog((prevState) =>
|
||||||
@@ -140,11 +140,26 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps)
|
|||||||
}, [currentInterpretationLog])
|
}, [currentInterpretationLog])
|
||||||
|
|
||||||
const handleRunRecording = useCallback((settings: RunSettings) => {
|
const handleRunRecording = useCallback((settings: RunSettings) => {
|
||||||
|
// Add optimistic run to cache immediately
|
||||||
|
const optimisticRun = {
|
||||||
|
id: runningRecordingId,
|
||||||
|
runId: `temp-${Date.now()}`, // Temporary ID until we get the real one
|
||||||
|
status: 'running',
|
||||||
|
name: runningRecordingName,
|
||||||
|
startedAt: new Date().toISOString(),
|
||||||
|
finishedAt: '',
|
||||||
|
robotMetaId: runningRecordingId,
|
||||||
|
log: 'Starting...',
|
||||||
|
isOptimistic: true
|
||||||
|
};
|
||||||
|
|
||||||
|
addOptimisticRun(optimisticRun);
|
||||||
|
|
||||||
createAndRunRecording(runningRecordingId, settings).then((response: CreateRunResponseWithQueue) => {
|
createAndRunRecording(runningRecordingId, settings).then((response: CreateRunResponseWithQueue) => {
|
||||||
|
invalidateRuns();
|
||||||
const { browserId, runId, robotMetaId, queued } = response;
|
const { browserId, runId, robotMetaId, queued } = response;
|
||||||
|
|
||||||
setIds({ browserId, runId, robotMetaId });
|
setIds({ browserId, runId, robotMetaId });
|
||||||
invalidateRuns();
|
|
||||||
navigate(`/runs/${robotMetaId}/run/${runId}`);
|
navigate(`/runs/${robotMetaId}/run/${runId}`);
|
||||||
|
|
||||||
if (queued) {
|
if (queued) {
|
||||||
@@ -160,8 +175,6 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps)
|
|||||||
|
|
||||||
socket.on('debugMessage', debugMessageHandler);
|
socket.on('debugMessage', debugMessageHandler);
|
||||||
socket.on('run-completed', (data) => {
|
socket.on('run-completed', (data) => {
|
||||||
setRunningRecordingName('');
|
|
||||||
setCurrentInterpretationLog('');
|
|
||||||
setRerenderRuns(true);
|
setRerenderRuns(true);
|
||||||
invalidateRuns();
|
invalidateRuns();
|
||||||
|
|
||||||
@@ -201,7 +214,13 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps)
|
|||||||
socket.off('connect_error');
|
socket.off('connect_error');
|
||||||
socket.off('disconnect');
|
socket.off('disconnect');
|
||||||
}
|
}
|
||||||
}, [runningRecordingName, sockets, ids, debugMessageHandler, user?.id, t, notify, setRerenderRuns, setQueuedRuns, navigate, setContent, setIds, invalidateRuns]);
|
}, [runningRecordingName, sockets, ids, debugMessageHandler, user?.id, t, notify, setRerenderRuns, setQueuedRuns, navigate, setContent, setIds, invalidateRuns, addOptimisticRun, runningRecordingId]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
queuedRuns.clear();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleScheduleRecording = async (settings: ScheduleSettings) => {
|
const handleScheduleRecording = async (settings: ScheduleSettings) => {
|
||||||
const { message, runId }: ScheduleRunResponse = await scheduleStoredRecording(runningRecordingId, settings);
|
const { message, runId }: ScheduleRunResponse = await scheduleStoredRecording(runningRecordingId, settings);
|
||||||
@@ -225,7 +244,7 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps)
|
|||||||
|
|
||||||
const handleRunCompleted = (completionData: any) => {
|
const handleRunCompleted = (completionData: any) => {
|
||||||
setRerenderRuns(true);
|
setRerenderRuns(true);
|
||||||
invalidateRuns();
|
invalidateRuns(); // Invalidate cache to show completed run status
|
||||||
|
|
||||||
if (queuedRuns.has(completionData.runId)) {
|
if (queuedRuns.has(completionData.runId)) {
|
||||||
setQueuedRuns(prev => {
|
setQueuedRuns(prev => {
|
||||||
|
|||||||
Reference in New Issue
Block a user