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 ¶
- Variables
- type Engine
- func (e *Engine) AddSource(ctx context.Context, s *registry.Source, password string) error
- func (e *Engine) BranchUsage(ctx context.Context, name string) (int64, error)
- func (e *Engine) CreateBranch(ctx context.Context, name, sourceName string, ttl time.Duration) (*registry.Branch, error)
- func (e *Engine) CreateBranchFrom(ctx context.Context, name, parentName string, ttl time.Duration) (*registry.Branch, error)
- func (e *Engine) DestroyBranch(ctx context.Context, name string) error
- func (e *Engine) ReapExpired(ctx context.Context, now time.Time) (destroyed []string, err error)
- func (e *Engine) Reconcile(ctx context.Context) error
- func (e *Engine) RefreshSource(ctx context.Context, name, password string) error
- func (e *Engine) RemoveSource(ctx context.Context, name string) error
- func (e *Engine) ResetBranch(ctx context.Context, name string) (*registry.Branch, error)
- func (e *Engine) RunReaper(ctx context.Context, interval time.Duration, ...)
Constants ¶
This section is empty.
Variables ¶
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 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) BranchUsage ¶
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 (*Engine) ReapExpired ¶
ReapExpired destroys every ready/failed branch whose TTL has passed. Called by branchd's reaper loop; now is injected for testability.
func (*Engine) Reconcile ¶
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 ¶
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 ¶
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 ¶
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.