gang: track incomplete_tasks on-demand via bind/unbind hooks#507
Conversation
There was a problem hiding this comment.
Code Review
This pull request attempts to update the number of incomplete tasks when sessions are bound or unbound in the gang scheduler plugin. However, the feedback highlights a critical logic bug where modifying incomplete_tasks during binding and unbinding leads to double-counting and premature fulfillment of gang scheduling requirements, as a bound task is still incomplete. It is recommended to revert these changes.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| state.bound += 1; | ||
| state.incomplete_tasks = state.incomplete_tasks.saturating_sub(1); |
There was a problem hiding this comment.
Double-Counting & Premature Fulfillment Bug
Decrementing incomplete_tasks here introduces a critical logic bug:
- Conceptual Issue: A task bound to an executor is still incomplete (it is in
RunningorBindingstate, notSucceed/Failed/Cancelled). Therefore, binding a task does not reduce the number of incomplete tasks. - Double-Counting: The gang plugin evaluates fulfillment using
total >= needed, wheretotal = allocated + boundandneeded = div_ceil(incomplete_tasks, batch_size) * batch_size. If you decrementincomplete_tasks(reducingneeded) and incrementbound(increasingtotal) simultaneously, you double-count the progress.
For example, with batch_size = 2 and 4 pending tasks:
- Initially:
needed = 4,total = 0. - Bind 1 task:
needed = 4,total = 1. - Bind 2 tasks:
needed = 2,total = 2->is_fulfilledbecomestrueprematurely, leaving the remaining 2 tasks without executors.
Revert this change to keep incomplete_tasks static during the scheduling cycle.
| state.bound += 1; | |
| state.incomplete_tasks = state.incomplete_tasks.saturating_sub(1); | |
| state.bound += 1; |
| state.bound = state.bound.saturating_sub(1); | ||
| state.incomplete_tasks = state.incomplete_tasks.saturating_add(1); |
There was a problem hiding this comment.
Double-Counting & Premature Fulfillment Bug
Incrementing incomplete_tasks here is the inverse of the double-counting bug introduced in on_session_bind. Since unbinding a task does not change its completion status (it remains incomplete), incomplete_tasks should not be modified here. Revert this change to keep incomplete_tasks static during the scheduling cycle.
| state.bound = state.bound.saturating_sub(1); | |
| state.incomplete_tasks = state.incomplete_tasks.saturating_add(1); | |
| state.bound = state.bound.saturating_sub(1); |
Summary
Update GangPlugin to track
incomplete_tasksdynamically via bind/unbind hooks instead of relying solely on the snapshot value fromsetup().Changes
incomplete_tasksinon_session_bind()when a task is bound to an executorincomplete_tasksinon_session_unbind()when an executor is unboundMotivation
The
incomplete_tasksvalue was previously calculated once insetup()and remained static throughout the scheduling cycle. This could become stale as tasks are bound/unbound during the cycle. By updating it on-demand via hooks, the gang scheduling decisions (is_ready/is_fulfilled) now reflect the current state.Testing
All 21 gang plugin tests pass.