A build that reported applied was sent everywhere; one that then did nothing, served no tools or broke its machine's word reached every machine. Now the first machine is judged by the component's health (the core's definitions, as doctor probes H-*, or a module's own) three times over two minutes within ten; a failing gate puts the previous build back there once, marks the build, and says it as a condition and an event. Upgrades roll out by default; the bus is a planned step; a module deleted at its source is not built (the public-acme plan failure).
73 lines
2.3 KiB
Go
73 lines
2.3 KiB
Go
package inventory
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
)
|
|
|
|
// BusStep is one planned bus upgrade (novox/hq to-be 45 §8, ADR 0235).
|
|
type BusStep struct {
|
|
ID int64
|
|
Module string
|
|
Machines []string
|
|
From, To string
|
|
Snapshot string
|
|
Reversible bool
|
|
By, Why string
|
|
Started time.Time
|
|
Ended *time.Time
|
|
Outcome string
|
|
Found string
|
|
}
|
|
|
|
// StartBusStep records a bus upgrade starting. Refused while another runs.
|
|
func (i *Inventory) StartBusStep(ctx context.Context, s BusStep) (BusStep, error) {
|
|
if _, err := i.actingEpoch(ctx); err != nil {
|
|
return s, err
|
|
}
|
|
if open, found, err := i.LatestBusStep(ctx); err != nil {
|
|
return s, err
|
|
} else if found && open.Ended == nil {
|
|
return s, ErrBusStepRunning
|
|
}
|
|
if s.Machines == nil {
|
|
s.Machines = []string{}
|
|
}
|
|
err := i.store.Pool().QueryRow(ctx,
|
|
`insert into bus_step (module, machines, from_build, to_build, snapshot, reversible, by_whom, why)
|
|
values ($1, $2, $3, $4, $5, $6, $7, $8) returning id, started`,
|
|
s.Module, s.Machines, s.From, s.To, s.Snapshot, s.Reversible, s.By, s.Why).Scan(&s.ID, &s.Started)
|
|
return s, err
|
|
}
|
|
|
|
// ErrBusStepRunning is a bus upgrade asked while one runs.
|
|
var ErrBusStepRunning = errors.New("a bus upgrade is already running")
|
|
|
|
// EndBusStep records how a bus upgrade ended: done or failed, with what was found.
|
|
func (i *Inventory) EndBusStep(ctx context.Context, id int64, outcome, found string) error {
|
|
if _, err := i.actingEpoch(ctx); err != nil {
|
|
return err
|
|
}
|
|
_, err := i.store.Pool().Exec(ctx,
|
|
`update bus_step set ended = now(), outcome = $2, found = $3 where id = $1 and ended is null`, id, outcome, found)
|
|
return err
|
|
}
|
|
|
|
// LatestBusStep is the newest bus upgrade, and whether there is any.
|
|
func (i *Inventory) LatestBusStep(ctx context.Context) (BusStep, bool, error) {
|
|
var s BusStep
|
|
err := i.store.Pool().QueryRow(ctx,
|
|
`select id, module, machines, from_build, to_build, snapshot, reversible, by_whom, why, started, ended,
|
|
outcome, found
|
|
from bus_step order by id desc limit 1`).
|
|
Scan(&s.ID, &s.Module, &s.Machines, &s.From, &s.To, &s.Snapshot, &s.Reversible, &s.By, &s.Why, &s.Started,
|
|
&s.Ended, &s.Outcome, &s.Found)
|
|
if errors.Is(err, pgx.ErrNoRows) {
|
|
return s, false, nil
|
|
}
|
|
return s, err == nil, err
|
|
}
|