fix(triage): respect global concurrency limit before queuing tasks

The triage processor was kicking off all eligible tasks simultaneously,
queuing them all on the semaphore regardless of available slots. Now it
checks semaphore.availableCount first and only starts as many triage
tasks as there are free slots. Remaining tasks get picked up on the
next poll cycle (default 10-15s) as slots free up.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-13 15:06:29 -07:00
parent cac0837ea6
commit ae91e8cfd0

View File

@@ -474,8 +474,16 @@ export class TriageProcessor {
&& !(t.nextRecoveryAt && new Date(t.nextRecoveryAt).getTime() > now), && !(t.nextRecoveryAt && new Date(t.nextRecoveryAt).getTime() > now),
); );
for (const task of triageTasks) { // Respect the global concurrency limit — only kick off as many triage
void this.specifyTask(task); // tasks as the semaphore has available slots. Without this gate, all
// eligible tasks queue on the semaphore simultaneously, which is
// wasteful and confusing in the UI.
const maxToStart = this.options.semaphore
? Math.max(0, this.options.semaphore.availableCount)
: triageTasks.length;
for (let i = 0; i < Math.min(triageTasks.length, maxToStart); i++) {
void this.specifyTask(triageTasks[i]);
} }
} catch (err) { } catch (err) {
triageLog.error("Poll error:", err); triageLog.error("Poll error:", err);