effect-flock-worker.ts 1.6 KB

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