Skip to content

feat: domain.Request/Result, requeue:, failPolicy:, ToClient cache - #265

Merged
iAlexeze merged 1 commit into
mainfrom
feat/requeue-or-gates
Aug 24, 2026
Merged

feat: domain.Request/Result, requeue:, failPolicy:, ToClient cache#265
iAlexeze merged 1 commit into
mainfrom
feat/requeue-or-gates

Conversation

@iAlexeze

Copy link
Copy Markdown
Collaborator

Phase 2

This PR follows #264 (controller-runtime compat) and completes the picture.

The signature change that unlocks everything

domain.Reconciler used to be:

Reconcile(ctx context.Context, key string) error

It is now:

Reconcile(ctx context.Context, req Request) (Result, error)

Result.RequeueAfter now flows from every reconciler — typed or declarative — into the workqueue. A cert-rotation operator written entirely in YAML can say:

 requeue:
   after: "{{ timeUntil .status.certExpiry }}"` 

and each CR schedules its own next reconcile from its own state. The same path that carries ctrl.Result.RequeueAfter from a migrated controller-runtime reconciler now carries YAML-declared requeue intent from a declarative operator. One mechanism, two surfaces.

controller-runtime gets cache reads

kubeclient.ToClient(kube) now serves client.Get and client.List from the informer store for any type with a registered informer — the primary CRD and every watch: entry. Types without an informer fall through to a live API call. This restores the caching behaviour that mgr.GetClient() provided before migration, silently and without any change to the reconciler.

New features

  • requeue: — per-object, per-state requeue on reconciler.requeue:. Conditional via when:/or:. after: is a template expression with the full post-reconcile resolver.
operatorBox:
  reconciler:
    requeue:
      after: "{{ timeUntil .status.certExpiry }}"   # per-object, from its own state
      when:
        - field: status.phase
          equals: "Active"
  • failPolicy:open (default) or closed on both enqueueGate and reconcileGate. Controls what the gate does when an external: call fails. Validator warns when external: is declared without an explicit policy.
preReconcile:
  reconcileGate:
    failPolicy: closed   # hold back on evaluation failure
    external:
      - name: dep
        url: "{{ .spec.dependencyUrl }}/health"
    when:
      - field: external.dep.status
        equals: "200"

Breaking renames

  • anyOf:or: everywhere in the schema. Reads naturally alongside when:.
  • hooks.resources: / constructor.resources:managedResources: — removes the ambiguity with the watch: block.
  • domain.Reconciler interface — all implementors updated.

Documentation updated.

…licy:, ToClient cache

Breaking renames:
- anyOf: → or: across the entire schema (gates, autoscale, serve, status, validation)
- hooks.resources: / constructor.resources: → managedResources:
- domain.Reconciler: Reconcile(ctx, key string) error → Reconcile(ctx, Request) (Result, error)

New:
- requeue: per-object scheduled requeue after successful reconcile (when:/or: conditions, template after:)
- failPolicy: open/closed on enqueueGate and reconcileGate
- ToClient cache-backed Get/List from informer store; falls through to live API on miss
- domain.ReconcilerFrom forwards ctrl.Result.RequeueAfter through the bridge
- ork migrate generator updated: managedResources:, corrected toclient README template
- reconciler-model docs rewritten: two models, kordinator page, resync vs requeue
@iAlexeze iAlexeze changed the title eat: domain.Request/Result, requeue:, failPolicy:, ToClient cache feat: domain.Request/Result, requeue:, failPolicy:, ToClient cache Aug 24, 2026
@iAlexeze
iAlexeze merged commit 1057f31 into main Aug 24, 2026
8 checks passed
@iAlexeze
iAlexeze deleted the feat/requeue-or-gates branch August 24, 2026 22:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant