diff --git a/backend/src/bootstrap/startup.ts b/backend/src/bootstrap/startup.ts index a55c7eeb..19812cda 100644 --- a/backend/src/bootstrap/startup.ts +++ b/backend/src/bootstrap/startup.ts @@ -29,27 +29,29 @@ export async function startServer(server: Server): Promise { console.error('Migration failed:', error); } + // Synchronous starts: schedule background timers and continue. None of + // these fire their first tick for at least a few seconds, so they + // safely run alongside the async initializers below. LicenseService.getInstance().initialize(); - - await SelfUpdateService.getInstance().initialize(); - MonitorService.getInstance().start(); AutoHealService.getInstance().start(); - - await DockerEventManager.getInstance().start(); - - await TrivyService.getInstance().initialize(); - ImageUpdateService.getInstance().start(); - SchedulerService.getInstance().start(); + MfaService.getInstance().start(); + // Async initializers are independent of each other; run in parallel + // so total boot time is the slowest one rather than the sum. + await Promise.all([ + SelfUpdateService.getInstance().initialize(), + DockerEventManager.getInstance().start(), + TrivyService.getInstance().initialize(), + ]); + + // Fire-and-forget housekeeping; logged but never awaited. sweepStaleGitTempDirs().catch((err) => { console.warn('[GitSource] Temp dir sweep failed:', (err as Error).message); }); - MfaService.getInstance().start(); - const isPilotAgent = process.env.SENCHO_MODE === 'pilot'; const listenHost = isPilotAgent ? '127.0.0.1' : undefined; diff --git a/backend/src/services/SelfUpdateService.ts b/backend/src/services/SelfUpdateService.ts index d2a19c9a..fd34cd89 100644 --- a/backend/src/services/SelfUpdateService.ts +++ b/backend/src/services/SelfUpdateService.ts @@ -1,4 +1,4 @@ -import { execFileSync, execFile } from 'child_process'; +import { execFile } from 'child_process'; import { promisify } from 'util'; import * as fs from 'fs'; import DockerController from './DockerController'; @@ -63,9 +63,12 @@ class SelfUpdateService { return; } - // Verify docker compose CLI is available inside the container + // Verify docker compose CLI is available inside the container. + // execFileAsync (not Sync) so the parallel boot-task block in + // bootstrap/startup.ts can actually run TrivyService and DockerEventManager + // concurrently instead of waiting on a 5s blocking spawn here. try { - execFileSync('docker', ['compose', 'version'], { stdio: 'pipe', timeout: 5000 }); + await execFileAsync('docker', ['compose', 'version'], { timeout: 5000 }); } catch { console.log('[SelfUpdate] docker compose CLI not available in container'); disableCapability('self-update');