diff options
| author | Dax <[email protected]> | 2026-04-16 03:02:19 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-04-16 03:02:19 -0400 |
| commit | 3f7df08be97a0a6f6d224c1c8c93ace80ad97c33 (patch) | |
| tree | 2b9ccda9e4c50f31517d9a7844790ec05201c6a4 | |
| parent | ef6c26c730c7767ec5fc904927f2c5f1628de190 (diff) | |
| download | opencode-3f7df08be97a0a6f6d224c1c8c93ace80ad97c33.tar.gz opencode-3f7df08be97a0a6f6d224c1c8c93ace80ad97c33.zip | |
perf: make vcs init non-blocking by forking git branch resolution (#22771)
| -rw-r--r-- | packages/opencode/AGENTS.md | 6 | ||||
| -rw-r--r-- | packages/opencode/src/project/vcs.ts | 5 |
2 files changed, 9 insertions, 2 deletions
diff --git a/packages/opencode/AGENTS.md b/packages/opencode/AGENTS.md index fd9e597e7..f0f32fdd1 100644 --- a/packages/opencode/AGENTS.md +++ b/packages/opencode/AGENTS.md @@ -39,6 +39,12 @@ See `specs/effect/migration.md` for the compact pattern reference and examples. - Do the work directly in the `InstanceState.make` closure — `ScopedCache` handles run-once semantics. Don't add fibers, `ensure()` callbacks, or `started` flags on top. - Use `Effect.addFinalizer` or `Effect.acquireRelease` inside the `InstanceState.make` closure for cleanup (subscriptions, process teardown, etc.). - Use `Effect.forkScoped` inside the closure for background stream consumers — the fiber is interrupted when the instance is disposed. +- To make a service's `init()` non-blocking, fork `InstanceState.get(state)` at the `init()` call site (e.g. `Effect.forkIn(scope)`), not by forking work inside the `InstanceState.make` closure. Forking inside the closure leaves state incomplete for other methods that read it. +- `src/project/bootstrap.ts` already wraps every service `init()` in `Effect.forkDetach`, so `init()` is fire-and-forget in production. Keep `init()` methods synchronous internally; the caller controls concurrency. + +## Effect v4 beta API + +- `Effect.fork` and `Effect.forkDaemon` do not exist. Use `Effect.forkIn(scope)` to fork a fiber into a specific scope. ## Preferred Effect services diff --git a/packages/opencode/src/project/vcs.ts b/packages/opencode/src/project/vcs.ts index 559371859..b1375a7b7 100644 --- a/packages/opencode/src/project/vcs.ts +++ b/packages/opencode/src/project/vcs.ts @@ -1,4 +1,4 @@ -import { Effect, Layer, Context, Stream } from "effect" +import { Effect, Layer, Context, Stream, Scope } from "effect" import { formatPatch, structuredPatch } from "diff" import path from "path" import { Bus } from "@/bus" @@ -157,6 +157,7 @@ export const layer: Layer.Layer<Service, never, AppFileSystem.Service | Git.Serv const fs = yield* AppFileSystem.Service const git = yield* Git.Service const bus = yield* Bus.Service + const scope = yield* Scope.Scope const state = yield* InstanceState.make<State>( Effect.fn("Vcs.state")(function* (ctx) { @@ -194,7 +195,7 @@ export const layer: Layer.Layer<Service, never, AppFileSystem.Service | Git.Serv return Service.of({ init: Effect.fn("Vcs.init")(function* () { - yield* InstanceState.get(state) + yield* InstanceState.get(state).pipe(Effect.forkIn(scope)) }), branch: Effect.fn("Vcs.branch")(function* () { return yield* InstanceState.use(state, (x) => x.current) |
