An http probe of /v2/ said only that a port answered; design 51 asks the health check to call versions per seat and probe the read side each minute, naming the program when it is down, from outside its process. registry_health asks versions of each seat through the program's port, writes the read-side finding while it fails and clears it after. Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
35 lines
1.4 KiB
Go
35 lines
1.4 KiB
Go
package holder
|
|
|
|
import "fmt"
|
|
|
|
// FindingReadSide is the finding of a store whose read side does not answer through the program.
|
|
const FindingReadSide = "read-side-down"
|
|
|
|
// ProbeName is the name the health check lists on each seat: any name answers, an empty list included.
|
|
const ProbeName = Self + "/program"
|
|
|
|
// Health is distribution's health check (design 51 *While the program is down*; ADR 0240), run by the runtime each
|
|
// minute outside the program's process: it asks `versions` of each seat it holds through the store's read side, the
|
|
// program's port (front), and answers what failed, naming the program. The finding is written while it fails and
|
|
// cleared once it answers.
|
|
func Health(front Catalog, finding func(kind, subject, words string, raised bool)) (map[string]any, error) {
|
|
answered := map[string]int{}
|
|
for _, seat := range Seats {
|
|
got, err := front.Versions(ProbeName)
|
|
if err != nil {
|
|
words := fmt.Sprintf("the store's read side does not answer %s's versions through distribution's program (port 5000): %v; is the program distribution running?", seat, err)
|
|
if finding != nil {
|
|
finding(FindingReadSide, seat, words, true)
|
|
}
|
|
return nil, fmt.Errorf("%s", words)
|
|
}
|
|
answered[seat] = len(got)
|
|
}
|
|
if finding != nil {
|
|
for _, seat := range Seats {
|
|
finding(FindingReadSide, seat, "", false)
|
|
}
|
|
}
|
|
return map[string]any{"healthy": true, "versions": answered}, nil
|
|
}
|