builders

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Aug 5, 2026 License: MIT Imports: 17 Imported by: 0

README

Builders

Builders retain build cache across repeated Hypeman builds. Without a Builder, each build gets a temporary 3 GB cache that disappears with its build VM. With a Builder, disposable build VMs reuse one persistent cache disk.

A Builder is useful for an application, repository, or pipeline that is built repeatedly. Reusing it reduces repeated downloads and work in later builds.

Identity and isolation

Each Builder has an opaque ID and owns one cache disk. Pass that ID as builder_id when creating a build. The ID—not the optional name or the caller's credentials—is the cache boundary.

Names are optional and non-unique. Tags support filtering. Automation should store and use the Builder ID.

Omitting builder_id preserves the original build behavior: Hypeman uses a temporary 3 GB cache and does not retain its contents. There is no implicit or default Builder.

Build behavior

A build that targets a Builder still runs in a new disposable VM. Hypeman attaches the Builder's cache disk for the build and detaches it when VM execution ends. Source archives, build secrets, and VM configuration are not stored on the Builder disk.

One build runs on a Builder at a time. Additional builds for the same Builder wait in submission order. Use separate Builders when build streams need to run concurrently or must not share cache state.

Builder details report the active build, queued build IDs, and max_concurrency. These are point-in-time values; max_concurrency is currently fixed at 1.

Cache lifecycle

Creating a Builder creates a fixed-size cache disk. Disk size cannot be changed; create a new Builder to use a different size.

The current build backend protects cache usage below 70% of disk capacity and allows it to grow to 90% before garbage collection reclaims entries. Cache contents are an optimization, not durable build output. Hypeman may recreate an empty disk after missing storage, interrupted cleanup, or an incompatible backend version.

POST /builders/{id}/prune clears cache contents while preserving the Builder's ID, name, tags, and disk size. Pruning is asynchronous: the Builder reports pruning until a fresh disk is ready. Builds, pruning, and deletion are mutually exclusive for a given Builder.

DELETE /builders/{id} permanently removes both the Builder and its cache disk. Deletion is rejected while the Builder has queued or active work.

Hypeman restarts

Builders' metadata survives Hypeman process restarts. Startup recovery reconciles interrupted prune or delete operations and stale VM attachments. Builds that were queued or running during the restart may be started again.

Builders are local to the Hypeman server that owns their disk. The initial implementation does not provide warm Builder VMs, concurrent builds on one Builder, cache migration between servers, or a durability guarantee for cached data.

Documentation

Overview

Package builders implements persistent cache resources used by disposable build VMs. A Builder is the unit of build-cache isolation; one build at a time may run on a Builder.

Index

Constants

View Source
const (
	StatusReady    = "ready"
	StatusPruning  = "pruning"
	StatusDeleting = "deleting"
	StatusError    = "error"
)

Builder status constants

View Source
const (
	// DefaultDiskSizeGb is the disk size used when a create request does
	// not specify one.
	DefaultDiskSizeGb = 50
)

Variables

View Source
var (
	// ErrNotFound is returned when a builder is not found
	ErrNotFound = errors.New("builder not found")

	// ErrAlreadyExists is returned when a builder with the same ID already exists
	ErrAlreadyExists = errors.New("builder already exists")

	// ErrInUse is returned when a builder is acquired by a build, has its
	// disk attached, or is mid-prune/delete
	ErrInUse = errors.New("builder is in use")

	// ErrInvalidID is returned when a caller-supplied builder ID is invalid
	ErrInvalidID = errors.New("invalid builder id")

	// ErrQuotaExceeded is returned when a create would exceed the configured
	// builder count limit
	ErrQuotaExceeded = errors.New("builder quota exceeded")

	// ErrInvalidDiskSize is returned when a requested disk size is negative
	ErrInvalidDiskSize = errors.New("invalid builder disk size")

	// ErrDiskSizeExceeded is returned when a requested disk size exceeds the
	// configured maximum
	ErrDiskSizeExceeded = errors.New("builder disk size exceeds maximum")
)

