fix(kanban): forward concurrency caps from dashboard /dispatch endpoint - #83499
Closed
rickhuizinga wants to merge 1 commit into
Closed
fix(kanban): forward concurrency caps from dashboard /dispatch endpoint#83499rickhuizinga wants to merge 1 commit into
rickhuizinga wants to merge 1 commit into
Conversation
The dashboard POST /dispatch endpoint calls dispatch_once() without forwarding max_in_progress_per_profile, max_in_progress, default_assignee, or failure_limit from kanban config. This means the dashboard bypasses per-profile and global concurrency caps entirely. The Desktop app auto-nudges the dispatcher after every board write (autoNudge in api.ts), so every task create/unblock/reassign triggers a dispatch_once that ignores the caps — causing all ready tasks for a profile to spawn simultaneously. The fix reads the same config keys using the same _coerce_positive_int helper already used by the CLI path (kanban.py _cmd_dispatch) and the gateway watcher (kanban_watchers.py), then forwards all four params to dispatch_once. The gateway and CLI already do this; the dashboard was the only caller that didn't.
Collaborator
Author
|
Thanks for the quick triage! Closing in favor of #81382 — it's more complete (regression tests, |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The dashboard's
POST /dispatchendpoint (plugins/kanban/dashboard/plugin_api.py) callsdispatch_once()without forwardingmax_in_progress_per_profile,max_in_progress,default_assignee, orfailure_limitfrom the kanban config. When these parameters areNone, the enforcement logic in_dispatch_once_lockedskips the cap checks entirely.This means the dashboard bypasses per-profile and global concurrency caps that the gateway tick and CLI correctly enforce.
Impact
The Desktop app's Kanban plugin auto-nudges the dispatcher after every board write (
autoNudgeinapps/desktop/src/plugins/kanban/api.ts— debounced 400ms, fire-and-forget). EverypatchTask,createTask,deleteTask,bulkTasks,reassignTask, andreclaimTaskcall triggers aPOST /dispatch.Because the dashboard endpoint doesn't forward
max_in_progress_per_profile, a user withkanban.max_in_progress_per_profile: 1who creates or unblocks multiple tasks for the same profile through the Desktop Kanban plugin sees all of them spawn simultaneously, bypassing the cap. The gateway's 60-second tick enforces the cap correctly, but the dashboard's immediate dispatch circumvents it before the tick runs.The old Dashboard web app does not have this problem — it only calls
/dispatchwhen the user explicitly clicks "Nudge dispatcher".Root Cause
Three callers invoke
dispatch_once():kanban_watchers.py)_cmd_dispatch(kanban.py)/dispatch(plugin_api.py)Fix
Read the same config keys using the same
_coerce_positive_inthelper already used by the CLI path (kanban.py:_cmd_dispatch), then forward all four parameters todispatch_once(). The config-reading block is copied verbatim from the CLI path to ensure identical semantics.Parameters now forwarded
max_in_progress_per_profile— per-profile concurrency cap ([Feature]: limit tasks per profile in kanban #21582)max_in_progress— global concurrency cap ([Bug]: hermes kanban dispatch command doesn't pass max_in_progress to dispatch_once #33488)default_assignee— fallback profile for unassigned ready tasks (feat(kanban): auto-assign unassigned ready tasks in dispatcher #27145)failure_limit— consecutive spawn failure threshold before auto-blockBackward compatibility
The
try/exceptfallback (matching the CLI path) ensures that ifload_config()fails, all caps fall back toNone(disabled) — identical to the current behavior. Users without these config keys set see no change.Follow-up (not in this PR)
The config-reading logic is now duplicated across three call sites. A future refactor could extract a shared
dispatch_config_from_config()helper that returns a dataclass, so all three callers use one implementation.