Repository: vllm-project/aibrix
File: pkg/controller/podautoscaler/podautoscaler_controller.go (Go)

Code before:
	// Implement a timeout for the reconciliation process.
	ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
	defer cancel()

	klog.V(4).InfoS("Reconciling PodAutoscaler", "obj", req.NamespacedName)

	var pa autoscalingv1alpha1.PodAutoscaler
	if err := r.Get(ctx, req.NamespacedName, &pa); err != nil {
		if errors.IsNotFound(err) {
			// Object might have been deleted after reconcile request, ignore and return.
			klog.Infof("PodAutoscaler resource not found. Ignoring since object %s must have been deleted", req.NamespacedName)
			return ctrl.Result{}, nil
		}
		klog.ErrorS(err, "Failed to get PodAutoscaler")
		return ctrl.Result{}, err
	}

	if !checkValidAutoscalingStrategy(pa.Spec.ScalingStrategy) {
		// TODO: update status or conditions
		// this is unrecoverable unless user make changes.
		return ctrl.Result{}, nil
	}

	switch pa.Spec.ScalingStrategy {
	case autoscalingv1alpha1.HPA:
		return r.reconcileHPA(ctx, pa)
	case autoscalingv1alpha1.KPA, autoscalingv1alpha1.APA:
		return r.reconcileCustomPA(ctx, pa)
	}

	newStatus := computeStatus(ctx, pa)
	if err := r.updateStatusIfNeeded(ctx, newStatus, &pa); err != nil {
		return ctrl.Result{}, err
	}

	return ctrl.Result{}, nil
}

func (r *PodAutoscalerReconciler) Run(ctx context.Context, errChan chan<- error) {
	ticker := time.NewTicker(r.resyncInterval)
	defer ticker.Stop()
	defer close(r.eventCh)

	for {
		select {
		case <-ticker.C:
			klog.V(4).Info("enqueue all autoscalers")
			// periodically sync all autoscaling objects
			if err := r.enqueuePodAutoscalers(ctx); err != nil {
				klog.ErrorS(err, "Failed to enqueue pod autoscalers")
				errChan <- err

Review comment (suggestion):
there's some other cases like other objects sometimes get enqueued (not PodAutoscaler object), in this case, `deleteScaler` need to handle such case.

Code after:
	}
}

//+kubebuilder:rbac:groups=autoscaling.aibrix.ai,resources=podautoscalers,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=autoscaling.aibrix.ai,resources=podautoscalers/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=autoscaling.aibrix.ai,resources=podautoscalers/finalizers,verbs=update
//+kubebuilder:rbac:groups=autoscaling,resources=horizontalpodautoscalers,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups="",resources=events,verbs=create;patch;update

// Reconcile is part of the main Kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state as specified by
// the PodAutoscaler resource. It handles the creation, update, and deletion logic for
// HorizontalPodAutoscalers based on the PodAutoscaler specifications.
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.17.3/pkg/reconcile
func (r *PodAutoscalerReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
	// Implement a timeout for the reconciliation process.
	ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
	defer cancel()

	klog.V(4).InfoS("Reconciling PodAutoscaler", "obj", req.NamespacedName)

	var pa autoscalingv1alpha1.PodAutoscaler
	if err := r.Get(ctx, req.NamespacedName, &pa); err != nil {
		if errors.IsNotFound(err) {
			r.deleteScaler(req.NamespacedName)
			// Object might have been deleted after reconcile request, clean it and return.
			klog.Infof("PodAutoscaler resource not found. Clean scaler object in memory since object %s must have been deleted", req.NamespacedName)
			return ctrl.Result{}, nil
		}
		klog.ErrorS(err, "Failed to get PodAutoscaler")
		return ctrl.Result{}, err
	}

	if !checkValidAutoscalingStrategy(pa.Spec.ScalingStrategy) {
		// TODO: update status or conditions
		// this is unrecoverable unless user make changes.
		return ctrl.Result{}, nil
	}

	switch pa.Spec.ScalingStrategy {
	case autoscalingv1alpha1.HPA:
		return r.reconcileHPA(ctx, pa)
	case autoscalingv1alpha1.KPA, autoscalingv1alpha1.APA:
		return r.reconcileCustomPA(ctx, pa)
	}

	newStatus := computeStatus(ctx, pa)
	if err := r.updateStatusIfNeeded(ctx, newStatus, &pa); err != nil {
		return ctrl.Result{}, err
	}