Skip to content

Commit 055df44

Browse files
committed
fix(lifecycle): tighten disposal boundaries
1 parent 83a407f commit 055df44

6 files changed

Lines changed: 23 additions & 14 deletions

File tree

packages/opencode/src/project/instance-runtime.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import { type InstanceContext } from "./instance-context"
33
import { InstanceStore, type LoadInput } from "./instance-store"
44
import { Effect, Layer } from "effect"
55

6-
// Bridge for Promise/ALS callers that cannot yet yield InstanceStore.Service.
7-
// This keeps InstanceStore itself low-level while still giving legacy Hono and
8-
// CLI paths the production bootstrap implementation. Delete this module once
9-
// those callers are migrated to Effect boundaries that provide InstanceStore
10-
// directly, like the HttpApi middleware does.
6+
// Production InstanceStore wiring plus a bridge for Promise/ALS callers that
7+
// cannot yet yield InstanceStore.Service. This keeps InstanceStore itself
8+
// low-level while still giving legacy Hono and CLI paths the production
9+
// bootstrap implementation. Delete the Promise helpers once those callers are
10+
// migrated to Effect boundaries that provide InstanceStore directly.
1111
// Keep the bootstrap implementation import lazy: Instance is imported broadly,
1212
// and importing the app bootstrap graph at module load can trigger ESM cycles.
1313
export const layer = Layer.unwrap(

packages/opencode/src/server/global-lifecycle.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import { GlobalBus } from "@/bus/global"
22
import { InstanceStore } from "@/project/instance-store"
3+
import * as Log from "@opencode-ai/core/util/log"
34
import { Effect } from "effect"
45
import { Event } from "./event"
56

7+
const log = Log.create({ service: "server" })
8+
69
export const emitGlobalDisposed = Effect.sync(() =>
710
GlobalBus.emit("event", {
811
directory: "global",
@@ -17,9 +20,18 @@ export const disposeAllInstancesAndEmitGlobalDisposed = Effect.fn(
1720
"Server.disposeAllInstancesAndEmitGlobalDisposed",
1821
)(function* (options?: { swallowErrors?: boolean }) {
1922
const store = yield* InstanceStore.Service
20-
const dispose = store.disposeAll()
21-
yield* (options?.swallowErrors ? dispose.pipe(Effect.catch(() => Effect.void)) : dispose)
22-
yield* emitGlobalDisposed
23+
yield* Effect.gen(function* () {
24+
yield* (options?.swallowErrors
25+
? store.disposeAll().pipe(
26+
Effect.catchCause((cause) =>
27+
Effect.sync(() => {
28+
log.warn("global disposal failed", { cause })
29+
}),
30+
),
31+
)
32+
: store.disposeAll())
33+
yield* emitGlobalDisposed
34+
}).pipe(Effect.uninterruptible)
2335
})
2436

2537
export * as GlobalLifecycle from "./global-lifecycle"

packages/opencode/src/server/routes/instance/config.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { Hono } from "hono"
22
import { describeRoute, validator, resolver } from "hono-openapi"
3-
import z from "zod"
43
import { Config } from "@/config/config"
5-
import { Instance } from "@/project/instance"
4+
import { InstanceState } from "@/effect/instance-state"
65
import { InstanceStore } from "@/project/instance-store"
76
import { Provider } from "@/provider/provider"
87
import { errors } from "../../error"
@@ -59,7 +58,7 @@ export const ConfigRoutes = lazy(() =>
5958
const cfg = yield* Config.Service
6059
const store = yield* InstanceStore.Service
6160
yield* cfg.update(config)
62-
yield* store.dispose(Instance.current)
61+
yield* store.dispose(yield* InstanceState.context)
6362
return config
6463
}),
6564
)

packages/opencode/src/server/routes/instance/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import { ExperimentalRoutes } from "./experimental"
2525
import { ProviderRoutes } from "./provider"
2626
import { EventRoutes } from "./event"
2727
import { SyncRoutes } from "./sync"
28-
import { InstanceMiddleware } from "./middleware"
2928
import { jsonRequest } from "./trace"
3029

3130
export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => {

packages/opencode/test/config/tui.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { afterEach, beforeEach, expect, test } from "bun:test"
22
import path from "path"
33
import fs from "fs/promises"
44
import { provideTestInstance, tmpdir } from "../fixture/fixture"
5-
import { Instance } from "../../src/project/instance"
65
import { InstanceRuntime } from "@/project/instance-runtime"
76
import { TuiConfig } from "../../src/cli/cmd/tui/config/tui"
87
import { Config } from "@/config/config"

packages/opencode/test/plugin/auth-override.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ describe("plugin.auth-override", () => {
9191
expect(copilot.length).toBe(1)
9292
expect(copilot[0].label).toBe("Test Override Auth")
9393
expect(plainMethods[ProviderID.make("github-copilot")][0].label).not.toBe("Test Override Auth")
94-
}, 30000) // Increased timeout for plugin installation
94+
}, 30000)
9595
})
9696

9797
const file = path.join(import.meta.dir, "../../src/plugin/index.ts")

0 commit comments

Comments
 (0)