package reconcile import ( "context" "errors" "edge-infra.dev/pkg/k8s/meta/status" "edge-infra.dev/pkg/k8s/object" "edge-infra.dev/pkg/k8s/runtime/conditions" "edge-infra.dev/pkg/k8s/runtime/patch" ) // Progressing updates the Reconciling condition for an object that is progressing // through a reconciler. If specific reconciliation states are detected, that // Reconciling condition is immediately patched so that it is reflected in the // K8s control plane to provide feedback to users: // // - If the object's ObservedGeneration does not match the object's current // generation, a contextual progressing reason is used. // - For objects that embed [ReconcileRequestStatus], if [ReconcileRequestAnnotation] // is present and it differs from the last handled reconcile request value // // The progressing condition is not perrsisted immediately because reconcilers // which always requeue on some interval would thrash on their Ready status when // reconciliation _should_ arrive to the same result if the object generation // has not changed. This behavior is intended to make a trade-off between // keeping the K8s API up to date with the latest object state as quickly as // possible vs status churning. func Progressing(ctx context.Context, obj conditions.Setter, patcher *patch.SerialPatcher, patchOpts ...patch.Option) error { conditions.Progressing(obj, status.ProgressingReason, "Reconciliation in progress") obsGen, err := object.GetStatusObservedGeneration(obj) switch { case err != nil && !errors.Is(err, object.ErrObservedGenerationNotFound): return err case err == nil: if obsGen != obj.GetGeneration() { conditions.Progressing(obj, status.ProgressingReason, "processing object: new generation %d -> %d", obsGen, obj.GetGeneration()) return patcher.Patch(ctx, obj, patchOpts...) } } var recAtVal string if v, ok := GetAnnotation(obj.GetAnnotations()); ok { recAtVal = v } lastRecHandledAtVal, err := GetStatusLastHandledReconcileAt(obj) switch { case !errors.Is(err, ErrLastHandledReconcileAtNotFound): return err case err != nil && recAtVal != lastRecHandledAtVal: return patcher.Patch(ctx, obj, patchOpts...) } return nil }