(
startPort = DEFAULT_START_PORT,
maxRetries = DEFAULT_MAX_PORT_RETRIES,
currentRetry = 0,
options = {}
)
| 29 | } |
| 30 | |
| 31 | async function findAvailablePortWithReservation( |
| 32 | startPort = DEFAULT_START_PORT, |
| 33 | maxRetries = DEFAULT_MAX_PORT_RETRIES, |
| 34 | currentRetry = 0, |
| 35 | options = {} |
| 36 | ) { |
| 37 | const createServer = options.createServer || net.createServer |
| 38 | const listenTimeoutMs = options.listenTimeoutMs ?? DEFAULT_PORT_PROBE_TIMEOUT_MS |
| 39 | const lastErrorCode = options.lastErrorCode |
| 40 | |
| 41 | if (currentRetry >= maxRetries) { |
| 42 | const errorSuffix = lastErrorCode ? ` Last error: ${lastErrorCode}.` : '' |
| 43 | throw new Error( |
| 44 | `Unable to find available port after ${maxRetries} attempts (tried ports ${startPort}-${startPort + maxRetries - 1}).${errorSuffix}` |
| 45 | ) |
| 46 | } |
| 47 | |
| 48 | const port = startPort + currentRetry |
| 49 | const result = await new Promise((resolve) => { |
| 50 | const server = createServer() |
| 51 | let completed = false |
| 52 | let timer = null |
| 53 | |
| 54 | const done = (value) => { |
| 55 | if (completed) return |
| 56 | completed = true |
| 57 | if (timer) clearTimeout(timer) |
| 58 | resolve(value) |
| 59 | } |
| 60 | |
| 61 | server.on('error', (error) => { |
| 62 | safeCloseServer(server) |
| 63 | done({ ok: false, errorCode: error?.code || 'UNKNOWN' }) |
| 64 | }) |
| 65 | |
| 66 | server.listen(port, () => { |
| 67 | done({ ok: true, port, reservationServer: server }) |
| 68 | }) |
| 69 | |
| 70 | timer = setTimeout(() => { |
| 71 | safeCloseServer(server) |
| 72 | done({ ok: false, errorCode: 'TIMEOUT' }) |
| 73 | }, listenTimeoutMs) |
| 74 | }) |
| 75 | |
| 76 | if (result.ok) { |
| 77 | return { port: result.port, reservationServer: result.reservationServer } |
| 78 | } |
| 79 | |
| 80 | return findAvailablePortWithReservation(startPort, maxRetries, currentRetry + 1, { |
| 81 | ...options, |
| 82 | lastErrorCode: result.errorCode, |
| 83 | }) |
| 84 | } |
| 85 | |
| 86 | async function terminateProcess(proc, { forceKillTimeoutMs = DEFAULT_FORCE_KILL_TIMEOUT_MS } = {}) { |
| 87 | if (!proc) return |
nothing calls this directly
no test coverage detected