fix(background-agent): prevent concurrency slot leaks on task startup failures
Unify slot ownership: processKey() owns the slot until task.concurrencyKey is set. Previously, startTask() released the slot on errors (session.create catch, createResult.error), but processKey() catch block didn't release, causing slot leaks when errors occurred between acquire() and task.concurrencyKey assignment. Changes: - Remove all pre-transfer release() calls in startTask() - Add conditional release in processKey() catch: only if task.concurrencyKey not set - Add validation for createResult.data?.id to catch malformed API responses This fixes 'Task failed to start within timeout' errors caused by exhausted concurrency slots that were never released.
This commit is contained in:
@@ -200,6 +200,11 @@ export class BackgroundManager {
|
||||
await this.startTask(item)
|
||||
} catch (error) {
|
||||
log("[background-agent] Error starting task:", error)
|
||||
// Release concurrency slot if startTask failed and didn't release it itself
|
||||
// This prevents slot leaks when errors occur after acquire but before task.concurrencyKey is set
|
||||
if (!item.task.concurrencyKey) {
|
||||
this.concurrencyManager.release(key)
|
||||
}
|
||||
}
|
||||
|
||||
queue.shift()
|
||||
@@ -240,16 +245,16 @@ export class BackgroundManager {
|
||||
query: {
|
||||
directory: parentDirectory,
|
||||
},
|
||||
}).catch((error) => {
|
||||
this.concurrencyManager.release(concurrencyKey)
|
||||
throw error
|
||||
})
|
||||
|
||||
if (createResult.error) {
|
||||
this.concurrencyManager.release(concurrencyKey)
|
||||
throw new Error(`Failed to create background session: ${createResult.error}`)
|
||||
}
|
||||
|
||||
if (!createResult.data?.id) {
|
||||
throw new Error("Failed to create background session: API returned no session ID")
|
||||
}
|
||||
|
||||
const sessionID = createResult.data.id
|
||||
subagentSessions.add(sessionID)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user