Hear what providers retire, and let a person approve, reject and delete (hq ADR 0230)
A provider now waits for a person before retiring more than three consumers or half of what it holds, and deletes only when asked. The controller is that person's way in: it keeps waiting and rejected sets as conditions, answers them with retire approve|reject, lists and deletes retired consumers through the provider's own tools on its machine, records each act in the hand-act log, and probes for anything retired longer than thirty days (D11).
This commit is contained in:
@@ -164,13 +164,19 @@ func consumePattern(pattern string) error {
|
||||
// The events a provider says about its consumers (novox/hq ADR 0224): a consumer it has failed
|
||||
// without one success for minutes, and that consumer succeeding again or being withdrawn. The
|
||||
// controller follows them from every module and `status` names a consumer failing until it recovers.
|
||||
//
|
||||
// **And what becomes of a consumer the mesh stopped asking for** (novox/hq ADR 0230): retired — its
|
||||
// access disabled and its data kept — after the same answer in five passes, waiting for a person when
|
||||
// more would go than the bound allows, re-enabled when asked for again, and deleted only by a person's
|
||||
// `cleanup delete`. One event, its `change` saying which.
|
||||
const (
|
||||
ProvisionerFailing = "provisioner.failing"
|
||||
ProvisionerRecovered = "provisioner.recovered"
|
||||
ProvisionerFailing = "provisioner.failing"
|
||||
ProvisionerRecovered = "provisioner.recovered"
|
||||
ProvisionerRetirement = "provisioner.retirement"
|
||||
)
|
||||
|
||||
// ProvisionerEvents are both, in the order they are said.
|
||||
var ProvisionerEvents = []string{ProvisionerFailing, ProvisionerRecovered}
|
||||
// ProvisionerEvents are all three, in the order they are said.
|
||||
var ProvisionerEvents = []string{ProvisionerFailing, ProvisionerRecovered, ProvisionerRetirement}
|
||||
|
||||
// EmitsAll is every event a module may publish: what it declares and, for a module that receives
|
||||
// contributions — a provider, running a provisioner over them — the provider's standing events.
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package catalogue
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Every provider may say what becomes of a consumer the mesh stopped asking for (novox/hq ADR 0230),
|
||||
// whatever its manifest lists — as it may say a consumer it keeps failing (ADR 0224) — and a module
|
||||
// that receives nothing may not.
|
||||
func TestEveryProviderMaySayWhatItRetires(t *testing.T) {
|
||||
provider := Manifest{Module: "pg", Receives: map[string]string{"postgres-database": "/x/mesh.json"},
|
||||
Emits: []string{"database.provisioned"}}
|
||||
for _, e := range []string{ProvisionerFailing, ProvisionerRecovered, ProvisionerRetirement, "database.provisioned"} {
|
||||
if !slices.Contains(provider.EmitsAll(), e) {
|
||||
t.Errorf("a provider may not emit %s: %v", e, provider.EmitsAll())
|
||||
}
|
||||
}
|
||||
if slices.Contains(Manifest{Module: "app", Emits: []string{"x"}}.EmitsAll(), ProvisionerRetirement) {
|
||||
t.Error("a module that provides nothing may say what it retires")
|
||||
}
|
||||
}
|
||||
@@ -267,6 +267,33 @@ var ControllerVerbs = []Verb{
|
||||
"probes": "\"true\": the registry — what each probe asserts, and the condition it raises",
|
||||
"signals": "\"true\": the signals table, each row with the age of its newest signal",
|
||||
}, nil, "run", "probes", "signals")},
|
||||
// A consumer the mesh stopped asking for: retired, waiting for a person, deleted only by one
|
||||
// (novox/hq ADR 0230).
|
||||
{Name: "retire", Description: "A consumer the mesh stops asking for is retired by its provider — access " +
|
||||
"disabled, data kept — after the same answer in five passes; more than three at once, or more than half " +
|
||||
"of those held, waits for a person. With no answer, every provider that waits and what it would retire. " +
|
||||
"With answer approve or reject, a node and a module: retire exactly what that provider waits with, or " +
|
||||
"keep it active — a hand act, which says why (novox/hq ADR 0230).",
|
||||
Input: schema(map[string]string{
|
||||
"answer": "approve or reject: answer what the provider waits with (needs node, module and why)",
|
||||
"node": "with answer: the machine the provider runs on",
|
||||
"module": "with answer: the provider module",
|
||||
"why": "with answer: why — required, and recorded in the hand-act log",
|
||||
"cause": "with answer: the cause in a word (retire-waiting when absent)",
|
||||
}, nil)},
|
||||
{Name: "cleanup", Description: "Every consumer a provider holds retired — its age, its size where the " +
|
||||
"backend knows, and why it was retired. With consumer (and node, module): the provider deletes that one " +
|
||||
"retired consumer — never an active one. With older-than: every retired consumer older than that many " +
|
||||
"days, listed; deleted only with confirm. Deleting is a hand act, which says why (novox/hq ADR 0230).",
|
||||
Input: schema(map[string]string{
|
||||
"node": "with consumer: the machine the provider runs on",
|
||||
"module": "with consumer: the provider module",
|
||||
"consumer": "delete this retired consumer (needs node, module and why)",
|
||||
"older-than": "delete every consumer retired more than this many days (needs why; lists only without confirm)",
|
||||
"confirm": "\"true\": with older-than, delete what is listed",
|
||||
"why": "with consumer or older-than: why — required, and recorded in the hand-act log",
|
||||
"cause": "with consumer or older-than: the cause in a word (cleanup-waiting when absent)",
|
||||
}, nil, "confirm")},
|
||||
{Name: "build", Description: "Have the build machine build a repository. Answers at once with the build's id: " +
|
||||
"`builds` with that id follows it line by line, and the module is registered when the outcome comes.",
|
||||
Input: schema(map[string]string{
|
||||
|
||||
Reference in New Issue
Block a user