effect-flock-worker.ts 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. import fs from "fs/promises"
  2. import os from "os"
  3. import { Effect, Layer } from "effect"
  4. import { AppFileSystem } from "@opencode-ai/shared/filesystem"
  5. import { EffectFlock } from "@opencode-ai/shared/util/effect-flock"
  6. import { Global } from "@opencode-ai/shared/global"
  7. type Msg = {
  8. key: string
  9. dir: string
  10. holdMs?: number
  11. ready?: string
  12. active?: string
  13. done?: string
  14. }
  15. function sleep(ms: number) {
  16. return new Promise<void>((resolve) => setTimeout(resolve, ms))
  17. }
  18. const msg: Msg = JSON.parse(process.argv[2]!)
  19. const testGlobal = Layer.succeed(
  20. Global.Service,
  21. Global.Service.of({
  22. home: os.homedir(),
  23. data: os.tmpdir(),
  24. cache: os.tmpdir(),
  25. config: os.tmpdir(),
  26. state: os.tmpdir(),
  27. bin: os.tmpdir(),
  28. log: os.tmpdir(),
  29. }),
  30. )
  31. const testLayer = EffectFlock.layer.pipe(Layer.provide(testGlobal), Layer.provide(AppFileSystem.defaultLayer))
  32. async function job() {
  33. if (msg.ready) await fs.writeFile(msg.ready, String(process.pid))
  34. if (msg.active) await fs.writeFile(msg.active, String(process.pid), { flag: "wx" })
  35. try {
  36. if (msg.holdMs && msg.holdMs > 0) await sleep(msg.holdMs)
  37. if (msg.done) await fs.appendFile(msg.done, "1\n")
  38. } finally {
  39. if (msg.active) await fs.rm(msg.active, { force: true })
  40. }
  41. }
  42. await Effect.runPromise(
  43. Effect.gen(function* () {
  44. const flock = yield* EffectFlock.Service
  45. yield* flock.withLock(
  46. Effect.promise(() => job()),
  47. msg.key,
  48. msg.dir,
  49. )
  50. }).pipe(Effect.provide(testLayer)),
  51. ).catch((err) => {
  52. const text = err instanceof Error ? (err.stack ?? err.message) : String(err)
  53. process.stderr.write(text)
  54. process.exit(1)
  55. })