pipeline

package
v0.32.5 Latest Latest
Warning

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

Go to latest
Published: Aug 6, 2026 License: Apache-2.0 Imports: 29 Imported by: 0

Documentation

Overview

Package pipeline orchestrates the snapshot download: tree build, resume scan, bounded-concurrency node processing, volume download, and finalization.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Run

func Run(ctx context.Context, cfg Config) error

Run builds the snapshot tree, scans the output directory for resume state, and downloads all missing node data with bounded concurrency. The per-node download phase is BEST-EFFORT: nodes are independent (own DataExport, own output subdir, no shared mutable state), so one node's failure — a permanently broken volume, a DataExport timeout — is recorded and does NOT cancel sibling nodes still downloading; aborting healthy nodes seconds from completion is the wrong trade-off for a backup/download tool. Run aggregates every per-node failure into a single errors.Join error. A genuine ctx cancellation (SIGINT, or the caller cancelling its parent context) still aborts all in-flight nodes promptly; in that case Run returns ctx.Err() instead of the aggregated per-node error — but only when at least one node actually failed. If every node already succeeded before the cancellation was observed, Run reports success: a late-arriving cancellation must never turn a fully successful download into a reported failure.

func RunRooted

func RunRooted(
	ctx context.Context,
	cfg Config,
	destination *archive.RootedDestination,
) error

RunRooted executes the pipeline through the caller's locked destination.

func WithPayloadChecksumObserver

func WithPayloadChecksumObserver(ctx context.Context, observer PayloadChecksumObserver) context.Context

WithPayloadChecksumObserver returns a context that observes complete publication checksum passes without changing archive reads or writes.

Types

type Config

