fix: serialize runtime cleanup

This commit is contained in:
lofyer
2026-08-13 01:36:00 +08:00
parent fd1ff92927
commit 8cd23bada1
4 changed files with 206 additions and 4 deletions
+50 -2
View File
@@ -544,6 +544,7 @@ export class OpenCodeRuntime implements AgentRuntime {
}
>()
private embeddedRunTail: Promise<void> = Promise.resolve()
private readonly conversationRunTails = new Map<string, Promise<void>>()
private readonly dependencies: OpenCodeRuntimeDependencies
constructor(
@@ -594,6 +595,47 @@ export class OpenCodeRuntime implements AgentRuntime {
}
}
private async acquireConversationRun(
conversationId: string,
signal: AbortSignal
): Promise<() => void> {
signal.throwIfAborted()
const previous =
this.conversationRunTails.get(conversationId) ?? Promise.resolve()
let releaseGate!: () => void
const gate = new Promise<void>((resolve) => {
releaseGate = resolve
})
const tail = previous.then(
() => gate,
() => gate
)
this.conversationRunTails.set(conversationId, tail)
let abort!: () => void
const aborted = new Promise<never>((_resolve, reject) => {
abort = () => reject(signal.reason)
})
signal.addEventListener('abort', abort, { once: true })
try {
await Promise.race([previous, aborted])
signal.throwIfAborted()
return () => {
releaseGate()
if (this.conversationRunTails.get(conversationId) === tail) {
this.conversationRunTails.delete(conversationId)
}
}
} catch (error) {
releaseGate()
if (this.conversationRunTails.get(conversationId) === tail) {
this.conversationRunTails.delete(conversationId)
}
throw error
} finally {
signal.removeEventListener('abort', abort)
}
}
private terminate(child: SpawnedProcess): void {
if (child.exitCode !== null) {
return
@@ -1030,13 +1072,18 @@ export class OpenCodeRuntime implements AgentRuntime {
request: AgentExecutionRequest,
signal: AbortSignal
): AsyncGenerator<RuntimeEvent, void, void> {
const release = this.usesEmbeddedPermissionMediation()
const releaseEmbedded = this.usesEmbeddedPermissionMediation()
? await this.acquireEmbeddedRun(signal)
: undefined
const releaseConversation = await this.acquireConversationRun(
request.conversationId,
signal
)
try {
yield* this.runUnlocked(request, signal)
} finally {
release?.()
releaseConversation()
releaseEmbedded?.()
}
}
@@ -1643,6 +1690,7 @@ export class OpenCodeRuntime implements AgentRuntime {
this.clientInitialization = undefined
this.sessions.clear()
this.sessionInitializations.clear()
this.conversationRunTails.clear()
await server?.close()
}