(input: {
port: number;
hostname: string;
allowedHosts: ReadonlyArray<string>;
authToken: string | undefined;
})
| 1183 | }); |
| 1184 | |
| 1185 | const runDaemonSession = (input: { |
| 1186 | port: number; |
| 1187 | hostname: string; |
| 1188 | allowedHosts: ReadonlyArray<string>; |
| 1189 | authToken: string | undefined; |
| 1190 | }) => |
| 1191 | Effect.gen(function* () { |
| 1192 | const daemonHost = canonicalDaemonHost(input.hostname); |
| 1193 | const restoreWebBaseUrl = installDefaultExecutorWebBaseUrl( |
| 1194 | daemonBaseUrl(daemonHost, input.port), |
| 1195 | ); |
| 1196 | const scopeId = currentDaemonScopeId(); |
| 1197 | |
| 1198 | try { |
| 1199 | // No process-level startup lock: the DB ownership lock acquired inside |
| 1200 | // startServer (openOwnedLocalDatabase) is the real gate. server.json and |
| 1201 | // the daemon pointer are attach/dedup hints, and the checks below are |
| 1202 | // friendly fast-paths that may race without being unsafe. |
| 1203 | |
| 1204 | // A supervised daemon (launchd/systemd) is the OS-guaranteed singleton |
| 1205 | // — kickstart -k kills the old instance before starting the new — so any |
| 1206 | // server.json from a previous boot is stale. Reclaim it rather than |
| 1207 | // refusing: across a reboot the recorded pid may have been recycled by |
| 1208 | // an unrelated process, which would otherwise make the "is one already |
| 1209 | // running?" check treat it as alive-but-unreachable, refuse to start, |
| 1210 | // and crash-loop under KeepAlive. (Found by a real reboot test with |
| 1211 | // integration data in the DB.) |
| 1212 | if (process.env.EXECUTOR_SUPERVISED) { |
| 1213 | yield* takeOverActiveLocalServer().pipe(Effect.ignore); |
| 1214 | } else { |
| 1215 | yield* assertNoOtherActiveLocalServer(); |
| 1216 | } |
| 1217 | |
| 1218 | const existing = yield* readDaemonPointer({ hostname: daemonHost, scopeId }); |
| 1219 | |
| 1220 | if (existing) { |
| 1221 | const existingUrl = daemonBaseUrl(existing.hostname, existing.port); |
| 1222 | if (isPidAlive(existing.pid) && (yield* isServerReachable(existingUrl))) { |
| 1223 | if (process.env.EXECUTOR_SUPERVISED) { |
| 1224 | yield* terminatePid(existing.pid).pipe(Effect.ignore); |
| 1225 | const stopped = yield* waitForUnreachable({ |
| 1226 | check: isServerReachable(existingUrl), |
| 1227 | timeoutMs: DAEMON_STOP_TIMEOUT_MS, |
| 1228 | intervalMs: DAEMON_BOOT_POLL_MS, |
| 1229 | }); |
| 1230 | if (!stopped) { |
| 1231 | return yield* Effect.fail( |
| 1232 | new Error( |
| 1233 | [ |
| 1234 | `The existing daemon for scope ${scopeId} at ${existingUrl} (pid ${existing.pid}) did not stop within ${DAEMON_STOP_TIMEOUT_MS / 1000}s.`, |
| 1235 | "Stop it manually and re-run.", |
| 1236 | ].join("\n"), |
| 1237 | ), |
| 1238 | ); |
| 1239 | } |
| 1240 | } else { |
| 1241 | return yield* Effect.fail( |
| 1242 | new Error( |
no test coverage detected