Functions

func DiskVolumeID

func DiskVolumeID(builderID string) string

DiskVolumeID returns the deterministic volume ID of a builder's disk.

func ValidateBuilderID

func ValidateBuilderID(id string) error

ValidateBuilderID validates a caller-supplied builder ID.

Types

type Builder

type Builder struct {
	ID           string
	Name         string // optional, non-unique metadata
	DiskSizeGb   int
	Tags         tags.Tags
	Status       string
	CreatedAt    time.Time
	LastUsedAt   *time.Time
	DiskVolumeID string
}

Builder is a first-class build-cache resource backed by a persistent disk.

type Config

type Config struct {
	// MaxCount caps the number of builders (0 = unlimited)
	MaxCount int

	// DefaultDiskSizeGb is the disk size for creates that omit it
	// (<= 0 uses DefaultDiskSizeGb)
	DefaultDiskSizeGb int

	// MaxDiskSizeGb caps the requested disk size (0 = unlimited)
	MaxDiskSizeGb int

	// IdleTTL is how long a builder may go unused before it is deleted.
	// Deletion is total and irreversible. 0 disables the reaper.
	IdleTTL time.Duration
}

Config holds configuration for the builders manager

type CreateBuilderRequest

type CreateBuilderRequest struct {
	ID         *string // optional caller-supplied ID
	Name       string
	DiskSizeGb int // 0 uses the configured default; immutable after creation
	Tags       tags.Tags
}

CreateBuilderRequest is the domain request for creating a builder

type Manager

type Manager interface {
	// Start reconciles on-disk state after a restart and starts the idle
	// reaper when configured. Called once when the API server starts.
	Start(ctx context.Context) error

	// CreateBuilder creates a builder and eagerly provisions its disk
	CreateBuilder(ctx context.Context, req CreateBuilderRequest) (*Builder, error)

	// GetBuilder returns a builder by ID
	GetBuilder(ctx context.Context, id string) (*Builder, error)

	// ListBuilders returns all builders
	ListBuilders(ctx context.Context) ([]Builder, error)

	// DeleteBuilder deletes a builder and its disk. Deletion is total and
	// irreversible. Returns ErrInUse while the builder is acquired by a
	// build, has its disk attached, or is mid-prune.
	DeleteBuilder(ctx context.Context, id string) error

	// AcquireForBuild marks a builder as held by a build, recreating a
	// missing disk as best-effort cache recovery. Returns ErrInUse when the
	// builder is already held or not ready. A disk attachment on an unheld,
	// ready builder can only be a leaked record or a stale VM from a
	// crashed build, so it is cleared before the acquisition instead of
	// failing builds until the next restart reconciliation.
	AcquireForBuild(ctx context.Context, id string, buildID string) (*Builder, error)

	// ReleaseBuild releases a builder held by AcquireForBuild and records
	// last_used_at, including for failed builds.
	ReleaseBuild(ctx context.Context, id string, buildID string) error

	// ResetDisk resets a builder's cache by recreating its disk
	// asynchronously: the returned snapshot has status pruning, followed by
	// ready (or error). Returns ErrInUse while the builder is acquired by a
	// build, has its disk attached, or is mid-delete.
	ResetDisk(ctx context.Context, id string) (*Builder, error)

	// SetBuildActivityChecker registers a function reporting whether a
	// builder has queued or running builds. DeleteBuilder and ResetDisk
	// consult it so they also return ErrInUse while builds are queued,
	// before any build holds the acquisition.
	SetBuildActivityChecker(fn func(builderID string) bool)
}

Manager provides builder lifecycle operations

func NewManager

func NewManager(
	p *paths.Paths,
	config Config,
	volumeMgr volumes.Manager,
	instanceMgr instanceChecker,
	logger *slog.Logger,
	meter metric.Meter,
) (Manager, error)

NewManager creates a new builders manager. If meter is nil, metrics are disabled.

type Metrics

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

Metrics holds the metrics instruments for builder operations.

Jump to

Keyboard shortcuts

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