fix(shared): add timeout to isSessionActive to prevent infinite hang
The SDK client disables fetch timeout (req.timeout = false). When the opencode server is slow or unresponsive, client.session.status() hangs forever, blocking the entire dispatchToHooks chain (sequential await) and deadlocking the plugin. Add a 5s timeout wrapper around the status call in isSessionActive(). On timeout, the catch block returns false (treat as inactive), letting the caller proceed instead of hanging indefinitely. The timeout parameter is exposed for testing to avoid 5s test delays. Refs: .debugging/status-timeout-hang.md
This commit is contained in:
@@ -505,4 +505,32 @@ describe("promptAsyncAfterSessionIdle", () => {
|
||||
response: { accepted: true, sessionID: "ses_bound_prompt" },
|
||||
})
|
||||
})
|
||||
|
||||
test("#given session.status hangs forever #when promptAsync gate checks activity #then it dispatches after status timeout", { timeout: 10_000 }, async () => {
|
||||
// given
|
||||
let promptCalls = 0
|
||||
const neverSettles = new Promise<never>(() => {})
|
||||
const client = {
|
||||
session: {
|
||||
status: () => neverSettles,
|
||||
promptAsync: async () => {
|
||||
promptCalls += 1
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// when
|
||||
const result = await promptAsyncAfterSessionIdle({
|
||||
client,
|
||||
sessionID: "ses_status_timeout",
|
||||
input: { path: { id: "ses_status_timeout" }, body: { parts: [] } },
|
||||
source: "test:status-timeout",
|
||||
settleMs: 0,
|
||||
postDispatchHoldMs: 0,
|
||||
})
|
||||
|
||||
// then
|
||||
expect(result.status).toBe("dispatched")
|
||||
expect(promptCalls).toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -52,4 +52,20 @@ describe("session idle prompt guard", () => {
|
||||
// then
|
||||
expect(shouldPrompt).toBe(true)
|
||||
})
|
||||
|
||||
test("#given session.status hangs forever #when checking active session #then it returns false after timeout", async () => {
|
||||
// given
|
||||
const neverSettles = new Promise<never>(() => {})
|
||||
const client = {
|
||||
session: {
|
||||
status: () => neverSettles,
|
||||
},
|
||||
}
|
||||
|
||||
// when
|
||||
const active = await isSessionActive(client, "ses-hang", 50)
|
||||
|
||||
// then
|
||||
expect(active).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user