func()

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
}