fix(core): release unread Console config responses (#53409)

This commit is contained in:
Kit Langton
2026-10-05 11:59:54 -07:00
committed by GitHub
Unverified
parent 54630586a7
commit a701129184
2 changed files with 27 additions and 1 deletions
@@ -470,7 +470,8 @@ export const OpencodePlugin = define<HttpClient.HttpClient | Bus.Service | Manag
})
function fetchConfig(http: HttpClient.HttpClient, value: Credential.Value) {
return http
// Scoped so responses whose body is never read (404, errors) are released here instead of by a GC-time abort.
return HttpClient.withScope(http)
.execute(
HttpClientRequest.get(`${serverUrl(value)}/api/v2/config`).pipe(
HttpClientRequest.acceptJson,
@@ -498,6 +499,7 @@ function fetchConfig(http: HttpClient.HttpClient, value: Credential.Value) {
)
}),
),
Effect.scoped,
)
}
@@ -1072,6 +1072,30 @@ describe("OpencodePlugin", () => {
),
)
it.effect("releases unread Console config responses when the fetch completes", () =>
Effect.gen(function* () {
const credentials = yield* Credential.Service
const signals: AbortSignal[] = []
const state = { status: 404 }
const http = HttpClient.make((request, _url, signal) => {
signals.push(signal)
return Effect.succeed(HttpClientResponse.fromWeb(request, new Response("unavailable", state)))
})
yield* credentials.create({
integrationID: Integration.ID.make("opencode"),
value: Credential.Key.make({ type: "key", key: "secret", metadata: { server: "https://console.test" } }),
})
yield* addPlugin().pipe(Effect.provideService(HttpClient.HttpClient, http))
yield* drain
state.status = 503
yield* TestClock.adjust("1 minute")
yield* drain
// An unreleased response is only aborted when garbage collected, which fails outside a request on workerd.
expect(signals.map((signal) => signal.aborted)).toEqual([true, true])
}),
)
it.effect("reports a rejected Console refresh token as signed out without removing the credential", () =>
Effect.acquireUseRelease(
Effect.sync(() =>