in pkg/controller/controller.go [841:953]
func (c *FrameworkController) compactFrameworkScale(
f *ci.Framework) (producedNewPendingTask bool) {
logPfx := fmt.Sprintf("[%v]: compactFrameworkScale: ", f.Key())
klog.Infof(logPfx + "Started")
defer func() { klog.Infof(logPfx + "Completed") }()
producedNewPendingTask = false
// Align with syncFrameworkScale to simplify completing.
if f.IsCompleting() ||
f.Status.State == ci.FrameworkAttemptCompleted ||
f.Status.State == ci.FrameworkCompleted {
klog.Infof(logPfx+"Skipped: Framework is already %v", f.Status.State)
return producedNewPendingTask
}
// For TaskRoles/Tasks which no longer belong to its current f.Spec, try to
// delete the Completed DeletionPending ones.
taskRoleStatuses := &f.Status.AttemptStatus.TaskRoleStatuses
for taskRoleIndex := len(*taskRoleStatuses) - 1; taskRoleIndex >= 0; taskRoleIndex-- {
taskRoleStatus := (*taskRoleStatuses)[taskRoleIndex]
taskRoleName := taskRoleStatus.Name
taskCountStatus := int32(len(taskRoleStatus.TaskStatuses))
// Will delete Tasks in in range [taskIndexDeleteStart, taskCountStatus)
taskIndexDeleteStart := taskCountStatus
taskRoleSpec := f.GetTaskRoleSpec(taskRoleName)
var taskCountSpec int32
if taskRoleSpec == nil {
taskCountSpec = 0
} else {
taskCountSpec = taskRoleSpec.TaskNumber
}
for taskIndex := taskCountStatus - 1; taskIndex >= taskCountSpec; taskIndex-- {
taskStatus := taskRoleStatus.TaskStatuses[taskIndex]
if taskStatus.DeletionPending && taskStatus.State == ci.TaskCompleted {
taskIndexDeleteStart = taskIndex
} else {
// Cannot continue graceful deletion anymore
break
}
}
var newTaskCountStatus *int32
if taskIndexDeleteStart == 0 && taskRoleSpec == nil {
// Delete the whole Completed DeletionPending TaskRole
newTaskCountStatus = nil
} else {
// Delete tail Completed DeletionPending Tasks
newTaskCountStatus = &taskIndexDeleteStart
}
if newTaskCountStatus != nil && *newTaskCountStatus == taskCountStatus {
// Nothing can be deleted
continue
}
// Start deletion
klog.Infof("[%v][%v]: compactFrameworkScale: ScaleDown: Deletion: %v -> %v",
f.Key(), taskRoleName, taskCountStatus, common.SprintPtrInt32(newTaskCountStatus))
for taskIndex := taskCountStatus - 1; taskIndex >= taskIndexDeleteStart; taskIndex-- {
klog.Info(fmt.Sprintf(
"[%v][%v][%v]: compactFrameworkScale: ScaleDown: Deletion",
f.Key(), taskRoleName, taskIndex) +
c.cConfig.LogObjectSnapshot.Task.GetLogTailOnTaskDeletion(
f.MockTask(taskRoleName, taskIndex, true)))
taskRoleStatus.TaskStatuses[taskIndex] = nil
}
if newTaskCountStatus == nil {
taskRoleLastIndex := len(*taskRoleStatuses) - 1
(*taskRoleStatuses)[taskRoleIndex] = (*taskRoleStatuses)[taskRoleLastIndex]
(*taskRoleStatuses)[taskRoleLastIndex] = nil
*taskRoleStatuses = (*taskRoleStatuses)[:taskRoleLastIndex]
} else {
taskRoleStatus.TaskStatuses = taskRoleStatus.TaskStatuses[:*newTaskCountStatus]
}
}
// For TaskRoles/Tasks which still belong to its current f.Spec, replace all
// Completed DeletionPending ones with new Task instances.
for _, taskRoleStatus := range f.TaskRoleStatuses() {
taskRoleName := taskRoleStatus.Name
taskCountStatus := int32(len(taskRoleStatus.TaskStatuses))
taskRoleSpec := f.GetTaskRoleSpec(taskRoleName)
if taskRoleSpec != nil {
taskCountSpec := taskRoleSpec.TaskNumber
taskCountStatusAndSpec := common.MinInt32(taskCountStatus, taskCountSpec)
for taskIndex := taskCountStatusAndSpec - 1; taskIndex >= 0; taskIndex-- {
taskStatus := taskRoleStatus.TaskStatuses[taskIndex]
if taskStatus.DeletionPending && taskStatus.State == ci.TaskCompleted {
// Replace the Completed DeletionPending Task with new instance
klog.Info(fmt.Sprintf(
"[%v][%v][%v]: compactFrameworkScale: ScaleDown: Replacement",
f.Key(), taskRoleName, taskIndex) +
c.cConfig.LogObjectSnapshot.Task.GetLogTailOnTaskDeletion(
f.MockTask(taskRoleName, taskIndex, true)))
taskRoleStatus.TaskStatuses[taskIndex] =
f.NewTaskStatus(taskRoleName, taskIndex)
producedNewPendingTask = true
}
}
}
}
return producedNewPendingTask
}