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