cubemaster: fix ceiling division in the scheduler concurrency limits - #1465
cubemaster: fix ceiling division in the scheduler concurrency limits#1465dwin-gharibi wants to merge 1 commit into
Conversation
…ision Signed-off-by: Dwin Gharibi <dwin.gharibi@email.kntu.ac.ir>
| "testing" | ||
| ) | ||
|
|
||
| func perNodeCreateLimit(totalLimitCreate, healthyNodes int64) int64 { |
There was a problem hiding this comment.
These tests assert on perNodeCreateLimit / clusterLimit — helpers that re-implement the fixed formulas rather than calling the production code. Since they're decoupled from the expressions inside monitorLimit() in local.go, a future change that reintroduces the * 1.0 integer-truncation pattern in local.go would leave these tests green, so the stated goal ("a future refactor cannot silently reintroduce truncation") isn't fully met. Consider extracting the per-node and cluster-limit computations into shared package-level functions that both monitorLimit() and these tests call, so the tests guard the real production path.
Review: cubemaster: fix ceiling division in the scheduler concurrency limits (#1465)Verdict: Approve — correct bug fix, one test-coverage improvement worth makingThe PR correctly identifies and fixes a real bug. The three expressions of the form
The fix (
The behavior change (limits round up by one unit in non-exact divisions) is intentional and Finding (minor)The new tests don't exercise the production code path. Optional suggestionFor these small positive-integer counts, an integer ceiling-division idiom — AI-generated review — findings are advisory; a human maintainer should confirm before merging. |
Closes #1464.
Motivation
Three limit calculations were written as
int64(math.Ceil(float64(a * b * 1.0 / c))). Every operandis
int64and the untyped constant1.0is representable as an integer, so it converts toint64and the whole inner expression is integer arithmetic — it truncates.
math.Ceilthen runs on analready-integral value and does nothing.
The
* 1.0factors show the intent was float division and round-up. What actually happens isround-down, so whenever the node counts do not divide evenly the cluster runs one unit below its
configured create/destroy concurrency.
What this changes
CubeMaster/pkg/scheduler/local.go— convert tofloat64before dividing, at all three sites::283float64(totalLimitCreate*1.0/newHealthyNodes)float64(totalLimitCreate)/float64(newHealthyNodes):286float64(newHealthyNodes * newCreateLimitOfEveryNode * 1.0 / newMasterNodes)float64(newHealthyNodes*newCreateLimitOfEveryNode) / float64(newMasterNodes):309float64(newHealthyNodes * newLimitDesroyOfEveryNode * 1.0 / newMasterNodes)float64(newHealthyNodes*newLimitDesroyOfEveryNode) / float64(newMasterNodes)The numerator product stays in
int64(it is a small count product, nowhere near overflow) and onlythe division becomes floating point, which is the minimal change that makes
math.Ceilmeaningful.No comment changes.
Testing
New:
CubeMaster/pkg/scheduler/local_limit_math_test.go— table tests pinning the rounding for bothshapes, including the exact cases from the issue (
10/3 → 4,4*5/3 → 7) plus exact-division andn < divisorcases so a future refactor cannot silently reintroduce truncation.CI gates checked locally:
gofmt -l ./pkg— clean (fmt-check).GOOS=linux go build ./...— clean.staticcheck -checks 'SA4015' ./pkg/scheduler/— the threelocal.gofindings are gone.Risk / rollout
Behaviour change by design: create and destroy concurrency will increase by one unit in clusters
where the division was not exact. That is the configured intent, but it does mean slightly more
in-flight work per node after this lands — worth noting if a cluster was unknowingly relying on the
lower effective limit.
pkg/selector/score/realtimescore_test.go:40-41has the samemath.Ceil-on-integer pattern in atest; left alone here to keep this PR single-purpose.