engine

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jun 10, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package engine orchestrates branch lifecycle as sagas over the registry, cow planner, and runtime driver. The CLI (P1) and branchd (P2) both embed it.

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidName = errors.New("invalid branch name")

ErrInvalidName rejects branch names that cannot be used across runtimes (docker container names, k8s pod names — RFC 1123 after the pgbranch-br- prefix). The API maps it to 400.

Functions

This section is empty.

Types

type Engine

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

func New

func New(reg *registry.Registry, drv runtime.Driver, defaultImage string) *Engine

New builds an engine on the default OverlayFS backend.

func NewWithPlanner

func NewWithPlanner(reg *registry.Registry, drv runtime.Driver, defaultImage string, planner cow.Planner) *Engine

NewWithPlanner selects the copy-on-write backend (branchd --cow).

func (*Engine) AddSource

func (e *Engine) AddSource(ctx context.Context, s *registry.Source, password string) error

AddSource registers a source and seeds it from the given live Postgres.

func (*Engine) BranchUsage

func (e *Engine) BranchUsage(ctx context.Context, name string) (int64, error)

BranchUsage measures a branch's copy-on-write layer in bytes (the branch's own writes, not the shared source data). Overlay: `du -sb` on the rw volume; zfs: the clone's `used` property (space unique to the clone). It is a helper-container roundtrip — cheap, but not free.

func (*Engine) CreateBranch

func (e *Engine) CreateBranch(ctx context.Context, name, sourceName string, ttl time.Duration) (*registry.Branch, error)

CreateBranch is a saga: every step registers a compensation that runs (in reverse order) if a later step fails. No orphans, ever. ttl 0 means the branch never expires.

func (*Engine) CreateBranchFrom

func (e *Engine) CreateBranchFrom(ctx context.Context, name, parentName string, ttl time.Duration) (*registry.Branch, error)

CreateBranchFrom creates a branch whose base is another (ready) branch's current state — branch-from-branch.

Overlay backend: a freeze saga. The parent's rw volume cannot be shared writable, so it is frozen into an immutable layer:

CHECKPOINT parent -> stop parent -> fresh parent rw volume ->
restart parent on [frozen rw, …its old chain…, source] (wait ready) ->
start child on the same chain -> commit (layer row + parent rw swap,
atomic) -> child ready.

The parent gets a new container (and so possibly a new host port; the wire router resolves live, so dbname@parent connections just reconnect). On any failure before the commit the parent is restored to its original rw volume and chain and restarted; if even that fails it is marked failed — never half-frozen. The layer row is committed only after both restarts succeeded.

ZFS backend: block-level CoW — snapshot the parent's clone and clone that. No freeze, no stop, no layer rows.

CSI backend: the child's PVC is a clone of the parent's PVC. No freeze or layer rows either, but the parent is briefly stopped around the clone for crash consistency (see provisionCSI).

func (*Engine) DestroyBranch

func (e *Engine) DestroyBranch(ctx context.Context, name string) error

func (*Engine) ReapExpired

func (e *Engine) ReapExpired(ctx context.Context, now time.Time) (destroyed []string, err error)

ReapExpired destroys every ready/failed branch whose TTL has passed. Called by branchd's reaper loop; now is injected for testability.

func (*Engine) Reconcile

func (e *Engine) Reconcile(ctx context.Context) error

Reconcile aligns the registry with reality at startup: stuck 'creating' branches are failed and their resources cleaned; managed containers with no registry row are removed.

func (*Engine) RefreshSource

func (e *Engine) RefreshSource(ctx context.Context, name, password string) error

RefreshSource re-seeds a source into a fresh generation volume. Existing branches keep the volume they were created from; only new branches see the new generation. The previous generation's volume is GC'd once no live branch references it. A failed seed leaves the current generation intact.

func (*Engine) RemoveSource

func (e *Engine) RemoveSource(ctx context.Context, name string) error

RemoveSource deletes a source's volume, its orphaned frozen layers, and the registry rows. Refused while any live branch still uses the source or (defensively) while any layer is still referenced.

func (*Engine) ResetBranch

func (e *Engine) ResetBranch(ctx context.Context, name string) (*registry.Branch, error)

ResetBranch throws away a ready branch's writes and reprovisions it from its recorded source volume on the same registry row (ready -> resetting -> ready; new container id and host port).

func (*Engine) RunReaper

func (e *Engine) RunReaper(ctx context.Context, interval time.Duration, logf func(format string, args ...any))

RunReaper destroys expired branches every interval until ctx is done. branchd runs it as a goroutine; logf (optional, nil = silent) receives destroy/error reports.

Jump to

Keyboard shortcuts

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