fix: render run immediately

This commit is contained in:
Rohit Rajan
2025-09-29 20:08:17 +05:30
parent e4c52376f2
commit 9a2d60ef4c
5 changed files with 43 additions and 11 deletions

View File

@@ -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,

View File

@@ -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;
} }

View File

@@ -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];

View File

@@ -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;

View File

@@ -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 => {