perf(backend): parallelize independent startup initializers (#816)

The boot path awaited SelfUpdateService.initialize, DockerEventManager.start,
and TrivyService.initialize one at a time even though none of them depend on
each other. Group them into a single Promise.all so total cold-start time is
the slowest one rather than the sum.

Also convert the inner `docker compose version` probe in
SelfUpdateService.initialize from execFileSync to execFileAsync. Without that,
the synchronous spawn would block the event loop for up to 5 seconds and
silently serialize the other two members of the parallel block, defeating
the parallelization win for in-container deployments.

The synchronous service starts (Monitor, AutoHeal, ImageUpdate, Scheduler,
Mfa) are grouped together up front. They schedule timers whose first ticks
fire 5+ seconds out, so they safely run alongside the awaited block.
This commit is contained in:
Anso
2026-04-28 00:33:17 -04:00
committed by GitHub
parent 61a7e43d82
commit 18cf2e65e8
2 changed files with 19 additions and 14 deletions
+13 -11
View File
@@ -29,27 +29,29 @@ export async function startServer(server: Server): Promise<void> {
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;