fix(automation): add stopAutomation to IAutomationEngine interface and fix interval cleanup

This commit is contained in:
2025-11-22 01:50:37 +01:00
parent 3a60ffae91
commit bd198a78ad
2 changed files with 46 additions and 9 deletions

View File

@@ -3,35 +3,53 @@ import type { BrowserWindow, IpcMainInvokeEvent } from 'electron';
import { DIContainer } from './di-container'; import { DIContainer } from './di-container';
import type { HostedSessionConfig } from '@/packages/domain/entities/HostedSessionConfig'; import type { HostedSessionConfig } from '@/packages/domain/entities/HostedSessionConfig';
import { StepId } from '@/packages/domain/value-objects/StepId'; import { StepId } from '@/packages/domain/value-objects/StepId';
import { MockAutomationEngineAdapter } from '@/packages/infrastructure/adapters/automation/MockAutomationEngineAdapter';
let progressMonitorInterval: NodeJS.Timeout | null = null;
export function setupIpcHandlers(mainWindow: BrowserWindow): void { export function setupIpcHandlers(mainWindow: BrowserWindow): void {
const container = DIContainer.getInstance(); const container = DIContainer.getInstance();
const startAutomationUseCase = container.getStartAutomationUseCase(); const startAutomationUseCase = container.getStartAutomationUseCase();
const sessionRepository = container.getSessionRepository(); const sessionRepository = container.getSessionRepository();
const automationEngine = container.getAutomationEngine(); const automationEngine = container.getAutomationEngine();
const logger = container.getLogger();
ipcMain.handle('start-automation', async (_event: IpcMainInvokeEvent, config: HostedSessionConfig) => { ipcMain.handle('start-automation', async (_event: IpcMainInvokeEvent, config: HostedSessionConfig) => {
try { try {
logger.info('Starting automation', { sessionName: config.sessionName });
// Clear any existing progress interval
if (progressMonitorInterval) {
clearInterval(progressMonitorInterval);
progressMonitorInterval = null;
}
// Connect to browser first (required for dev mode) // Connect to browser first (required for dev mode)
const connectionResult = await container.initializeBrowserConnection(); const connectionResult = await container.initializeBrowserConnection();
if (!connectionResult.success) { if (!connectionResult.success) {
logger.error('Browser connection failed', undefined, { errorMessage: connectionResult.error });
return { success: false, error: connectionResult.error }; return { success: false, error: connectionResult.error };
} }
logger.info('Browser connection established');
const result = await startAutomationUseCase.execute(config); const result = await startAutomationUseCase.execute(config);
logger.info('Automation session created', { sessionId: result.sessionId });
const session = await sessionRepository.findById(result.sessionId); const session = await sessionRepository.findById(result.sessionId);
if (session) { if (session) {
// Start the automation by executing step 1 // Start the automation by executing step 1
logger.info('Executing step 1');
await automationEngine.executeStep(StepId.create(1), config); await automationEngine.executeStep(StepId.create(1), config);
} }
// Set up progress monitoring // Set up progress monitoring
const checkInterval = setInterval(async () => { progressMonitorInterval = setInterval(async () => {
const updatedSession = await sessionRepository.findById(result.sessionId); const updatedSession = await sessionRepository.findById(result.sessionId);
if (!updatedSession) { if (!updatedSession) {
clearInterval(checkInterval); if (progressMonitorInterval) {
clearInterval(progressMonitorInterval);
progressMonitorInterval = null;
}
return; return;
} }
@@ -44,10 +62,14 @@ export function setupIpcHandlers(mainWindow: BrowserWindow): void {
errorMessage: updatedSession.errorMessage || null errorMessage: updatedSession.errorMessage || null
}); });
if (updatedSession.state.value === 'COMPLETED' || if (updatedSession.state.value === 'COMPLETED' ||
updatedSession.state.value === 'FAILED' || updatedSession.state.value === 'FAILED' ||
updatedSession.state.value === 'STOPPED_AT_STEP_18') { updatedSession.state.value === 'STOPPED_AT_STEP_18') {
clearInterval(checkInterval); logger.info('Automation ended', { state: updatedSession.state.value });
if (progressMonitorInterval) {
clearInterval(progressMonitorInterval);
progressMonitorInterval = null;
}
} }
}, 100); }, 100);
@@ -56,9 +78,11 @@ export function setupIpcHandlers(mainWindow: BrowserWindow): void {
sessionId: result.sessionId sessionId: result.sessionId
}; };
} catch (error) { } catch (error) {
const err = error instanceof Error ? error : new Error('Unknown error');
logger.error('Automation failed', err);
return { return {
success: false, success: false,
error: error instanceof Error ? error.message : 'Unknown error' error: err.message
}; };
} }
}); });
@@ -89,22 +113,34 @@ export function setupIpcHandlers(mainWindow: BrowserWindow): void {
ipcMain.handle('stop-automation', async (_event: IpcMainInvokeEvent, sessionId: string) => { ipcMain.handle('stop-automation', async (_event: IpcMainInvokeEvent, sessionId: string) => {
try { try {
logger.info('Stopping automation', { sessionId });
// Clear progress monitoring interval
if (progressMonitorInterval) {
clearInterval(progressMonitorInterval);
progressMonitorInterval = null;
logger.info('Progress monitor cleared');
}
// Stop the automation engine interval // Stop the automation engine interval
const engine = automationEngine as MockAutomationEngineAdapter; automationEngine.stopAutomation();
engine.stopAutomation(); logger.info('Automation engine stopped');
// Update session state to failed with user stop reason // Update session state to failed with user stop reason
const session = await sessionRepository.findById(sessionId); const session = await sessionRepository.findById(sessionId);
if (session) { if (session) {
session.fail('User stopped automation'); session.fail('User stopped automation');
await sessionRepository.update(session); await sessionRepository.update(session);
logger.info('Session marked as failed', { sessionId });
} }
return { success: true }; return { success: true };
} catch (error) { } catch (error) {
const err = error instanceof Error ? error : new Error('Unknown error');
logger.error('Stop automation failed', err);
return { return {
success: false, success: false,
error: error instanceof Error ? error.message : 'Unknown error' error: err.message
}; };
} }
}); });

View File

@@ -9,4 +9,5 @@ export interface ValidationResult {
export interface IAutomationEngine { export interface IAutomationEngine {
validateConfiguration(config: HostedSessionConfig): Promise<ValidationResult>; validateConfiguration(config: HostedSessionConfig): Promise<ValidationResult>;
executeStep(stepId: StepId, config: HostedSessionConfig): Promise<void>; executeStep(stepId: StepId, config: HostedSessionConfig): Promise<void>;
stopAutomation(): void;
} }