Files
mesh-delivery/sdk/buildstep/pause.go
T

108 lines
3.3 KiB
Go

package buildstep
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"strings"
"time"
)
// The states `pauses` of the build seats, whose three seats hold the same layouts (the part `build-step`): a node's
// pause under `paused.<node>`, its capacity under `capacity.<node>`.
// PausesState is the name of the state.
const PausesState = "pauses"
// PauseKey is the key of a node's pause.
func PauseKey(node string) (string, error) {
if err := checkNode(node); err != nil {
return "", err
}
return "paused." + node, nil
}
// CapacityKey is the key of a node's capacity.
func CapacityKey(node string) (string, error) {
if err := checkNode(node); err != nil {
return "", err
}
return "capacity." + node, nil
}
// Pause is whether a node takes no new ask, and who said so.
type Pause struct {
V int `json:"v"`
Paused bool `json:"paused"`
By string `json:"by,omitempty"`
At time.Time `json:"at,omitzero"`
}
// EncodePause is p as a pauses value.
func EncodePause(p Pause) ([]byte, error) {
p.V = Version
p.At = p.At.UTC()
return json.Marshal(p)
}
// DecodePause reads a pause, refusing another version.
func DecodePause(data []byte) (Pause, error) {
var p Pause
if err := decodeVersioned(data, &p, func() int { return p.V }); err != nil {
return Pause{}, err
}
return p, nil
}
// Capacity is how many steps a node runs at once, and why.
type Capacity struct {
V int `json:"v"`
Effective int `json:"effective"`
Configured int `json:"configured"`
ConfiguredFrom string `json:"configured-from,omitempty"`
QuotaCores float64 `json:"quota-cores,omitempty"`
QuotaFrom string `json:"quota-from"`
CoresPerStep float64 `json:"cores-per-step"`
ByCPU int `json:"by-cpu,omitempty"`
BuildHours string `json:"build-hours,omitempty"`
OutsideHours bool `json:"outside-hours,omitempty"`
BuildHoursFault string `json:"build-hours-fault,omitempty"`
Ineligible string `json:"ineligible,omitempty"`
Why string `json:"why"`
At time.Time `json:"at,omitzero"`
}
// EncodeCapacity is c as a pauses value.
func EncodeCapacity(c Capacity) ([]byte, error) {
c.V = Version
c.At = c.At.UTC()
return json.Marshal(c)
}
// DecodeCapacity reads a capacity, refusing another version.
func DecodeCapacity(data []byte) (Capacity, error) {
var c Capacity
if err := decodeVersioned(data, &c, func() int { return c.V }); err != nil {
return Capacity{}, err
}
return c, nil
}
func decodeVersioned(data []byte, into any, version func() int) error {
if err := json.Unmarshal(data, into); err != nil {
return fmt.Errorf("buildstep: value does not fit its shape: %w", err)
}
if v := version(); v != Version {
return fmt.Errorf("%w: a value of version %d, this reader reads %d", ErrUnknownVersion, v, Version)
}
return nil
}
// ComposerKey is the key a composer build is kept under: the fetched commit, the directory, the package and the
// toolchain it ran with.
func ComposerKey(repository, commit, dir, pkg string, toolchain ToolchainUsed) string {
sum := sha256.Sum256([]byte(strings.Join([]string{repository, commit, dir, pkg, toolchain.Version, toolchain.Recipe}, "\n")))
return "composer-" + hex.EncodeToString(sum[:8])
}