Files
mesh-controller/internal/inventory/busstep.go
T

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