Skip to content

[release-1.14] Fix unbounded job.Status.Conditions growth - #5448

Merged
volcano-sh-bot merged 4 commits into
volcano-sh:release-1.14from
volcano-sh-bot:cherry-pick-5422-to-release-1.14
Jun 15, 2026
Merged

[release-1.14] Fix unbounded job.Status.Conditions growth#5448
volcano-sh-bot merged 4 commits into
volcano-sh:release-1.14from
volcano-sh-bot:cherry-pick-5422-to-release-1.14

Conversation

@volcano-sh-bot

Copy link
Copy Markdown
Contributor

This is an automated cherry-pick of #5422

This adds a maxJobConditions cap (32) and deduplicates consecutive identical condition phases, preventing etcd object-size exceeded errors when frequently retrying jobs.

Signed-off-by: Avinash Kumar Deepak <avinash8655279@gmail.com>
Allocates a new slice and copies elements instead of slicing the existing array, ensuring old pointers are safely garbage collected.

Signed-off-by: Avinash Kumar Deepak <avinash8655279@gmail.com>
Signed-off-by: Avinash Kumar Deepak <avinash8655279@gmail.com>
Signed-off-by: Avinash Kumar Deepak <avinash8655279@gmail.com>
@volcano-sh-bot volcano-sh-bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Jun 15, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a helper function appendJobCondition to deduplicate and append job status conditions, replacing direct slice appends across the controller, and adds corresponding unit tests. The review feedback suggests optimizing the slice pre-allocation capacity in the helper function to avoid reallocation, and strengthening the unit tests by asserting the exact slice structure using reflect.DeepEqual instead of only checking the length and the last element.

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.

// appendJobCondition appends c to conditions. If a condition with the same
// phase already exists, it is removed and the new condition is appended at the end.
func appendJobCondition(conditions []batch.JobCondition, c batch.JobCondition) []batch.JobCondition {
res := make([]batch.JobCondition, 0, len(conditions))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Pre-allocating the slice with a capacity of len(conditions) + 1 avoids a potential slice reallocation and memory copy when appending the new condition c (especially when c.Status is a new phase not present in the existing conditions).

Suggested change
res := make([]batch.JobCondition, 0, len(conditions))
res := make([]batch.JobCondition, 0, len(conditions)+1)

Comment on lines +1485 to +1541
func TestAppendJobCondition(t *testing.T) {
testcases := []struct {
Name string
Conditions []v1alpha1.JobCondition
NewCondition v1alpha1.JobCondition
ExpectedLen int
ExpectedPhase v1alpha1.JobPhase
}{
{
Name: "Append to empty conditions",
Conditions: []v1alpha1.JobCondition{},
NewCondition: v1alpha1.JobCondition{
Status: v1alpha1.Pending,
},
ExpectedLen: 1,
ExpectedPhase: v1alpha1.Pending,
},
{
Name: "Replace existing condition with same phase",
Conditions: []v1alpha1.JobCondition{
{Status: v1alpha1.Pending},
{Status: v1alpha1.Running},
},
NewCondition: v1alpha1.JobCondition{
Status: v1alpha1.Pending,
},
ExpectedLen: 2,
ExpectedPhase: v1alpha1.Pending,
},
{
Name: "Append if phase is different",
Conditions: []v1alpha1.JobCondition{
{Status: v1alpha1.Pending},
{Status: v1alpha1.Running},
},
NewCondition: v1alpha1.JobCondition{
Status: v1alpha1.Completed,
},
ExpectedLen: 3,
ExpectedPhase: v1alpha1.Completed,
},
}

for _, tc := range testcases {
t.Run(tc.Name, func(t *testing.T) {
result := appendJobCondition(tc.Conditions, tc.NewCondition)

if len(result) != tc.ExpectedLen {
t.Errorf("Expected length %d, got %d", tc.ExpectedLen, len(result))
}

if result[len(result)-1].Status != tc.ExpectedPhase {
t.Errorf("Expected last phase %v, got %v", tc.ExpectedPhase, result[len(result)-1].Status)
}
})
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current assertions only verify the length of the resulting slice and the status of the last element. This is a weak assertion that could pass even if the deduplication logic is incorrect (e.g., if other elements are lost or the order is wrong). Comparing the exact expected slice using reflect.DeepEqual makes the test much more robust and precise.

func TestAppendJobCondition(t *testing.T) {
	testcases := []struct {
		Name               string
		Conditions         []v1alpha1.JobCondition
		NewCondition       v1alpha1.JobCondition
		ExpectedConditions []v1alpha1.JobCondition
	}{
		{
			Name:       "Append to empty conditions",
			Conditions: []v1alpha1.JobCondition{},
			NewCondition: v1alpha1.JobCondition{
				Status: v1alpha1.Pending,
			},
			ExpectedConditions: []v1alpha1.JobCondition{
				{Status: v1alpha1.Pending},
			},
		},
		{
			Name: "Replace existing condition with same phase",
			Conditions: []v1alpha1.JobCondition{
				{Status: v1alpha1.Pending},
				{Status: v1alpha1.Running},
			},
			NewCondition: v1alpha1.JobCondition{
				Status: v1alpha1.Pending,
			},
			ExpectedConditions: []v1alpha1.JobCondition{
				{Status: v1alpha1.Running},
				{Status: v1alpha1.Pending},
			},
		},
		{
			Name: "Append if phase is different",
			Conditions: []v1alpha1.JobCondition{
				{Status: v1alpha1.Pending},
				{Status: v1alpha1.Running},
			},
			NewCondition: v1alpha1.JobCondition{
				Status: v1alpha1.Completed,
			},
			ExpectedConditions: []v1alpha1.JobCondition{
				{Status: v1alpha1.Pending},
				{Status: v1alpha1.Running},
				{Status: v1alpha1.Completed},
			},
		},
	}

	for _, tc := range testcases {
		t.Run(tc.Name, func(t *testing.T) {
			result := appendJobCondition(tc.Conditions, tc.NewCondition)

			if !reflect.DeepEqual(result, tc.ExpectedConditions) {
				t.Errorf("Expected conditions %v, got %v", tc.ExpectedConditions, result)
			}
		})
	}
}

@JesseStutler

Copy link
Copy Markdown
Member

/approve
/lgtm

@volcano-sh-bot volcano-sh-bot added the lgtm Indicates that a PR is ready to be merged. label Jun 15, 2026
@volcano-sh-bot

Copy link
Copy Markdown
Contributor Author

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: JesseStutler

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@volcano-sh-bot volcano-sh-bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 15, 2026
@volcano-sh-bot
volcano-sh-bot merged commit 039ce76 into volcano-sh:release-1.14 Jun 15, 2026
18 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants