Reconciler Logic

作者 grafana1ccacf29049fApache-2.0279 个星标收录于 2026年10月8日更新于 2026年10月8日仓库今天更新

Implement reconcilers and watchers for grafana-app-sdk apps — write `TypedReconciler[*MyKind]` reconcile functions, apply generation-based skip patterns, do conflict-safe status updates via `resource.UpdateObject`, configure `BasicReconcileOptions` (namespace, label/field filters, finalizer management), use `Watcher` for event-style handling, reconcile `UnmanagedKinds` (resources your app doesn't own), and register the whole thing in `app.go`. Use when writing a reconciler, implementing the reconcile loop, adding async business logic, handling create/update/delete events, processing resource state changes, scheduling periodic resyncs with `RequeueAfter`, picking between Watcher and Reconciler, or wiring a controller into `app.go` — even when the user says "process this resource", "handle X events", or "write a controller" without saying "reconciler".

AI 生成的概览

指导为 grafana-app-sdk 应用实现 reconciler 与 watcher,包括类型化协调函数、状态更新和 app.go 注册。

功能
该技能提供编写 grafana-app-sdk 应用异步业务逻辑层的说明。内容涵盖 TypedReconciler 协调函数、基于 generation 的跳过模式、通过 resource.UpdateObject 进行冲突安全的状态更新、BasicReconcileOptions(如命名空间与标签或字段过滤)、finalizer 管理、Watcher 事件处理、UnmanagedKinds,以及在 app.go 中的注册。它产出 Go 协调器代码与接线指导,而非可运行脚本。
适用场景
适用于编写 reconciler 或 controller、实现协调循环、添加异步业务逻辑、处理创建、更新或删除事件、使用 RequeueAfter 安排周期性重新同步、在 Watcher 与 Reconciler 之间做选择,或将 controller 接入 app.go 的场景。
运行要求
需要 grafana-app-sdk 和 Go 工具链;该技能本身不附带脚本,只有参考文档。它引用了 grafana-app-sdk 的 GitHub 仓库和 operator 包文档。

Reconciler Logic

Reconcilers are the async business-logic layer of a grafana-app-sdk app. The SDK enqueues a reconcile event when a resource is created, updated, or deleted; the reconciler observes the current state and drives the system toward the desired state.

Common Workflows

Implementing a new reconciler end-to-end

bash
# 1. Generate operator stubs for a standalone appgrafana-app-sdk project component add operator
# 2. Implement the ReconcileFunc — see § TypedReconciler below for the pattern
# 3. Register the reconciler in app.go (see references/registration.md)
# 4. Generate, build, and verify it runsgrafana-app-sdk generatego build ./...go run ./cmd/operator   # tail logs — reconcile entries should appear when you kubectl-apply a resource

If the operator starts but no reconcile events fire when you create a resource:

  • Check BasicReconcileOptions.Namespace matches the resource's namespace
  • Check BasicReconcileOptions.LabelFilters / FieldSelectors — most "no events" issues are filter mismatches (kubectl get <resource> -o yaml to see labels)
  • Confirm the reconciler was attached to the right (latest) version of the kind

TypedReconciler — preferred pattern

operator.TypedReconciler handles type assertion and provides a strongly-typed ReconcileFunc:

go
type MyKindReconciler struct {    operator.TypedReconciler[*v1alpha1.MyKind]    client resource.Client}
func NewMyKindReconciler(client resource.Client) *MyKindReconciler {    r := &MyKindReconciler{client: client}    r.ReconcileFunc = r.reconcile  // wire the typed func    return r}
func (r *MyKindReconciler) reconcile(    ctx context.Context,    req operator.TypedReconcileRequest[*v1alpha1.MyKind],) (operator.ReconcileResult, error) {    obj := req.Object
    // Skip if already reconciled this generation    if obj.GetGeneration() == obj.Status.LastObservedGeneration &&       req.Action != operator.ReconcileActionDeleted {        return operator.ReconcileResult{}, nil    }
    log := logging.FromContext(ctx).With("name", obj.GetName(), "namespace", obj.GetNamespace())    log.Info("reconciling", "action", operator.ResourceActionFromReconcileAction(req.Action))
    if req.Action == operator.ReconcileActionDeleted {        return operator.ReconcileResult{}, nil    }
    // ... business logic ...
    // Atomic status update — see § Status updates below    _, err := resource.UpdateObject(ctx, r.client, obj.GetStaticMetadata().Identifier(),        func(obj *v1alpha1.MyKind, _ bool) (*v1alpha1.MyKind, error) {            obj.Status.LastObservedGeneration = obj.GetGeneration()            obj.Status.State = "Ready"            return obj, nil        },        resource.UpdateOptions{Subresource: "status"},    )    return operator.ReconcileResult{}, err}

ReconcileAction values: ReconcileActionCreated, ReconcileActionUpdated, ReconcileActionDeleted, ReconcileActionResynced.

To requeue after a delay (e.g. polling an external system):

go
return operator.ReconcileResult{RequeueAfter: 10 * time.Second}, nil

Status updates with resource.UpdateObject

Always use resource.UpdateObject for status writes — it fetches the latest version before applying your update function, avoiding 409 Conflict errors when multiple reconcile events race:

go
_, err := resource.UpdateObject(ctx, r.client, identifier,    func(obj *v1alpha1.MyKind, exists bool) (*v1alpha1.MyKind, error) {        obj.Status.LastObservedGeneration = obj.GetGeneration()        obj.Status.State = "Ready"        obj.Status.Message = ""        return obj, nil    },    resource.UpdateOptions{Subresource: "status"},)

Do not use client.Update for status — it sends the full object and races with spec changes made by users.

Generation-based skip

Check LastObservedGeneration at the top of the reconcile function to avoid re-processing unchanged resources:

go
if obj.GetGeneration() == obj.Status.LastObservedGeneration {    return operator.ReconcileResult{}, nil}

ReconcileOptions

Control informer behavior via BasicReconcileOptions on the AppManagedKind entry:

go
{    Kind:       mykindv1alpha1.MyKindKind(),    Reconciler: reconciler,    ReconcileOptions: simple.BasicReconcileOptions{        Namespace:      "my-namespace",          // watch one namespace; default is all        LabelFilters:   []string{"env=prod"},    // only reconcile matching resources        FieldSelectors: []string{"status.phase=Running"},        UsePlain:       false,                   // false = wrap in OpinionatedReconciler (default; manages finalizers)    },},

UsePlain: false (the default) wraps your reconciler in OpinionatedReconciler, which manages finalizers automatically so the SDK can guarantee clean deletion.

References

  • references/watchers.md [blocked] — Watcher alternative (event-style Add/Update/Delete callbacks) + decision matrix for watcher vs reconciler
  • references/unmanaged-kinds.md [blocked] — UnmanagedKinds for reconciling resources your app doesn't own, with UseOpinionated: false guidance and common failure modes
  • references/registration.md [blocked] — full app.go wiring (client setup, multi-version registration, ValidateManifest) + common failure modes

External resources

来源与署名

来源:grafana/skills位于skills/grafana-app-sdk/reconciler-logic提交1ccacf2

许可证: Apache-2.0

内容归原作者所有。SourceWeft 从公开仓库中收录这些内容。

举报或申请下架

更多来自 grafana/skills 的技能

React 19 Plugin Migration

grafana

指导将 Grafana 插件迁移至 React 19 兼容,按顺序完成构建、依赖与源码修改步骤。

Software Development279今天更新

Plugin Bundle Size

grafana

指导使用 React.lazy、Suspense 和 webpack 代码分割来优化 Grafana 应用插件包体积。

Software Development279今天更新

Grafana Scenes

grafana

使用 @grafana/scenes 框架构建 Grafana 插件页面,涵盖场景、面板、变量与下钻导航。

Software Development279今天更新

Check Npm

grafana

对 JS/TS 仓库的 npm、yarn 或 pnpm 配置进行只读供应链加固审计。

Security279今天更新

Mimir

grafana

指导搭建和运维 Grafana Mimir,用于可扩展、多租户、长期的 Prometheus 与 OTLP 指标存储。

DevOps & Cloud279今天更新

K6 Trend Analysis

grafana

Analyze Grafana Cloud k6 test run trends over time. Detects slow metric drift (e.g., P95 latency creeping up while still passing thresholds), computes headroom to thresholds, flags anomalies, and recommends threshold tightening. Use when the user asks about test performance trends, wants to know if metrics are degrading, asks whether thresholds should be tightened, or wants a health check across recent runs for a specific test. Trigger on phrases like "how is my test trending", "is P95 getting worse", "check for performance regression", "should I tighten thresholds", "are my tests degrading", "show me trends for test X", "analyze my k6 test runs", or "is my test getting slower". Also trigger when a user asks to check all tests in a project -- run this skill once per test and synthesize.

待分类279今天更新