table

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Sep 28, 2026 License: MIT Imports: 15 Imported by: 0

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

View Source
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.

View Source
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.

View Source
const BenchBeatInterval = time.Second

BenchBeatInterval is the cadence a bench writes its host row at.

View Source
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.

View Source
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.

View Source
const LoadWindow = 10 * time.Second

LoadWindow is how long a load sample stays in a row's sliding window.

View Source
const NeverCounted = "?/? done ?%, left ?, eta ?"

NeverCounted is the progress line before any good read.

View Source
const ProgressKey = "proc:progress"

ProgressKey is proc:progress, the progress duty's record (reconcile.ProgressKey; the table does not import reconcile).

View Source
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.

View Source
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.

View Source
const StreamsTable = "streams"

StreamsTable is the streams table's name in the store.

Variables

View Source
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.

View Source
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).

View Source
var FriendDoneWheres = []string{ws.Done, ws.Merging, ws.Landed}

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.

View Source
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.

View Source
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.

View Source
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

func BenchPlayKey(bench string) string

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

func ConsumerCards(consumer string, n [4]int) [][]string

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

func DiffCells(published, direct string) string

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

func Fixture2674Now() time.Time

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

func FleetFixtureOf(n int) [][]string

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 FriendCardsKeyAt(e uint64, friend, where string) string

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 LiveSnapshot2674

func LiveSnapshot2674() string

LiveSnapshot2674 is the raw snapshot file.

func MaskXY

func MaskXY(table string) string

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

func NoMirrorKey(bench string) string

NoMirrorKey is ci:nomirror:<bench>, written only by the ci_run.lua functions (internal/nsprint/ci names the same key).

func PlayBehind

func PlayBehind(result string) string

PlayBehind is the role a play receipt's result names after failed:.

func PoolViewKeyAt

func PoolViewKeyAt(e uint64) string

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

func PrepareCheck(ctx context.Context, client *redis.Client) (seeded bool, err error)

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

func ReleaseLock(ctx context.Context, client redis.UniversalClient, key, token string) error

ReleaseLock deletes key only while it still holds token.

func SprintFixture

func SprintFixture() [][]string

SprintFixture is the keyspace as Redis commands.

func SprintFixtureNow

func SprintFixtureNow() time.Time

SprintFixtureNow is the fixture's instant.

func StreamsDefinition

func StreamsDefinition() ntable.Table

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.

func StreamsShape

func StreamsShape(streams []string, epoch uint64) ntable.Table

StreamsShape is the streams table for the streams of ws:order under epoch: one row per stream, its label the stream's name, every count cell bound to ws.KeyAt(epoch, stream, state), its sentinel excluded.

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

func (p *ClearPlan) Checkpoint() string

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.

func (*ClearPlan) Count

func (p *ClearPlan) Count() int

Count is the number of landed members the clear moves.

type Consumer

type Consumer struct{ Kind, Name string }

Consumer is one consumer of copies: <Kind>:<Name>, bench or friend.

func (Consumer) ID

func (c Consumer) ID() string

ID is the consumer's key prefix and row name, <kind>:<name>.

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

type FixtureStream struct {
	Name                                             string
	Waiting, Ready, Working, Review, Merging, Landed int64
}

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 Proc

type Proc struct {
	Name string
	Up   bool
	Age  int64
	Why  string
}

Proc is one process line: reconciler, harvest worker or consumer.

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).

func (Row) Width

func (r Row) Width() int64

Width includes stale leases until the reconciler releases them; it is derived, never read from a sidecar key (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 Parse

func Parse(raw []any) (*Snapshot, error)

Parse decodes the flat tagged list returned by ns_snapshot.

func Read

func Read(ctx context.Context, client *redis.Client) (*Snapshot, error)

Read takes one consistent server snapshot. Callers must load the nova_sprint function library during deployment; rendering is read-only.

func ReadNamed

func ReadNamed(ctx context.Context, client *redis.Client, sprint string) (*Snapshot, error)

ReadNamed includes a named control sprint, which is hidden from the live table by default. It still makes exactly one FCALL_RO.

func (*Snapshot) Render

func (s *Snapshot) Render() string

Render prints the table. It is deterministic: registries are sorted, so the same snapshot always prints byte for byte the same table.

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.

func (*SprintSnapshot) Render

func (s *SprintSnapshot) Render(now time.Time) string

Render prints the whole table at now.

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).

func (StreamRow) AnyUnread

func (r StreamRow) AnyUnread() bool

AnyUnread says a cell of the row did not come back.

func (StreamRow) Total

func (r StreamRow) Total() int64

Total is every task in the stream's six sets.

Jump to

Keyboard shortcuts

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