Help us shape the future of Go! Take the 2026 Go Developer Survey

retention

package
v0.5.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 1, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Overview

Package retention deletes metadata rows past an operator-configured age. It is opt-in per data class and runs on the scheduler leader only: runs and the audit log are kept by default, and the usage events (ADR 0096), which exist only once an operator turns their recording on, keep a 30 day window. Deletes are tenant scoped, bounded per statement, paused between batches and capped per cycle, so the janitor never turns into one long DELETE that holds locks or floods the WAL.

Index

Constants

View Source
const (
	TableDagRuns             = "dag_runs"
	TableTaskInstances       = "task_instances"
	TableTaskInstanceHistory = "task_instance_history"
	TableXComIndex           = "xcom_index"
	TableAuditLog            = "audit_log"
	TableUsageEvents         = "usage_events"
)

Table names used as the `table` metric label.

Variables

View Source
var ErrNotLeading = errors.New("retention: not leading")

ErrNotLeading ends a cycle when this instance lost leadership mid-cycle.

Functions

This section is empty.

Types

type Config

type Config struct {
	DagRunsDays     int
	AuditLogDays    int
	UsageEventsDays int
	DryRun          bool
	BatchSize       int
	BatchPause      time.Duration
	MaxRowsPerCycle int
}

Config is the janitor's view of the retention section.

func (Config) Enabled

func (c Config) Enabled() bool

Enabled reports whether any class is configured.

type Counts

type Counts struct {
	DagRuns             int64
	TaskInstances       int64
	TaskInstanceHistory int64
	XComIndex           int64
	AuditLog            int64
	UsageEvents         int64
	// Capped reports that a dry-run count stopped at its per-tenant cap, so
	// the counts are a lower bound. Deletes never set it.
	Capped bool
}

Counts is the number of rows deleted (or, in dry run, eligible) per table.

func (Counts) Add

func (c Counts) Add(o Counts) Counts

Add returns the field-wise sum of c and o.

func (Counts) Total

func (c Counts) Total() int64

Total is the number of rows across every table.

type Janitor

type Janitor struct {
	// contains filtered or unexported fields
}

Janitor runs retention cycles.

func New

func New(store Store, cfg Config, rec Recorder, logger *slog.Logger) *Janitor

New builds a Janitor. A nil recorder drops metrics.

func (*Janitor) RunCycle

func (j *Janitor) RunCycle(ctx context.Context)

RunCycle runs one cycle and logs its outcome. A cycle that fails or loses leadership is retried on the caller's next tick.

func (*Janitor) RunOnce

func (j *Janitor) RunOnce(ctx context.Context) (Counts, error)

RunOnce runs one retention cycle and returns what it deleted, or in dry run what it would delete. The lanes (each tenant's runs, then each scope's audit rows) take turns, one batch each, so under the cycle cap no tenant and no class waits behind another's backlog.

func (*Janitor) SetLeading

func (j *Janitor) SetLeading(leading func() bool)

SetLeading gates every batch on leadership: once leading reports false the cycle stops with ErrNotLeading before its next batch.

type Recorder

type Recorder interface {
	RecordRetentionDeleted(table string, n int64)
	RecordRetentionEligible(table string, n int64)
	ObserveRetentionCycle(d time.Duration)
}

Recorder receives the janitor's metrics.

type Store

type Store interface {
	// TenantIDs lists every tenant.
	TenantIDs(ctx context.Context) ([]string, error)
	// DeleteFinishedRuns removes, in one transaction, at most rowLimit rows of
	// up to maxRuns settled runs of tenant that ended before cutoff, run rows
	// included, children first. A run with more children than fit is finished
	// by later calls, each of which re-checks that the run is still eligible.
	DeleteFinishedRuns(ctx context.Context, tenant string, cutoff time.Time, maxRuns, rowLimit int) (Counts, error)
	// DeleteAuditLog removes up to limit audit rows of tenant older than cutoff.
	// An empty tenant means the tenant-less system rows.
	DeleteAuditLog(ctx context.Context, tenant string, cutoff time.Time, limit int) (int64, error)
	// DeleteUsageEvents removes up to limit usage events older than cutoff,
	// oldest first in the order the service API serves them, and moves the
	// pruned mark past them in the same transaction.
	DeleteUsageEvents(ctx context.Context, cutoff time.Time, limit int) (int64, error)
	// CountEligible counts what a cycle would delete, summed across all tenants;
	// a nil cutoff skips that class.
	CountEligible(ctx context.Context, runCutoff, auditCutoff, usageCutoff *time.Time) (Counts, error)
	// RecordRetentionPurge writes an audit entry for rows of the audit log a
	// cycle deleted in the scope of tenant ("" is the system rows).
	RecordRetentionPurge(ctx context.Context, tenant string, rows int64, cutoff time.Time) error
}

Store is the storage the janitor deletes through.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL