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
- func Disabled() bool
- func Due(stateDir string, every time.Duration) bool
- func SpawnRun(stateDir, boardRoot string, every time.Duration)
- func StampPath(stateDir string) string
- func Task(stateDir, boardRoot string, every time.Duration) bgrun.Task
- func WriteStamp(stateDir string, s Stamp) error
- type Result
- type Runner
- type Stamp
Constants ¶
const DefaultBranch = "jaira/board"
DefaultBranch is where the snapshot goes unless told otherwise.
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.
const Dir = "board"
Dir is the directory the ticket files live in inside the snapshot branch.
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 StampPath ¶
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 ¶
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 ¶
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 ¶
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.