snapshot

package
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Sep 20, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package snapshot keeps a branch that holds the board as files, and reaps the refs whose tickets have arrived in a branch that matters.

It exists because a ticket nobody is working lives only on its ref, which means an untouched backlog lives only on the remote. Every participant's clone holds the refs it has fetched, so the board survives any one machine — but somebody cloning for the first time has no refs at all, and neither has somebody who never fetched. This branch is for them. It is a backup, not the storage: the working state is always on the refs.

The branch is built with plumbing and never checked out. That is not a trick to save time: the run happens in the background of somebody else's command, and a run that touched the working tree could not be allowed to happen while they were in the middle of anything.

Two properties are load-bearing:

  • The files live under board/, not under .jaira/tickets/. If they sat at the same path, the first person to merge this branch by accident would get an add/add conflict across every ticket at once — the worse version of the problem this design exists to avoid. A different path makes the collision impossible by construction rather than by care.
  • The reaping happens here, immediately after the write. At that moment the ticket is in two places: in this snapshot and in the branch it landed in. That is the difference between tidying up and throwing away, and it is why removing a ref belongs in this one place rather than in logbook, in archive and in a timer.

Index

Constants

View Source
const DefaultBranch = "jaira/board"

DefaultBranch is where the snapshot goes unless told otherwise.

View Source
const DefaultEvery = 72 * time.Hour

DefaultEvery is how old a snapshot may get before another is taken.

Three days rather than minutes, and the reason is not thrift: every participant's clone holds the refs locally, so the board is reconstructible from any of them. This is the backup for the first-time cloner, which is a slow case. Each ticket ref also carries its own history, so the snapshot is not the record of what happened either — a commit per write would buy nothing and cost hundreds of commits a day.

View Source
const Dir = "board"

Dir is the directory the ticket files live in inside the snapshot branch.

View Source
const DisableEnv = "JAIRA_NO_SNAPSHOT"

DisableEnv switches snapshots off, and is also the recursion guard handed to the spawned child, so there is one mechanism here rather than two.

Variables

This section is empty.

Functions

func Disabled

func Disabled() bool

Disabled reports whether snapshots are switched off for this process.

func Due

func Due(stateDir string, every time.Duration) bool

Due reports whether the last snapshot is older than every.

func SpawnRun

func SpawnRun(stateDir, boardRoot string, every time.Duration)

SpawnRun starts a detached child that takes the snapshot, if one is due.

func StampPath

func StampPath(stateDir string) string

StampPath is where the record lives, under the state directory the caller passes — never inside the repository, because when the backup last ran is this machine's business and committing it would be one more thing for two clones to disagree about.

func Task

func Task(stateDir, boardRoot string, every time.Duration) bgrun.Task

Task is the background job: take a snapshot when the last one is older than every. Everything careful about running it — stamping before the run, the recursion guard, not waiting, not spawning from a test binary — lives in core/bgrun, which the ref fetch uses too.

func WriteStamp

func WriteStamp(stateDir string, s Stamp) error

WriteStamp records that a run happened.

Types

type Result

type Result struct {
	// Branch is the snapshot branch.
	Branch string `json:"branch"`
	// Commit is the snapshot that was written, or "" when nothing changed.
	Commit string `json:"commit,omitempty"`
	// Tickets is how many tickets the snapshot holds.
	Tickets int `json:"tickets"`
	// Added and Removed are the ids this run put in and took out, against the
	// previous snapshot.
	Added   []string `json:"added,omitempty"`
	Removed []string `json:"removed,omitempty"`
	// Reaped are the refs deleted because their ticket has landed.
	Reaped []string `json:"reaped,omitempty"`
	// Unchanged says the set of refs was identical to the last snapshot, so no
	// commit was written and nothing was pushed.
	Unchanged bool `json:"unchanged"`
}

Result reports one run.

type Runner

type Runner struct {
	Repo   *gitref.Repo
	Branch string

	// LandingBranches are the branches whose contents mean "this ticket has
	// arrived": a ticket filed away in one of them is finished for everybody,
	// so its ref has done its job. Empty means nothing is reaped — an
	// unresolved answer must not delete anything, because a ref left standing
	// costs nothing while one removed by mistake takes away exactly the
	// visibility this is for.
	LandingBranches []string
}

Runner takes snapshots for one board.

func (*Runner) Drop

func (r *Runner) Drop(id string) error

Drop removes one ref without waiting for the ticket to land, for a branch that is never going to be merged.

Deliberately a separate act with its own command: the automatic path only ever removes a ref whose ticket is provably somewhere else, and a tool that quietly relaxed that rule would recreate the invisible window this whole design closes.

func (*Runner) Run

func (r *Runner) Run() (*Result, error)

Run writes a snapshot if the refs have changed since the last one, then reaps the refs whose tickets have landed.

type Stamp

type Stamp = bgrun.Mark

Stamp is what gets recorded, kept as this package's own name for it.

func ReadStamp

func ReadStamp(stateDir string) Stamp

ReadStamp returns the record, or a zero Stamp.

Jump to

Keyboard shortcuts

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