Documentation
¶
Overview ¶
clear.go: `nova-sprint table clear` (#3637). Zeroes the table's landed column in under a second and leaves waiting untouched: every member of every ws:<s>:landed set moves to done/ok through the one task move (ns_tcard_move, fn/lua/02_card_move.lua, #3778: landed -> done/ok; the card stays, in ws:<s>:done, which the stream table does not print), and each friend's current done count (ZCARD of its done, merging and landed card sets) is stored in ws:done0 (no longer read by the table, #4071). working and merging are live places, not counters, so a clear never moves them.
Round trips: the stream and friend lists, the landed members and done counts, the landed tasks' fields (the checkpoint), then ONE MULTI/EXEC that applies every move. The caller writes the checkpoint before Apply.
live.go: the live layout of nova-sprint table (#2674), a Go port of the bash of record rowan-tools bin/sprint-table-redis. It reads the keys that script reads and prints its layout byte for byte, but for one line:
SPRINT TABLE / the one count / blank / the bench block / two blanks / the friend block.
The progress line is the one count (ws.SprintCounts.Header, nova-tools #4411): the numbers sprint status, ws counts and the sprint table print, the streams' sentinels never counted. The bash printed sprint-xy's sprint:<S>:xy (or SPRINT-XY.txt, and a stale line when both were missing); that key is no longer read, and MaskXY is the one documented difference the parity control and --compare mask on both sides.
Keys (all read-only; each has one writer elsewhere):
friend:<f> HMGET at up ready working done (friend-row)
friend:<f>:down GET, a set value prints "down" (out-of-credits)
ws:order, ws:<s>:*, the one count (ws.CountsReader): the memberships ride
ws:log, sprint:order the SCAN walk's first round trip, every count the pipeline
s:<S>:pitstop HGETALL, the pitstop verb's hash: the title reads
*** PIT STOP *** <why> since <at> (#3423, #3887)
bench:* SCAN COUNT 1000, then HGETALL (bench-row, card-dealer)
bench:<b>:cards:<w> ZCARD, w = ready working done ok fail (the card move, #3692)
ci:nomirror:<b> SMEMBERS, the repos the bench has no mirror of (ns_ci_release, #3724)
bench:_pool:cards:ready ZCARD, the pool line: cards not dealt (#2733)
sprint:<S>:cards EXISTS, the sprint has cards: the pool line prints at 0
A host row's ready, working, done, ok and fail are the ZCARDs of its card views, read in the same pipeline (nova-tools#3692, ONE PLACE: every card is in one place, and these sets are the bench view of it). The bash bench-row's queue, working, done, ok and fail fields are no longer read: it counted job dirs, and cards that had ended printed as "-". host, at and load1 still come from the bench's own hash.
A host row ends " | nomirror=<repos>" while ci:nomirror:<b> is non-empty (#3804): every CI claim of those repos skips the bench until its mirror exists, so the defect is on the row; "?" when the set could not be read.
Bench keys are found by SCAN, as the bash does (a cursor walk; the bench ACL user has no KEYS and no EVAL_RO); every value is then read in ONE pipelined round trip.
sprint.go: the whole sprint table (#3530, part of #3662), the one screen Glenn watches, read from Redis once a second. It replaces the bash renderers of 2026-09-24 (a streams renderer that asked GitHub, an ETA script, sprint-table-redis for the host and friend blocks, and a shell loop that stitched their files together). Layout, one blank line between blocks:
SPRINT TABLE [*** PIT STOP ***] <landed>/<total> done <z>%, left <l>, eta <HH:MM> ET gh <n>/h (ws.SprintCounts.Header) stream | waiting | ready | working | review | merging | landed (rows in ws:order, all-zero rows hidden, total) REVIEW stream=<s> over=<n> oldest=<id> age=<d> max=<d> (a stream with cards in review past cfg:review max_age, #4072) consumer | ready | working | done | ok | fail | ok% | status | load (one row per consumer, total)
review is ZCARD ws:<s>:review: one state for every card past working that is not yet merging (Glenn 2026-09-26 8:20 AM ET, "let's do review": a card whose consumer copy failed and waits for its typed verdict (#4072), and a card whose PR waits for its read; the old reading set and the merging <read>/<unread> split (#3900, #3929) are gone). Every cell is one plain ZCARD; it is left, never done. The headline and the stream block are one read of ws.Counts (the one count, #4411): the headline's total is the total row's sum, and each stream's sentinel is counted nowhere (it is the stream's stop, not work: in no cell, no total, no x/y and no left).
The consumer table is ONE table (#4071, Glenn 2026-09-25 2:40 PM: "friends can fuck up cards too"): a row per consumer, friends and benches alike, named <kind>:<name> (friend:emma, bench:hetzner) so the kind shows. Every cell is one ZCARD of <kind>:<name>:cards:<set> for set = ready, working, ok, fail; done = ok + fail and ok% = ok / done are derived, never stored, with no sprint window and no base from a clear. The cells count consumer work only, by structure (nova-tools#4237): a record naming a probe is refused by every move into <kind>:<name>:cards:<set> (cm_zadd and the move gates in 02_card_move.lua), and a probe's result lives on the bench beat (bench:<b>:beat probe, fleet build), which this table never counts; after sprint clear and a fleet roll every row reads 0 | 0 | 0 | -. status is up when the consumer's own beat (<kind>:<name>:beat at, ms) is under a minute old and <kind>:<name>:down does not exist, else down (the row still shows its cards); an up consumer whose desired hash has paused 1 (worker pause, #4308) prints paused instead; an up bench whose last fleet play stopped (bench:<b>:play result failed:<role>, #4356) prints behind: <role>; load is the beat's cpu or load1 (a bench beat's, or a friend beat's, which nova-friend's beat measures on the machine the friend's session runs on, #4233; - when the beat has none). The old friend:<f> row hash and bench:<b> hash are never read, and no friend's load is read from another consumer's beat.
Keys, every one read in ONE pipelined round trip per tick (a second round trip only on the tick a membership set changed; never KEYS, never SCAN):
ws:order ZRANGE, the streams in rank order (the ws index, #3662)
ws:<s>:<state> ZCARD for waiting, ready, working, review, merging, landed, parked
ws:log XRANGE over the last hour: the landed rate for the ETA
sprint:order, s:<S> ZRANGE and HGET status, no sprint named: the open sprint
friends, benches, SMEMBERS: the consumers (friends the --friends roster
consumers when given; then the benches; then any other
enrolled consumer), each once
<c>:cards:<set> ZCARD for set = ready, working, ok, fail
<c>:beat HMGET load1 at ncpu cpu models
<c>:down EXISTS (a string or a hash; either means down)
<c>:desired HGET paused (1: the status reads paused while up)
bench:<b>:play HGET result (failed:<role>: the status reads behind: <role>)
s:<S>:pitstop EXISTS, with the legacy sprint:<S>:pitstop
The membership of ws:order, friends, benches and consumers is kept from the previous tick, so the tick's one pipeline reads the sets and every member's values together; a tick that finds a set changed reads again at once with the new ones, so a row is never rendered from last second's membership.
streams.go: the stream block as a nova-table (internal/ntable). Glenn 2026-09-27: "The work stream table is really just a series of ordered sets, per-cell" / "and the value printed, happens to be for each cell, |s|". The streams table's rows are the streams of ws:order and its cells are BOUND to the sets the card model owns, ws:<s>:<state> under the epoch (ws.KeyAt), one count column per state of ws.Stream, each folding to its sum in the footer row total; the row labels are the stream names. Nothing is copied: the sprint tick reads every cell through ntable.QueueCells in its one pipeline (the ws.CellReader seam of ws.CountsReader, so the headline and the block are one count, #4411), renders the block through ntable.Render, and the sprint loop binds the table in the store (ntable.Bind) whenever its shape moves, so `nova-table render streams` prints the same block from the same sets. A row's excluded member is the stream's sentinel: the stream's stop, not work, counted nowhere (#4318).
Package table parses and renders the nova-sprint table from the single consistent snapshot returned by the ns_snapshot Redis Function. One call, one server instant: section 6 of #2756.
Index ¶
- Constants
- Variables
- func AcquireLock(ctx context.Context, client redis.UniversalClient, key, token string, ...) (holder string, err error)
- func BenchPlayKey(bench string) string
- func CheckLive(ctx context.Context, client *redis.Client, out, sprint string, now time.Time) (string, error)
- func ConsumerCards(consumer string, n [4]int) [][]string
- func DefectFixture() [][]string
- func DefectGolden() string
- func DiffCells(published, direct string) string
- func Fixture2674() [][]string
- func Fixture2674Degraded() [][]string
- func Fixture2674Now() time.Time
- func FleetFixture() [][]string
- func FleetFixtureOf(n int) [][]string
- func FriendCardsKeyAt(e uint64, friend, where string) string
- func Golden2674() string
- func Golden2674Degraded() string
- func Golden2674NoRedis() string
- func Golden3530() string
- func LiveSnapshot2674() string
- func MaskXY(table string) string
- func NoMirrorKey(bench string) string
- func PlayBehind(result string) string
- func PoolViewKeyAt(e uint64) string
- func PrepareCheck(ctx context.Context, client *redis.Client) (seeded bool, err error)
- func ReleaseLock(ctx context.Context, client redis.UniversalClient, key, token string) error
- func SprintFixture() [][]string
- func SprintFixtureNow() time.Time
- func StreamsDefinition() ntable.Table
- func StreamsOf(counts ws.SprintCounts) ntable.Table
- func StreamsShape(streams []string, epoch uint64) ntable.Table
- type BenchRow
- type ClearPlan
- type Consumer
- type ConsumerRow
- type FixtureStream
- type FriendRow
- type LiveConfig
- type LiveSnapshot
- type Pipeline
- type Proc
- type ProgressEvents
- type Row
- type Snapshot
- type SprintConfig
- type SprintReader
- type SprintSnapshot
- type StreamRow
Constants ¶
const ( FleetCards = 1000 FleetStreams = 13 FleetFriends = 4 FleetBenches = 7 FleetOpenSprints = 9 )
Fleet fixture sizes (#3893): the shape of the fleet store on 2026-09-25, rounded up, so the wide table is proven to render at the size it refused.
const ( MaxSprints = 1024 MaxOpenSprints = 16 MaxBenches = 64 MaxFriends = 16 BoundRemedy = "--layout live" )
Bounds of the snapshot (6.3), the same numbers as ns_snapshot's. A registry larger than its bound makes the function return one error line that names it (#3893): `snapshot: bound exceeded: bound=<name> value=<n> limit=<n> remedy=<flag>`. MaxSprints bounds the registry of every sprint ever made (closed ones stay in it); MaxOpenSprints bounds the open sprints whose rows are read.
const BenchBeatInterval = time.Second
BenchBeatInterval is the cadence a bench writes its host row at.
const DoneBaseKey = "ws:done0"
DoneBaseKey holds each friend's done count at the last `table clear` (#3637). The sprint table no longer reads it (#4071: the consumer done column is ok + fail, ZCARDs with no base); a clear still records it.
const LiveWindow = 2 * time.Second
LiveWindow is how young the renderer's published file must be for `table --check --live` (#2756 6.8, #3253): a renderer stopped for longer is a failed check, not a stale pass.
const LoadWindow = 10 * time.Second
LoadWindow is how long a load sample stays in a row's sliding window.
const NeverCounted = "?/? done ?%, left ?, eta ?"
NeverCounted is the progress line before any good read.
const ProgressKey = "proc:progress"
ProgressKey is proc:progress, the progress duty's record (reconcile.ProgressKey; the table does not import reconcile).
const RetiredPipeline = `REFUSED pipeline reads a retired key family; remedy="nova-sprint ws counts"`
RetiredPipeline is the wide table's pipeline row, always (#4411): the row's cells were the retired card family (s:<S>:idx:card:<state>, s:<S>:pool, s:<S>:waiting), which is not a count of the sprint's work (its cards are task records in the ws index, counted by the one count, ws.Counts). card push and 02_card_move.lua still write that family, so a number there would print beside the one count and disagree with it; the row refuses whatever the family holds, the way census does, and names the verb that counts. ns_snapshot still returns the cells (the reply's shape); they are parsed and never printed.
const StreamsOwner = "nova-sprint task move"
StreamsOwner is the verb that writes the sets the streams table's cells are bound to: a write through nova-table is refused naming it.
const StreamsTable = "streams"
StreamsTable is the streams table's name in the store.
Variables ¶
var CheckpointFields = []string{"title", "pr", "head", "owner", "kind", "route", "ref", "created_at", "state_at"}
CheckpointFields are the task fields a clear checkpoint keeps, in order.
var ConsumerSets = []string{"ready", "working", "ok", "fail"}
ConsumerSets are the four <kind>:<name>:cards:<set> sets a consumer row counts, in column order (done = ok + fail is derived).
FriendDoneWheres are the friend card sets a clear's checkpoint counts as a friend's done work (#3778): done, and merging and landed for a task that named a PR.
var SprintFixtureStreams = []FixtureStream{
{"swarm: cards", 150, 5, 6, 3, 0, 0},
{"nova-sprint + merge + bus", 310, 6, 0, 2, 1, 2},
{"nova sprint migration", 14, 0, 0, 0, 0, 0},
{"fleet, ci, secrets, jev", 0, 0, 2, 2, 0, 1},
{"redis: store + bus", 81, 0, 0, 0, 0, 0},
{"nova-work", 0, 0, 0, 0, 0, 0},
{"landing: streams + lander", 3, 0, 0, 0, 2, 0},
{"docs", 0, 0, 0, 0, 0, 0},
{"rowan-tools", 1, 0, 0, 0, 0, 3},
{"harvest", 0, 4, 0, 0, 0, 0},
}
SprintFixtureStreams are the fixture's streams in rank order with their waiting, ready, working, review, merging and landed counts.
var StreamsRenderOpts = ntable.RenderOpts{HideZeroRows: true, Title: "stream", LabelWidth: nameWidth}
StreamsRenderOpts renders the block as the sprint table always has: the label column headed "stream" and 25 wide, every all-zero row hidden (the whole block when none is left); `nova-table render streams --hide-zero-rows` prints the same block headed by the table's name.
var WSStates = ws.Stream
WSStates are the six per-stream sets the table counts, in reply order: the stream line ws.Stream (Glenn 2026-09-26). review is where a card waits for a verdict or a read.
Functions ¶
func AcquireLock ¶
func AcquireLock(ctx context.Context, client redis.UniversalClient, key, token string, ttl time.Duration) (holder string, err error)
AcquireLock takes key for token, or returns the holder's token.
func BenchPlayKey ¶
BenchPlayKey is the bench's fleet play receipt, and PlayBehind the role its result says the play stopped in ("" for ok): the table's own spelling of fleetbuild.PlayKey and fleetbuild.BehindRole (#4356), since fleetbuild's tests import this package; TestPlayReceiptSpellingIsTheTables holds the two to one another.
func CheckLive ¶
func CheckLive(ctx context.Context, client *redis.Client, out, sprint string, now time.Time) (string, error)
CheckLive is `table --check --live` (#2756 6.8, #3253): the renderer's --out file must be younger than LiveWindow at now, and every cell it holds must equal the same cell of a direct read (one FCALL_RO ns_snapshot, named sprint included) taken now. A second-writer key makes the direct read carry an error, which fails the check by name. The error names the failing cell; the receipt is one line.
func ConsumerCards ¶
ConsumerCards is n[i] copy ids in <consumer>:cards:<ConsumerSets[i]>, as ZADD commands scored by age: created_at from two hours before the fixture's now.
func DefectFixture ¶
func DefectFixture() [][]string
DefectFixture seeds the defects of 2026-09-22 (6.8) so that `table --check` renders them and asserts the exact output. Tests then add each forbidden sidecar key in turn to prove the two-writers refusal.
The copy's lease_until is deliberately in the past so the stale count is deterministic; no value in the fixture is relative to now. The rows are the consumer sets (#3998): ready and working are <consumer>:cards:ready and :cards:working.
func DefectGolden ¶
func DefectGolden() string
DefectGolden is the exact table DefectFixture must render.
func DiffCells ¶
DiffCells compares a published table with a direct render cell by cell and names the first cell that differs, or returns "" when every cell is equal. A proc age may differ by the live window's seconds, since it counts from the tick that rendered it.
func Fixture2674 ¶
func Fixture2674() [][]string
Fixture2674 is the live snapshot as Redis commands, one per key, in file order. Lines are tab-separated; "#" lines are comments.
func Fixture2674Degraded ¶
func Fixture2674Degraded() [][]string
Fixture2674Degraded is applied on top of Fixture2674(): every branch of the bash the live snapshot did not happen to take. Every age is at least 15 s from its threshold, so a render a few seconds late prints the same cells.
func Fixture2674Now ¶
Fixture2674Now is the capture instant of the snapshot (its "captured=" line).
func FleetFixture ¶
func FleetFixture() [][]string
FleetFixture seeds a fleet-shaped keyspace: FleetCards cards spread over FleetStreams streams and FleetOpenSprints open sprints, FleetBenches benches, FleetFriends friends, and a sprint registry that also holds closed sprints and a control sprint, 13 names in all (the registry bound of 4 refused the fleet at 9). Each card is a card:<id> record whose where names the one ws:<stream>:<where> set that holds it, scored by created_at; the wide table reads the per-sprint card indexes and the bench queues beside them. Commands are variadic so the whole seed is a few hundred calls.
func FleetFixtureOf ¶
FleetFixtureOf is FleetFixture with n cards in place of FleetCards, so a test can show the table's cost does not grow with the cards.
func FriendCardsKeyAt ¶
func Golden2674 ¶
func Golden2674() string
Golden2674 is the bash of record's SPRINT-TABLE.txt on Fixture2674().
func Golden2674Degraded ¶
func Golden2674Degraded() string
Golden2674Degraded is the bash's table on Fixture2674() plus Fixture2674Degraded(): missing, stale and down friend rows, no xy or landed key, an empty q:blocked, no bench:pool, a hostless hash, and fresh and stale dealer counts. A stale bench is not here: the bash drops it and Go prints it "stale" (#3372), so it lives in the dead-bench divergence case.
func Golden2674NoRedis ¶
func Golden2674NoRedis() string
Golden2674NoRedis is the bash's first tick when Redis does not answer.
func Golden3530 ¶
func Golden3530() string
Golden3530 is the whole table rendered from SprintFixture at SprintFixtureNow.
func MaskXY ¶
MaskXY is the one documented difference between the live layout and the bash of record (nova-tools #4411): the bash's progress line (sprint-xy's sprint:<S>:xy, or its SPRINT ? line) and its xy stale lines against the one count's line. It replaces the line after the title's blank with "X/Y MASKED" and drops every "stale: ... xy key missing" line, so the parity control and --compare compare every other byte.
func NoMirrorKey ¶
NoMirrorKey is ci:nomirror:<bench>, written only by the ci_run.lua functions (internal/nsprint/ci names the same key).
func PlayBehind ¶
PlayBehind is the role a play receipt's result names after failed:.
func PoolViewKeyAt ¶
PoolViewKeyAt is the undealt pool under epoch e, the card move's bench view for cards with no bench (bench:_pool's ready set, nova-tools#4238).
func PrepareCheck ¶
PrepareCheck readies a store for `table --check` (#3253). In one pipeline it reads DBSIZE and the sprints set. An empty store is seeded with DefectFixture in one MULTI, so the check needs no hand-loaded keyspace. A store whose sprints set holds a sprint that is neither a control sprint nor one of the fixture's own sprints is the live fleet: PrepareCheck refuses it and names that sprint. It reports whether it seeded.
func ReleaseLock ¶
ReleaseLock deletes key only while it still holds token.
func SprintFixture ¶
func SprintFixture() [][]string
SprintFixture is the keyspace as Redis commands.
func SprintFixtureNow ¶
SprintFixtureNow is the fixture's instant.
func StreamsDefinition ¶
StreamsDefinition is the streams table with no rows: waiting, ready, working, review, merging and landed as count:sum as wide as their headers, footer total; the row labels (the stream names) are the render's own first column.
func StreamsOf ¶
func StreamsOf(counts ws.SprintCounts) ntable.Table
StreamsOf is the streams table filled from the one count: one row per stream of counts, its cells' counts and unread marks those rows carry. The block renders from it, so a snapshot built from counts alone (a failed tick's last good rows, a test's) prints the same block as a tick's.
Types ¶
type BenchRow ¶
type BenchRow struct {
Key string // the key suffix, bench:<Key>
Fields map[string]string
// NoMirror is ci:nomirror:<Key>, sorted and comma-joined: "" when the
// set is empty, "?" when it could not be read (#3804).
NoMirror string
}
BenchRow is one bench:<b> hash, values already sanitized the way the bash's awk does.
type ClearPlan ¶
type ClearPlan struct {
At time.Time
Epoch uint64 // the sprint epoch the plan was read under (#4238)
Streams []string
Landed map[string][]redis.Z // stream -> landed members (score landed_at ms)
Tasks map[string]map[string]string // task id -> task:<id> fields; absent when no hash
Friends []string
Done map[string]string // friend -> done count now
}
ClearPlan is what a clear will move, read before anything is written.
func PlanClear ¶
func PlanClear(ctx context.Context, client redis.UniversalClient, friends []string, now time.Time) (*ClearPlan, error)
PlanClear reads what a clear at now would move. friends empty reads the friends SET.
func (*ClearPlan) Apply ¶
func (p *ClearPlan) Apply(ctx context.Context, client redis.UniversalClient, by, why, receipt string) error
Apply moves every planned landed member to done/ok through the one task move and stores the done base, in one MULTI/EXEC. receipt is stored as ws:checkpoint. A member the move refuses (it left landed since the plan, or its record is gone) stays where it is and is named in the error.
func (*ClearPlan) Checkpoint ¶
Checkpoint is the durable record of what the clear moves, as TSV: a comment line, then one `task` row per landed member (stream, id, landed_at ms, then CheckpointFields) and one `friend` row per done count.
type Consumer ¶
type Consumer struct{ Kind, Name string }
Consumer is one consumer of copies: <Kind>:<Name>, bench or friend.
type ConsumerRow ¶
type ConsumerRow struct {
Consumer
Ready, Working, OK, Fail int64
Unread [4]bool
Up bool
Paused bool
Behind string
Load string
// Models is a friend beat's models field: the models of the copies it
// holds in working (life.FriendBeat); the row prints it beside the name
// while the row is up and working.
Models string
}
ConsumerRow is one row of the consumer table (#4071): the four ZCARDs of <kind>:<name>:cards:ready|working|ok|fail, Unread per cell when its ZCARD did not come back (it prints "?", never a false 0), Up from the beat and the down key, Paused from the desired hash (worker pause, #4308), Load from the beat ("-" when it has none), Behind the role a bench's last fleet play stopped in (#4356; "" when it did not).
func (ConsumerRow) Done ¶
func (r ConsumerRow) Done() int64
Done is every copy that ended on the consumer: ok plus fail.
func (ConsumerRow) Status ¶
func (r ConsumerRow) Status() string
Status is the row's status cell: down, behind: <role> (up, its last fleet play stopped in role), paused (up and paused) or up.
type FixtureStream ¶
FixtureStream is one fixture stream's seven set sizes, in WSStates order.
type FriendRow ¶
type FriendRow struct {
Name string
At, Up, Ready, Working, Done string
OK, Fail string // friend:<f>:cards:ok|fail ZCARDs: its copies ended (#3929)
Down string
// Stale is the whole table's count of the friend's working set members
// with no live child (#3892): "" on the bash layout, "?" unread.
Stale string
}
FriendRow is one friend:<f> hash plus its down flag, raw.
type LiveConfig ¶
type LiveConfig struct {
Friends []string // the roster, in display order
Sprint string // the pit stop (pitstop.Key) and the one count's sprint; "" the open one
RowStale time.Duration // a friend row older than this prints "stale" (bash ROW_STALE_S=10)
// BenchStale: a host row whose own at is older than this prints "stale";
// zero is 2 x BenchBeatInterval (#3372). The bash of record used 60 s.
BenchStale time.Duration
}
LiveConfig names what the bash hard-codes; nothing here is compiled in.
func Fixture2674Config ¶
func Fixture2674Config() LiveConfig
Fixture2674Config is the bash's roster and sprint (FRIENDS, XYKEY), its friend staleness (ROW_STALE_S=10) and its 60 s bench beat freshness.
type LiveSnapshot ¶
type LiveSnapshot struct {
Config LiveConfig
// Epoch is the sprint epoch the card cells were read under
// (nova-tools#4238); a friend row stamped with another epoch shows zero.
Epoch uint64
Friends []FriendRow
// Counts is the one count (ws.Counts) the progress line prints; At zero
// is never read.
Counts ws.SprintCounts
// Pitstop is s:<S>:pitstop, the one key `nova-sprint pitstop set|clear`
// writes (#3887): while it exists the title says PIT STOP with its why
// and at. A key of another type there (the 09-23 string) still stops the
// dealer, so it shows too, By wrongtype, until the verb repairs it.
Pitstop pitstop.Stop
Benches []BenchRow
// Pool is the pool line's count: the ZCARD of bench:_pool:cards:ready
// (the undealt view the card move keeps, #2733) whenever that view has
// cards or the sprint's roster exists; otherwise the retired card-dealer
// bench:pool hash's queue, as the bash of record read it. PoolPresent
// says whether the line prints.
Pool string
PoolPresent bool
// Stale is set by the loop when this tick's read failed and the friend
// rows and the counts are the last good read (LastGood is when).
Stale bool
LastGood time.Time
}
LiveSnapshot is one read of the live keyspace.
func FailedLive ¶
func FailedLive(cfg LiveConfig, last *LiveSnapshot) *LiveSnapshot
FailedLive is the tick whose read failed: the friend, counts and pit stop values of last (nil when there never was a good read), no bench rows, and a stale line (the bash's LAST_FROWS path).
func ReadLive ¶
func ReadLive(ctx context.Context, client redis.UniversalClient, cfg LiveConfig) (*LiveSnapshot, error)
ReadLive reads the live keyspace: the SCAN cursor walk for bench:* (its first page pipelined with the one count's memberships), then one pipeline for every value, the one count's cells among them: two round trips while ws:order holds still between them.
func (*LiveSnapshot) RenderLive ¶
func (s *LiveSnapshot) RenderLive(now time.Time) string
RenderLive prints the bash layout at now.
type Pipeline ¶
type Pipeline struct {
Sprint string
Cards map[string]int64
Pool int64 // s:<S>:pool: queued cards whose every DEPENDS-ON is landed (#3066)
Waiting int64 // s:<S>:waiting: queued cards with a DEPENDS-ON not yet merged on their base
Backpressure int64
Orphan int64
Reconcile int64
}
Pipeline is one sprint's cells of the retired card family (6.4), as ns_snapshot returns them; Render never prints them (RetiredPipeline).
type ProgressEvents ¶
type ProgressEvents struct {
Events int64 // asks the system made (pit stop set with a diagnosis)
Refused int64 // the duty refusals of the last pass, each counted once
Last string // the last EVENT line
// Unread is the read error when proc:progress did not come back: the
// line then says so rather than showing a quiet none.
Unread string
}
ProgressEvents is proc:progress as read.
func ParseProgressEvents ¶
func ParseProgressEvents(h map[string]string) ProgressEvents
ParseProgressEvents reads an HGETALL of proc:progress; a missing or non-numeric count is 0.
func (ProgressEvents) Line ¶
func (e ProgressEvents) Line() string
Line is `EVENTS n=<asks> refused=<n> last=<line>` when either count is non-zero, `EVENTS not read: <err>` when the record did not come back, else "" (no line).
type Row ¶
type Row struct {
Name string
Up bool
Desired int64
Missing bool
Ready int64
Working int64
Stale int64
Leased int64
Queue int64
Done int64
Why string
}
Row is one bench or friend. Benches and friends are rows of one shape (6.4): name | up | desired | ready | working | stale | leased | queue | done | why, read from the consumer's sets (#3998): ready and leased are ZCARDs of <consumer>:cards:ready|working, stale the working copies whose lease lapsed, working the rest. Width is leased, never stored (6.5).
type Snapshot ¶
type Snapshot struct {
Time int64
Benches []Row
Friends []Row
Pipelines []Pipeline
Procs []Proc
Errors []string
}
Snapshot is one consistent instant.
func Read ¶
Read takes one consistent server snapshot. Callers must load the nova_sprint function library during deployment; rendering is read-only.
type SprintConfig ¶
type SprintConfig struct {
// Sprint names the sprint: its pit stop keys s:<Sprint>:pitstop and
// sprint:<Sprint>:pitstop; empty reads the open one's.
Sprint string
// Friends is the friend rows' order; empty reads the friends SET,
// sorted by name.
Friends []string
// LockKey/LockToken, when set, refresh the writer's lock in the tick's
// own pipeline (see AcquireLock); the read reports LockLost when it is gone.
LockKey, LockToken string
LockTTL time.Duration
}
SprintConfig is what the whole table is told; everything else is read.
func SprintFixtureConfig ¶
func SprintFixtureConfig() SprintConfig
SprintFixtureConfig is the roster in Glenn's order and the fixture sprint.
type SprintReader ¶
type SprintReader struct {
Client redis.UniversalClient
Config SprintConfig
// contains filtered or unexported fields
}
SprintReader reads the whole table, keeping set membership across ticks.
func NewSprintReader ¶
func NewSprintReader(client redis.UniversalClient, cfg SprintConfig) *SprintReader
NewSprintReader is a reader with no membership yet: its first Read takes two round trips (the sets, then the values).
func (*SprintReader) Read ¶
func (r *SprintReader) Read(ctx context.Context, now time.Time) (*SprintSnapshot, error)
Read is one tick at now.
type SprintSnapshot ¶
type SprintSnapshot struct {
Config SprintConfig
// Epoch is the sprint epoch every cell of this snapshot was read under
// (nova-tools#4238): sprint:epoch, read in the same pipeline as the
// cells; a cell of another epoch is never shown.
Epoch uint64
Pitstop bool
// Streams is Counts.Streams as rows, for readers of one stream's cells.
Streams []StreamRow
// Counts is the one count (ws.Counts) the headline, the stream rows and
// the total row all print from.
Counts ws.SprintCounts
GHHour int64 // GitHub calls in the hour before the read (gh:calls:all, #4343)
// Events is proc:progress as the progress duty wrote it (#4319): the
// asks so far, the last EVENT line, and the last pass's duty refusals.
// The table prints one EVENTS line from it only when non-zero.
Events ProgressEvents
// Consumers are the consumer table's rows, in display order (#4071).
Consumers []ConsumerRow
// RoundTrips is how many pipelines the read took: 1 in steady state.
RoundTrips int
// LockLost says the tick found the writer's lock held by someone else.
LockLost bool
// Stale is set when this tick's read failed; the rows are LastGood's.
Stale bool
LastGood time.Time
// Errors are the tick's partial failures (a pit stop key, the ws:log
// window or the Studio beat that did not come back): the rows stand,
// and each prints as one ERR line under the tables, never nothing.
Errors []string
}
SprintSnapshot is one tick's read.
func FailedSprint ¶
func FailedSprint(cfg SprintConfig, last *SprintSnapshot) *SprintSnapshot
FailedSprint is the tick whose read failed: last's rows (none when there never was a good read) and a stale line.
type StreamRow ¶
type StreamRow struct {
Name string
Waiting, Ready, Working, Review, Merging, Landed int64
Unread [6]bool
}
StreamRow is one stream's six counts, in WSStates order. Unread marks a cell whose ZCARD did not come back: it prints "?", never a false 0 (a 0 there would also feed XY's left, pct and eta).