refactor(06-03): migrate Batch 3 feature lifecycle routes to facade pattern

- start.ts: Add facadeFactory parameter, use facade.isAutoLoopRunning/startAutoLoop
- resume-feature.ts: Add facadeFactory parameter, use facade.resumeFeature
- resume-interrupted.ts: Add facadeFactory parameter, use facade.resumeInterruptedFeatures
- All routes maintain backward compatibility with autoModeService fallback
This commit is contained in:
Shirone
2026-01-30 21:38:03 +01:00
parent 0ee28c58df
commit ffbfd2b79b
3 changed files with 71 additions and 4 deletions

View File

@@ -4,12 +4,16 @@
import type { Request, Response } from 'express';
import type { AutoModeService } from '../../../services/auto-mode-service.js';
import type { AutoModeServiceFacade } from '../../../services/auto-mode/index.js';
import { createLogger } from '@automaker/utils';
import { getErrorMessage, logError } from '../common.js';
const logger = createLogger('AutoMode');
export function createResumeFeatureHandler(autoModeService: AutoModeService) {
export function createResumeFeatureHandler(
autoModeService: AutoModeService,
facadeFactory?: (projectPath: string) => AutoModeServiceFacade
) {
return async (req: Request, res: Response): Promise<void> => {
try {
const { projectPath, featureId, useWorktrees } = req.body as {
@@ -26,6 +30,20 @@ export function createResumeFeatureHandler(autoModeService: AutoModeService) {
return;
}
// Use facade if factory is provided, otherwise fall back to autoModeService
if (facadeFactory) {
const facade = facadeFactory(projectPath);
// Start resume in background
// Default to false - worktrees should only be used when explicitly enabled
facade.resumeFeature(featureId, useWorktrees ?? false).catch((error) => {
logger.error(`Resume feature ${featureId} error:`, error);
});
res.json({ success: true });
return;
}
// Legacy path: use autoModeService directly
// Start resume in background
// Default to false - worktrees should only be used when explicitly enabled
autoModeService

View File

@@ -8,6 +8,7 @@
import type { Request, Response } from 'express';
import { createLogger } from '@automaker/utils';
import type { AutoModeService } from '../../../services/auto-mode-service.js';
import type { AutoModeServiceFacade } from '../../../services/auto-mode/index.js';
const logger = createLogger('ResumeInterrupted');
@@ -15,7 +16,10 @@ interface ResumeInterruptedRequest {
projectPath: string;
}
export function createResumeInterruptedHandler(autoModeService: AutoModeService) {
export function createResumeInterruptedHandler(
autoModeService: AutoModeService,
facadeFactory?: (projectPath: string) => AutoModeServiceFacade
) {
return async (req: Request, res: Response): Promise<void> => {
const { projectPath } = req.body as ResumeInterruptedRequest;
@@ -27,7 +31,14 @@ export function createResumeInterruptedHandler(autoModeService: AutoModeService)
logger.info(`Checking for interrupted features in ${projectPath}`);
try {
await autoModeService.resumeInterruptedFeatures(projectPath);
// Use facade if factory is provided, otherwise fall back to autoModeService
if (facadeFactory) {
const facade = facadeFactory(projectPath);
await facade.resumeInterruptedFeatures();
} else {
await autoModeService.resumeInterruptedFeatures(projectPath);
}
res.json({
success: true,
message: 'Resume check completed',

View File

@@ -4,12 +4,16 @@
import type { Request, Response } from 'express';
import type { AutoModeService } from '../../../services/auto-mode-service.js';
import type { AutoModeServiceFacade } from '../../../services/auto-mode/index.js';
import { createLogger } from '@automaker/utils';
import { getErrorMessage, logError } from '../common.js';
const logger = createLogger('AutoMode');
export function createStartHandler(autoModeService: AutoModeService) {
export function createStartHandler(
autoModeService: AutoModeService,
facadeFactory?: (projectPath: string) => AutoModeServiceFacade
) {
return async (req: Request, res: Response): Promise<void> => {
try {
const { projectPath, branchName, maxConcurrency } = req.body as {
@@ -32,6 +36,40 @@ export function createStartHandler(autoModeService: AutoModeService) {
? `worktree ${normalizedBranchName}`
: 'main worktree';
// Use facade if factory is provided, otherwise fall back to autoModeService
if (facadeFactory) {
const facade = facadeFactory(projectPath);
// Check if already running
if (facade.isAutoLoopRunning(normalizedBranchName)) {
res.json({
success: true,
message: `Auto mode is already running for ${worktreeDesc}`,
alreadyRunning: true,
branchName: normalizedBranchName,
});
return;
}
// Start the auto loop for this project/worktree
const resolvedMaxConcurrency = await facade.startAutoLoop(
normalizedBranchName,
maxConcurrency
);
logger.info(
`Started auto loop for ${worktreeDesc} in project: ${projectPath} with maxConcurrency: ${resolvedMaxConcurrency}`
);
res.json({
success: true,
message: `Auto mode started with max ${resolvedMaxConcurrency} concurrent features`,
branchName: normalizedBranchName,
});
return;
}
// Legacy path: use autoModeService directly
// Check if already running
if (autoModeService.isAutoLoopRunningForProject(projectPath, normalizedBranchName)) {
res.json({