From a147ad68e6aed8a6a3eeaf2ce1e56f73fab7fa31 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Wed, 15 Apr 2026 20:55:14 -0400 Subject: feat(shared): add Effect-idiomatic file lock (EffectFlock) (#22681) --- .../shared/test/fixture/effect-flock-worker.ts | 64 ++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 packages/shared/test/fixture/effect-flock-worker.ts (limited to 'packages/shared/test/fixture') diff --git a/packages/shared/test/fixture/effect-flock-worker.ts b/packages/shared/test/fixture/effect-flock-worker.ts new file mode 100644 index 000000000..7fd2e144a --- /dev/null +++ b/packages/shared/test/fixture/effect-flock-worker.ts @@ -0,0 +1,64 @@ +import fs from "fs/promises" +import path from "path" +import os from "os" +import { Effect, Layer } from "effect" +import { AppFileSystem } from "@opencode-ai/shared/filesystem" +import { EffectFlock } from "@opencode-ai/shared/util/effect-flock" +import { Global } from "@opencode-ai/shared/global" + +type Msg = { + key: string + dir: string + holdMs?: number + ready?: string + active?: string + done?: string +} + +function sleep(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)) +} + +const msg: Msg = JSON.parse(process.argv[2]!) + +const testGlobal = Layer.succeed( + Global.Service, + Global.Service.of({ + home: os.homedir(), + data: os.tmpdir(), + cache: os.tmpdir(), + config: os.tmpdir(), + state: os.tmpdir(), + bin: os.tmpdir(), + log: os.tmpdir(), + }), +) + +const testLayer = EffectFlock.layer.pipe(Layer.provide(testGlobal), Layer.provide(AppFileSystem.defaultLayer)) + +async function job() { + if (msg.ready) await fs.writeFile(msg.ready, String(process.pid)) + if (msg.active) await fs.writeFile(msg.active, String(process.pid), { flag: "wx" }) + + try { + if (msg.holdMs && msg.holdMs > 0) await sleep(msg.holdMs) + if (msg.done) await fs.appendFile(msg.done, "1\n") + } finally { + if (msg.active) await fs.rm(msg.active, { force: true }) + } +} + +await Effect.runPromise( + Effect.gen(function* () { + const flock = yield* EffectFlock.Service + yield* flock.withLock( + Effect.promise(() => job()), + msg.key, + msg.dir, + ) + }).pipe(Effect.provide(testLayer)), +).catch((err) => { + const text = err instanceof Error ? (err.stack ?? err.message) : String(err) + process.stderr.write(text) + process.exit(1) +}) -- cgit v1.2.3