@open-mercato/cli 0.5.1-develop.3032.01699048cb → 0.5.1-develop.3043.1a796c3920
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/dist/agentic/shared/AGENTS.md.template +1 -1
- package/dist/lib/__integration__/TC-INT-007.spec.js +201 -0
- package/dist/lib/__integration__/TC-INT-007.spec.js.map +7 -0
- package/dist/lib/dev-env-reload.js +89 -0
- package/dist/lib/dev-env-reload.js.map +7 -0
- package/dist/lib/generators/extensions/ai-agents.js +218 -0
- package/dist/lib/generators/extensions/ai-agents.js.map +7 -0
- package/dist/lib/generators/extensions/ai-tools.js +56 -1
- package/dist/lib/generators/extensions/ai-tools.js.map +2 -2
- package/dist/lib/generators/extensions/index.js +2 -0
- package/dist/lib/generators/extensions/index.js.map +2 -2
- package/dist/lib/testing/integration-discovery.js +102 -5
- package/dist/lib/testing/integration-discovery.js.map +2 -2
- package/dist/mercato.js +153 -79
- package/dist/mercato.js.map +2 -2
- package/package.json +5 -5
- package/src/__tests__/mercato.test.ts +301 -25
- package/src/lib/__integration__/TC-INT-007.spec.ts +228 -0
- package/src/lib/__tests__/dev-env-reload.test.ts +62 -0
- package/src/lib/dev-env-reload.ts +110 -0
- package/src/lib/generators/__tests__/module-subset.test.ts +14 -0
- package/src/lib/generators/__tests__/output-snapshots.test.ts +17 -0
- package/src/lib/generators/__tests__/scanner.test.ts +1 -1
- package/src/lib/generators/__tests__/structural-contracts.test.ts +26 -0
- package/src/lib/generators/extensions/ai-agents.ts +240 -0
- package/src/lib/generators/extensions/ai-tools.ts +72 -1
- package/src/lib/generators/extensions/index.ts +2 -0
- package/src/lib/testing/__tests__/integration-discovery.test.ts +68 -0
- package/src/lib/testing/integration-discovery.ts +127 -3
- package/src/mercato.ts +190 -83
package/src/mercato.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { resolveInitDerivedSecrets } from './lib/init-secrets'
|
|
|
12
12
|
import { parseModuleInstallArgs } from './lib/module-install-args'
|
|
13
13
|
import { resolveNextBuildIdCandidate } from './lib/next-build-id'
|
|
14
14
|
import { acquireServerStartLock } from './lib/server-start-lock'
|
|
15
|
+
import { createDevEnvReloader, watchDevEnvFiles } from './lib/dev-env-reload'
|
|
15
16
|
// Lazy-imported to avoid pulling in `testcontainers` (devDependency) at startup
|
|
16
17
|
const lazyIntegration = () => import('./lib/testing/integration')
|
|
17
18
|
import type { ChildProcess } from 'node:child_process'
|
|
@@ -19,6 +20,7 @@ import path from 'node:path'
|
|
|
19
20
|
import fs from 'node:fs'
|
|
20
21
|
|
|
21
22
|
let envLoaded = false
|
|
23
|
+
const initialProcessEnvironmentEntries = Object.entries(process.env)
|
|
22
24
|
|
|
23
25
|
async function runWithCapturedExitCode(action: () => Promise<void>): Promise<number> {
|
|
24
26
|
const previousExitCode = process.exitCode
|
|
@@ -311,6 +313,24 @@ type ManagedProcessExitResult = {
|
|
|
311
313
|
signal: NodeJS.Signals | null
|
|
312
314
|
}
|
|
313
315
|
|
|
316
|
+
type DevServerRestartResult = {
|
|
317
|
+
label: string
|
|
318
|
+
restart: true
|
|
319
|
+
filePath: string
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
type DevServerExitResult = ManagedProcessExitResult | DevServerRestartResult
|
|
323
|
+
|
|
324
|
+
type ModuleCommandLookupResult =
|
|
325
|
+
| {
|
|
326
|
+
status: 'ok'
|
|
327
|
+
module: Module
|
|
328
|
+
command: NonNullable<Module['cli']>[number]
|
|
329
|
+
}
|
|
330
|
+
| {
|
|
331
|
+
status: 'missing-module' | 'missing-cli' | 'missing-command'
|
|
332
|
+
}
|
|
333
|
+
|
|
314
334
|
function waitForManagedProcessExit(proc: ChildProcess, label: string): Promise<ManagedProcessExitResult> {
|
|
315
335
|
return new Promise((resolve) => {
|
|
316
336
|
proc.on('exit', (code, signal) => {
|
|
@@ -337,6 +357,54 @@ function createManagedProcessExitError(result: ManagedProcessExitResult): Error
|
|
|
337
357
|
return new Error(`[server] ${result.label} exited unexpectedly with ${formatManagedProcessExitStatus(result)}.`)
|
|
338
358
|
}
|
|
339
359
|
|
|
360
|
+
function isDevServerRestartResult(result: DevServerExitResult): result is DevServerRestartResult {
|
|
361
|
+
return 'restart' in result && result.restart === true
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function formatQueueWorkerLabel(queueNames: string[]): string {
|
|
365
|
+
if (queueNames.length === 0) return 'Queue worker'
|
|
366
|
+
const sorted = [...queueNames].sort((a, b) => a.localeCompare(b))
|
|
367
|
+
const preview = sorted.length > 4 ? `${sorted.slice(0, 4).join(', ')}, +${sorted.length - 4} more` : sorted.join(', ')
|
|
368
|
+
return `Queue worker (${preview})`
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function lookupModuleCommand(
|
|
372
|
+
allModules: Module[],
|
|
373
|
+
moduleName: string,
|
|
374
|
+
commandName: string,
|
|
375
|
+
): ModuleCommandLookupResult {
|
|
376
|
+
const mod = allModules.find((entry) => entry.id === moduleName)
|
|
377
|
+
if (!mod) {
|
|
378
|
+
return { status: 'missing-module' }
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
if (!mod.cli || mod.cli.length === 0) {
|
|
382
|
+
return { status: 'missing-cli' }
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const command = mod.cli.find((entry) => entry.command === commandName)
|
|
386
|
+
if (!command) {
|
|
387
|
+
return { status: 'missing-command' }
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return {
|
|
391
|
+
status: 'ok',
|
|
392
|
+
module: mod,
|
|
393
|
+
command,
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function describeMissingModuleCommand(result: Exclude<ModuleCommandLookupResult, { status: 'ok' }>): string {
|
|
398
|
+
switch (result.status) {
|
|
399
|
+
case 'missing-module':
|
|
400
|
+
return 'module not enabled'
|
|
401
|
+
case 'missing-cli':
|
|
402
|
+
return 'module has no CLI commands'
|
|
403
|
+
case 'missing-command':
|
|
404
|
+
return 'command not found'
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
340
408
|
function ensureNextBuildIdInConfiguredDistDir(appDir: string): void {
|
|
341
409
|
const configuredDistDir = path.join(appDir, '.mercato', 'next')
|
|
342
410
|
const configuredBuildIdPath = path.join(configuredDistDir, 'BUILD_ID')
|
|
@@ -404,36 +472,25 @@ async function runModuleCommand(
|
|
|
404
472
|
args: string[] = [],
|
|
405
473
|
options: { optional?: boolean; silentOptional?: boolean } = {},
|
|
406
474
|
): Promise<boolean> {
|
|
407
|
-
const
|
|
408
|
-
if (
|
|
475
|
+
const resolved = lookupModuleCommand(allModules, moduleName, commandName)
|
|
476
|
+
if (resolved.status !== 'ok') {
|
|
409
477
|
if (options.optional) {
|
|
410
478
|
if (!options.silentOptional) {
|
|
411
|
-
console.log(`⏭️ Skipping "${moduleName}:${commandName}" —
|
|
479
|
+
console.log(`⏭️ Skipping "${moduleName}:${commandName}" — ${describeMissingModuleCommand(resolved)}`)
|
|
412
480
|
}
|
|
413
481
|
return false
|
|
414
482
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
return false
|
|
483
|
+
switch (resolved.status) {
|
|
484
|
+
case 'missing-module':
|
|
485
|
+
throw new Error(`Module not found: "${moduleName}"`)
|
|
486
|
+
case 'missing-cli':
|
|
487
|
+
throw new Error(`Module "${moduleName}" has no CLI commands`)
|
|
488
|
+
case 'missing-command':
|
|
489
|
+
throw new Error(`Command "${commandName}" not found in module "${moduleName}"`)
|
|
423
490
|
}
|
|
424
|
-
throw new Error(`Module "${moduleName}" has no CLI commands`)
|
|
425
491
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
if (options.optional) {
|
|
429
|
-
if (!options.silentOptional) {
|
|
430
|
-
console.log(`⏭️ Skipping "${moduleName}:${commandName}" — command not found`)
|
|
431
|
-
}
|
|
432
|
-
return false
|
|
433
|
-
}
|
|
434
|
-
throw new Error(`Command "${commandName}" not found in module "${moduleName}"`)
|
|
435
|
-
}
|
|
436
|
-
await cmd.run(args)
|
|
492
|
+
|
|
493
|
+
await resolved.command.run(args)
|
|
437
494
|
return true
|
|
438
495
|
}
|
|
439
496
|
|
|
@@ -1599,12 +1656,11 @@ export async function run(argv = process.argv) {
|
|
|
1599
1656
|
const appDir = env.appDir
|
|
1600
1657
|
const nodeModulesBases = Array.from(new Set([env.rootDir, appDir]))
|
|
1601
1658
|
|
|
1602
|
-
|
|
1603
|
-
const autoSpawnWorkers = process.env.AUTO_SPAWN_WORKERS !== 'false'
|
|
1604
|
-
const autoSpawnScheduler = process.env.AUTO_SPAWN_SCHEDULER !== 'false'
|
|
1605
|
-
const queueStrategy = process.env.QUEUE_STRATEGY || 'local'
|
|
1606
|
-
const runtimeEnv = buildServerProcessEnvironment(process.env)
|
|
1659
|
+
let processes: ChildProcess[] = []
|
|
1607
1660
|
let didRetryCorruptedTurbopackCache = false
|
|
1661
|
+
let stopping = false
|
|
1662
|
+
let envChangePromiseResolve: ((result: DevServerRestartResult) => void) | null = null
|
|
1663
|
+
const envReloader = createDevEnvReloader(appDir, process.env, initialProcessEnvironmentEntries)
|
|
1608
1664
|
|
|
1609
1665
|
function cleanup() {
|
|
1610
1666
|
console.log('[server] Shutting down...')
|
|
@@ -1622,7 +1678,7 @@ export async function run(argv = process.argv) {
|
|
|
1622
1678
|
processes.map(
|
|
1623
1679
|
(proc) =>
|
|
1624
1680
|
new Promise<void>((resolve) => {
|
|
1625
|
-
if (proc.exitCode !== null) return resolve()
|
|
1681
|
+
if (proc.exitCode !== null || proc.signalCode !== null) return resolve()
|
|
1626
1682
|
proc.on('exit', () => resolve())
|
|
1627
1683
|
})
|
|
1628
1684
|
)
|
|
@@ -1634,10 +1690,17 @@ export async function run(argv = process.argv) {
|
|
|
1634
1690
|
} catch {
|
|
1635
1691
|
// Lock file may already be removed by Next.js — ignore
|
|
1636
1692
|
}
|
|
1693
|
+
processes = []
|
|
1637
1694
|
}
|
|
1638
1695
|
|
|
1639
|
-
process.on('SIGTERM',
|
|
1640
|
-
|
|
1696
|
+
process.on('SIGTERM', () => {
|
|
1697
|
+
stopping = true
|
|
1698
|
+
cleanup()
|
|
1699
|
+
})
|
|
1700
|
+
process.on('SIGINT', () => {
|
|
1701
|
+
stopping = true
|
|
1702
|
+
cleanup()
|
|
1703
|
+
})
|
|
1641
1704
|
|
|
1642
1705
|
console.log('[server] Starting Open Mercato in dev mode...')
|
|
1643
1706
|
|
|
@@ -1649,7 +1712,20 @@ export async function run(argv = process.argv) {
|
|
|
1649
1712
|
const nextBin = resolveInstalledBinary(nodeModulesBases, 'next/dist/bin/next')
|
|
1650
1713
|
const mercatoBin = resolveInstalledBinary(nodeModulesBases, '@open-mercato/cli/bin/mercato')
|
|
1651
1714
|
|
|
1652
|
-
const
|
|
1715
|
+
const stopEnvWatcher = watchDevEnvFiles(appDir, (filePath) => {
|
|
1716
|
+
envChangePromiseResolve?.({
|
|
1717
|
+
label: 'Environment file change',
|
|
1718
|
+
restart: true,
|
|
1719
|
+
filePath,
|
|
1720
|
+
})
|
|
1721
|
+
})
|
|
1722
|
+
|
|
1723
|
+
const waitForEnvChange = (): Promise<DevServerRestartResult> =>
|
|
1724
|
+
new Promise((resolve) => {
|
|
1725
|
+
envChangePromiseResolve = resolve
|
|
1726
|
+
})
|
|
1727
|
+
|
|
1728
|
+
const startNextDev = (runtimeEnv: NodeJS.ProcessEnv): Promise<ManagedProcessExitResult> =>
|
|
1653
1729
|
new Promise((resolve) => {
|
|
1654
1730
|
const nextProcess = spawn('node', [nextBin, 'dev', '--turbopack'], {
|
|
1655
1731
|
stdio: ['inherit', 'pipe', 'pipe'],
|
|
@@ -1682,7 +1758,7 @@ export async function run(argv = process.argv) {
|
|
|
1682
1758
|
didRetryCorruptedTurbopackCache = true
|
|
1683
1759
|
console.log('[server] Detected corrupted Turbopack dev cache. Clearing .mercato/next/dev and restarting Next.js once...')
|
|
1684
1760
|
removeTurbopackDevCache(appDir)
|
|
1685
|
-
return resolve(await startNextDev())
|
|
1761
|
+
return resolve(await startNextDev(runtimeEnv))
|
|
1686
1762
|
}
|
|
1687
1763
|
resolve({
|
|
1688
1764
|
label: 'Next.js dev server',
|
|
@@ -1692,43 +1768,68 @@ export async function run(argv = process.argv) {
|
|
|
1692
1768
|
})
|
|
1693
1769
|
})
|
|
1694
1770
|
|
|
1695
|
-
|
|
1696
|
-
|
|
1771
|
+
try {
|
|
1772
|
+
while (!stopping) {
|
|
1773
|
+
envReloader.reload()
|
|
1774
|
+
const runtimeEnv = buildServerProcessEnvironment(process.env)
|
|
1775
|
+
const autoSpawnWorkers = process.env.AUTO_SPAWN_WORKERS !== 'false'
|
|
1776
|
+
const autoSpawnScheduler = process.env.AUTO_SPAWN_SCHEDULER !== 'false'
|
|
1777
|
+
const queueStrategy = process.env.QUEUE_STRATEGY || 'local'
|
|
1778
|
+
const schedulerCommand = lookupModuleCommand(getCliModules(), 'scheduler', 'start')
|
|
1779
|
+
const managedExitPromises: Promise<DevServerExitResult>[] = [
|
|
1780
|
+
startNextDev(runtimeEnv),
|
|
1781
|
+
waitForEnvChange(),
|
|
1782
|
+
]
|
|
1783
|
+
|
|
1784
|
+
// Start workers if enabled
|
|
1785
|
+
if (autoSpawnWorkers) {
|
|
1786
|
+
const discoveredWorkerQueues = [...new Set(getRegisteredCliWorkers().map((worker) => worker.queue))]
|
|
1787
|
+
if (discoveredWorkerQueues.length === 0) {
|
|
1788
|
+
console.error('[server] AUTO_SPAWN_WORKERS is enabled, but no queues were discovered from CLI modules. Run `yarn generate` and verify `.mercato/generated/modules.cli.generated.ts` contains worker entries. Continuing without auto-spawned workers.')
|
|
1789
|
+
} else {
|
|
1790
|
+
console.log('[server] Starting workers for all queues...')
|
|
1791
|
+
const workerProcess = spawn('node', [mercatoBin, 'queue', 'worker', '--all'], {
|
|
1792
|
+
stdio: 'inherit',
|
|
1793
|
+
env: runtimeEnv,
|
|
1794
|
+
cwd: appDir,
|
|
1795
|
+
})
|
|
1796
|
+
processes.push(workerProcess)
|
|
1797
|
+
managedExitPromises.push(waitForManagedProcessExit(workerProcess, formatQueueWorkerLabel(discoveredWorkerQueues)))
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1697
1800
|
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
}
|
|
1713
|
-
}
|
|
1801
|
+
if (autoSpawnScheduler && queueStrategy === 'local') {
|
|
1802
|
+
if (schedulerCommand.status !== 'ok') {
|
|
1803
|
+
console.log(`[server] Skipping scheduler auto-start — ${describeMissingModuleCommand(schedulerCommand)}`)
|
|
1804
|
+
} else {
|
|
1805
|
+
console.log('[server] Starting scheduler polling engine...')
|
|
1806
|
+
const schedulerProcess = spawn('node', [mercatoBin, 'scheduler', 'start'], {
|
|
1807
|
+
stdio: 'inherit',
|
|
1808
|
+
env: runtimeEnv,
|
|
1809
|
+
cwd: appDir,
|
|
1810
|
+
})
|
|
1811
|
+
processes.push(schedulerProcess)
|
|
1812
|
+
managedExitPromises.push(waitForManagedProcessExit(schedulerProcess, 'Scheduler polling engine'))
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1714
1815
|
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
stdio: 'inherit',
|
|
1719
|
-
env: runtimeEnv,
|
|
1720
|
-
cwd: appDir,
|
|
1721
|
-
})
|
|
1722
|
-
processes.push(schedulerProcess)
|
|
1723
|
-
managedExitPromises.push(waitForManagedProcessExit(schedulerProcess, 'Scheduler polling engine'))
|
|
1724
|
-
}
|
|
1816
|
+
const firstExit = await Promise.race(managedExitPromises)
|
|
1817
|
+
await cleanupAndWait()
|
|
1818
|
+
envChangePromiseResolve = null
|
|
1725
1819
|
|
|
1726
|
-
|
|
1820
|
+
if (isDevServerRestartResult(firstExit)) {
|
|
1821
|
+
console.log(`[server] Detected environment file change (${path.basename(firstExit.filePath)}). Restarting app runtime...`)
|
|
1822
|
+
continue
|
|
1823
|
+
}
|
|
1727
1824
|
|
|
1728
|
-
|
|
1825
|
+
if (!isExpectedManagedExitSignal(firstExit.signal)) {
|
|
1826
|
+
throw createManagedProcessExitError(firstExit)
|
|
1827
|
+
}
|
|
1729
1828
|
|
|
1730
|
-
|
|
1731
|
-
|
|
1829
|
+
stopping = true
|
|
1830
|
+
}
|
|
1831
|
+
} finally {
|
|
1832
|
+
stopEnvWatcher()
|
|
1732
1833
|
}
|
|
1733
1834
|
},
|
|
1734
1835
|
},
|
|
@@ -1746,6 +1847,7 @@ export async function run(argv = process.argv) {
|
|
|
1746
1847
|
const autoSpawnScheduler = process.env.AUTO_SPAWN_SCHEDULER !== 'false'
|
|
1747
1848
|
const queueStrategy = process.env.QUEUE_STRATEGY || 'local'
|
|
1748
1849
|
const runtimeEnv = buildServerProcessEnvironment(process.env)
|
|
1850
|
+
const schedulerCommand = lookupModuleCommand(getCliModules(), 'scheduler', 'start')
|
|
1749
1851
|
const serverStartLock = acquireServerStartLock(appDir, {
|
|
1750
1852
|
port: runtimeEnv.PORT ?? process.env.PORT ?? null,
|
|
1751
1853
|
})
|
|
@@ -1753,7 +1855,7 @@ export async function run(argv = process.argv) {
|
|
|
1753
1855
|
function cleanup() {
|
|
1754
1856
|
console.log('[server] Shutting down...')
|
|
1755
1857
|
for (const proc of processes) {
|
|
1756
|
-
if (!proc.killed) {
|
|
1858
|
+
if (!proc.killed && proc.exitCode === null && proc.signalCode === null) {
|
|
1757
1859
|
proc.kill('SIGTERM')
|
|
1758
1860
|
}
|
|
1759
1861
|
}
|
|
@@ -1765,7 +1867,7 @@ export async function run(argv = process.argv) {
|
|
|
1765
1867
|
processes.map(
|
|
1766
1868
|
(proc) =>
|
|
1767
1869
|
new Promise<void>((resolve) => {
|
|
1768
|
-
if (proc.exitCode !== null) return resolve()
|
|
1870
|
+
if (proc.exitCode !== null || proc.signalCode !== null) return resolve()
|
|
1769
1871
|
proc.on('exit', () => resolve())
|
|
1770
1872
|
})
|
|
1771
1873
|
)
|
|
@@ -1789,6 +1891,9 @@ export async function run(argv = process.argv) {
|
|
|
1789
1891
|
cwd: appDir,
|
|
1790
1892
|
})
|
|
1791
1893
|
processes.push(nextProcess)
|
|
1894
|
+
const managedExitPromises: Promise<ManagedProcessExitResult>[] = [
|
|
1895
|
+
waitForManagedProcessExit(nextProcess, 'Next.js production server'),
|
|
1896
|
+
]
|
|
1792
1897
|
|
|
1793
1898
|
// Start workers if enabled
|
|
1794
1899
|
if (autoSpawnWorkers) {
|
|
@@ -1803,30 +1908,32 @@ export async function run(argv = process.argv) {
|
|
|
1803
1908
|
cwd: appDir,
|
|
1804
1909
|
})
|
|
1805
1910
|
processes.push(workerProcess)
|
|
1911
|
+
managedExitPromises.push(waitForManagedProcessExit(workerProcess, formatQueueWorkerLabel(discoveredWorkerQueues)))
|
|
1806
1912
|
}
|
|
1807
1913
|
}
|
|
1808
1914
|
|
|
1809
1915
|
if (autoSpawnScheduler && queueStrategy === 'local') {
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1916
|
+
if (schedulerCommand.status !== 'ok') {
|
|
1917
|
+
console.log(`[server] Skipping scheduler auto-start — ${describeMissingModuleCommand(schedulerCommand)}`)
|
|
1918
|
+
} else {
|
|
1919
|
+
console.log('[server] Starting scheduler polling engine...')
|
|
1920
|
+
const schedulerProcess = spawn('node', [mercatoBin, 'scheduler', 'start'], {
|
|
1921
|
+
stdio: 'inherit',
|
|
1922
|
+
env: runtimeEnv,
|
|
1923
|
+
cwd: appDir,
|
|
1924
|
+
})
|
|
1925
|
+
processes.push(schedulerProcess)
|
|
1926
|
+
managedExitPromises.push(waitForManagedProcessExit(schedulerProcess, 'Scheduler polling engine'))
|
|
1927
|
+
}
|
|
1817
1928
|
}
|
|
1818
1929
|
|
|
1819
|
-
|
|
1820
|
-
await Promise.race(
|
|
1821
|
-
processes.map(
|
|
1822
|
-
(proc) =>
|
|
1823
|
-
new Promise<void>((resolve) => {
|
|
1824
|
-
proc.on('exit', () => resolve())
|
|
1825
|
-
})
|
|
1826
|
-
)
|
|
1827
|
-
)
|
|
1930
|
+
const firstExit = await Promise.race(managedExitPromises)
|
|
1828
1931
|
|
|
1829
1932
|
await cleanupAndWait()
|
|
1933
|
+
|
|
1934
|
+
if (!isExpectedManagedExitSignal(firstExit.signal)) {
|
|
1935
|
+
throw createManagedProcessExitError(firstExit)
|
|
1936
|
+
}
|
|
1830
1937
|
} finally {
|
|
1831
1938
|
serverStartLock.release()
|
|
1832
1939
|
}
|