type Config struct {
	// Namespace is the Kubernetes namespace of the root Snapshot.
	Namespace string

	// RootSnapshot is the metadata.name of the root Snapshot CR.
	RootSnapshot string

	// OutputDir is the absolute path of the root output directory.
	// Its basename is chosen by the caller; no namespace wrapper is added.
	OutputDir string

	// Workers is the maximum number of nodes processed concurrently (default: 4).
	// For block volumes each worker finalizes up to PerVolumeConcurrency frames
	// simultaneously. Raw 256 MiB chunks remain on disk; encoding memory is
	// bounded by codec windows and buffers, independent of chunk size. zstd uses
	// one encoder worker and at most an 8 MiB window per frame plus fixed block,
	// history, and output buffers. Worst-case finalize memory therefore scales
	// with Workers × PerVolumeConcurrency × that per-frame codec bound, not
	// Workers × PerVolumeConcurrency × volume.DefaultChunkSize.
	Workers int

	// PerVolumeConcurrency is the maximum number of parallel chunk or file
	// downloads per volume (default: 4).
	// Multiplied with Workers and the codec's bounded per-frame working set it
	// determines the worst-case finalize RSS; see Workers for the peak formula.
	PerVolumeConcurrency int

	// MaxParallelDownloads is the global cap on concurrent whole-volume-stream
	// downloads across all nodes (default: 5). It is enforced by a single shared
	// semaphore acquired once per volume stream in downloadVolumeBinding.
	// This cap is independent of Workers (node-level errgroup limit) and
	// PerVolumeConcurrency (chunk/file-level errgroup limit per volume).
	MaxParallelDownloads int

	// TTL is the DataExport TTL string (e.g. "2h").  Defaults to "2h".
	TTL string

	// RunID is an opaque per-run identifier that scopes DataExport ownership to
	// this single download run. Because the DataExport CR name is deterministic,
	// two concurrent runs downloading the
	// same leaf into DIFFERENT output directories resolve to the SAME CR; RunID
	// lets each run stamp the CRs it creates (exporter.WithRunOwner) and refuse to
	// delete a CR another live run owns (exporter.ReleaseDataExport), so neither
	// run tears down the other's in-flight export (inv #10b). Run generates a
	// fresh RunID via crypto/rand when it is empty; tests may set it explicitly.
	RunID string

	// KeepExports, when true, leaves the per-volume DataExport CR (and the
	// server-side export chain it owns: export VolumeSnapshot/VolumeSnapshotContent/
	// export PVC) in the cluster after each volume stream completes, instead of
	// deleting it. Zero value (false) preserves the always-delete behavior that
	// predates this field. Set from the inverse of the `--cleanup` download flag.
	KeepExports bool

	// Compression is the codec used for volume data encoding. For block volumes it
	// determines the chunk frame encoding and the output filename extension
	// (e.g. ".zst" → data.bin.zst). For filesystem volumes each file inside data.tar
	// is individually compressed with this codec: entry names become <path><ext>
	// (ext is empty for codec=none). When nil, applyDefaults creates a zstd codec.
	Compression compress.Codec

	// KubeClient performs all Kubernetes API calls.  Required.
	KubeClient client.Client

	// AggClient is the aggregated subresource API client used to fetch per-node
	// manifests via manifests-download and to resolve leaf snapshot CR group/resource
	// for DataExport targetRef. When ManifestSource is nil and AggClient is set,
	// applyDefaults builds an AggregatedManifestSource from it.
	AggClient *aggapi.Client

	// ManifestSource fetches own-scope node manifests.
	// When nil an AggregatedManifestSource backed by AggClient is used.
	ManifestSource source.ManifestSource

	// OpenExport opens a DataExport for the given snapshot leaf NodeRef and
	// returns an Export ready for data transfer. When nil TransportClient and AggClient
	// must be non-nil and the production path (exporter.OpenExport) is used.
	//
	// leafRef identifies the snapshot leaf CR to target: for CSI VolumeSnapshot
	// leaves its APIVersion/Kind are "snapshot.storage.k8s.io/v1"/"VolumeSnapshot";
	// for domain snapshot CRs they carry the domain group and kind. The DataExport
	// targetRef is derived from leafRef via the AggClient RESTMapper.
	OpenExport func(ctx context.Context, namespace string, leafRef aggapi.NodeRef, ttl string) (*exporter.Export, error)

	// OpenExportWithAcquisition opens an export and returns operation-scoped
	// cleanup evidence for the exact DataExport acquired while opening it. The
	// acquisition may be non-nil together with an error when EnsureDataExport
	// succeeded but WaitReady or transport setup failed; callers must retain it
	// so that exact object is still cleaned up. Tests and alternative transports
	// that need cleanup evidence may supply it directly; the UID-aware production
	// path uses OpenExportWithTargetAcquisition. OpenExport remains the
	// compatibility path for implementations that do not manage DataExport
	// lifecycle.
	OpenExportWithAcquisition func(
		ctx context.Context,
		namespace string,
		leafRef aggapi.NodeRef,
		ttl string,
	) (*exporter.Export, *exporter.DataExportAcquisition, error)

	// OpenExportWithTargetAcquisition is the UID-aware production lifecycle
	// callback. It carries the exact Snapshot CR UID in addition to leafRef so
	// DataExport naming and adoption cannot cross Snapshot incarnations.
	OpenExportWithTargetAcquisition func(
		ctx context.Context,
		namespace string,
		leafRef aggapi.NodeRef,
		targetUID types.UID,
		ttl string,
	) (*exporter.Export, *exporter.DataExportAcquisition, error)

	// TransportClient is used for DataExport HTTP connections in the production path
	// (when OpenExport is nil).  May be nil in tests that supply OpenExport.
	TransportClient *transport.Client

	// ReadinessTimeout is how long OpenExport waits for a DataExport to become
	// Ready before returning an error.  Defaults to 5 minutes.
	ReadinessTimeout time.Duration

	// ReleaseTimeout bounds each per-volume DataExport release call (the
	// Get-before-Delete in exporter.ReleaseDataExport).  Defaults to 30 seconds.
	// downloadVolumeBinding derives a FRESH context.WithTimeout budget from this
	// value at the moment its release defer actually runs, not once up front, so
	// a slow OpenExport/WaitReady or a large volume transfer never eats into the
	// time release itself gets.
	ReleaseTimeout time.Duration

	// SelectedNodeKind and SelectedNodeName identify a single snapshot-CR node to
	// download together with its full subtree. When both are set, Run builds the
	// full tree (needed for path naming and ancestor scaffolding) and restricts
	// processing to the selected node and its descendants. Ancestor directories
	// between OutputDir and the selected node are created as content-free scaffolding
	// (no snapshot.yaml, no manifests/, no data, no sibling subtrees) so the
	// selected node sits at its real path under OutputDir.
	// When either value is empty the full tree is downloaded.
	SelectedNodeKind string
	SelectedNodeName string

	// Progress is the multi-bar progress Sink for reporting per-stream and
	// aggregate download progress. When nil, no progress output is produced
	// and download behaviour is unchanged.
	Progress progress.Sink

	// Log is the structured logger.  Defaults to slog.Default() when nil.
	Log *slog.Logger
	// contains filtered or unexported fields
}

Config holds all parameters for a snapshot download run.

type PayloadChecksumObserver

type PayloadChecksumObserver func(nodeDir string, payloadBytes int64)

PayloadChecksumObserver observes payload bytes traversed by publication checksum passes. It is intended for deterministic integrity-work accounting.

Jump to

Keyboard shortcuts

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