(input: {
hostname: string;
scopeId: string;
})
| 310 | }; |
| 311 | |
| 312 | export const acquireDaemonStartLock = (input: { |
| 313 | hostname: string; |
| 314 | scopeId: string; |
| 315 | }): Effect.Effect<DaemonStartLock, Error, FileSystem.FileSystem | Path.Path> => |
| 316 | Effect.gen(function* () { |
| 317 | const fs = yield* FileSystem.FileSystem; |
| 318 | const path = yield* Path.Path; |
| 319 | const dataDir = resolveDaemonDataDir(path); |
| 320 | yield* fs.makeDirectory(dataDir, { recursive: true }); |
| 321 | |
| 322 | const lockPath = daemonStartLockPath(path, input); |
| 323 | const lockPayload = JSON.stringify( |
| 324 | { |
| 325 | pid: process.pid, |
| 326 | hostname: canonicalDaemonHost(input.hostname), |
| 327 | scopeId: input.scopeId, |
| 328 | startedAt: new Date().toISOString(), |
| 329 | }, |
| 330 | null, |
| 331 | 2, |
| 332 | ); |
| 333 | |
| 334 | const tryAcquire = () => |
| 335 | fs.writeFileString(lockPath, `${lockPayload}\n`, { flag: "wx" }).pipe( |
| 336 | Effect.as(true), |
| 337 | Effect.catchCause(() => Effect.succeed(false)), |
| 338 | ); |
| 339 | |
| 340 | if (yield* tryAcquire()) { |
| 341 | return { |
| 342 | path: lockPath, |
| 343 | hostname: canonicalDaemonHost(input.hostname), |
| 344 | scopeId: input.scopeId, |
| 345 | }; |
| 346 | } |
| 347 | |
| 348 | const existingRaw = yield* fs |
| 349 | .readFileString(lockPath) |
| 350 | .pipe(Effect.catchCause(() => Effect.succeed(null))); |
| 351 | if (existingRaw !== null) { |
| 352 | const existingPid = parseLockPid(existingRaw); |
| 353 | if (existingPid !== null && !isPidAlive(existingPid)) { |
| 354 | yield* fs.remove(lockPath, { force: true }); |
| 355 | if (yield* tryAcquire()) { |
| 356 | return { |
| 357 | path: lockPath, |
| 358 | hostname: canonicalDaemonHost(input.hostname), |
| 359 | scopeId: input.scopeId, |
| 360 | }; |
| 361 | } |
| 362 | } |
| 363 | } |
| 364 | |
| 365 | return yield* Effect.fail( |
| 366 | new Error( |
| 367 | `Another daemon startup is already in progress for ${canonicalDaemonHost(input.hostname)} (${input.scopeId}).`, |
| 368 | ), |
| 369 | ); |
no test coverage detected