§717 (2): the assigner's asks and wants are views of the seat mesh-wants
The seat mesh-wants' definition gains the state asks (template state, history 5, view), its key forms the seven kinds' keys as the assigner's asks package writes them (hold, restore, backup, record, outside, revert, assignments) and its value the ask as the assigner composes it; its wants gains view. The assigner's first-view tool asks replaces assigner_read_asks, its callers the teller and the status view; the status view joins the callers of wants and assignments. The teller follows the asks by seat:mesh-wants.views.asks and invokes nothing of the assigner's. The status view's part waits on a question (its tools ask assigner_read_wants). Builds: design 47 G §717, A-299 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -36,7 +36,7 @@ const (
|
||||
func askAgainByHand(st store, ask func(string, any) (json.RawMessage, error), key, why, by string, now time.Time) (any, error) {
|
||||
switch {
|
||||
case key == "":
|
||||
return nil, errors.New("name the ask's key, as assigner_read_asks lists it")
|
||||
return nil, errors.New("name the ask's key, as the tool asks lists it")
|
||||
case why == "":
|
||||
return nil, errors.New("a hand ask again says why")
|
||||
case by == "" || by == stdio.Unproven:
|
||||
@@ -47,7 +47,7 @@ func askAgainByHand(st store, ask func(string, any) (json.RawMessage, error), ke
|
||||
return nil, err
|
||||
}
|
||||
if !found {
|
||||
return nil, fmt.Errorf("the assigner holds no ask under %s: assigner_read_asks lists them", key)
|
||||
return nil, fmt.Errorf("the assigner holds no ask under %s: the tool asks lists them", key)
|
||||
}
|
||||
_, routerAsk, err := assign.DecodeAsk(key, current)
|
||||
if err != nil {
|
||||
@@ -90,7 +90,7 @@ func askAgainTools(st store, ask func(string, any) (json.RawMessage, error), now
|
||||
"under key is written again under a new asking, which the teller asks on the operator channel, as when the channel says it " +
|
||||
"ended without an answer. Refused for an asking the operator answered, a proposal's authorising ask (the seat's verb again " +
|
||||
"asks it) and a record ask a put asked. Recorded as a hand act.",
|
||||
Input: schema(map[string]string{"key": "the ask's key, as assigner_read_asks lists it", "why": "why it is asked again"},
|
||||
Input: schema(map[string]string{"key": "the ask's key, as the tool asks lists it", "why": "why it is asked again"},
|
||||
[]string{"key", "why"}),
|
||||
Run: func(a map[string]any) (any, error) {
|
||||
key, _ := a["key"].(string)
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-assigner/asks"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/seats/meshwants"
|
||||
)
|
||||
|
||||
// Design 47 G §717: the assigner's asks are the seat mesh-wants' state asks, so every key its asks package writes is one of
|
||||
// that state's key forms, read back to the same parts, and each value is the seat's Ask.
|
||||
func TestTheAssignersAsksAreTheSeatMeshWantsAsks(t *testing.T) {
|
||||
const hex = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
const fp, digest = "src2:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
must := func(k string, err error) string {
|
||||
t.Helper()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return k
|
||||
}
|
||||
three := func(parse func(string) (string, string, string, bool)) func(string) []string {
|
||||
return func(k string) []string {
|
||||
if a, b, c, ok := parse(k); ok {
|
||||
return []string{a, b, c}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
for _, row := range []struct {
|
||||
key string
|
||||
parse func(string) []string
|
||||
want []string
|
||||
}{
|
||||
{must(asks.HoldAskKey("web", fp)), func(k string) []string {
|
||||
if a, b, ok := meshwants.ParseAsksByHoldModuleFingerprintKey(k); ok {
|
||||
return []string{a, b}
|
||||
}
|
||||
return nil
|
||||
}, []string{"web", hex}},
|
||||
{must(asks.RestoreAskKey("ace", "web", fp)), three(meshwants.ParseAsksByRestoreNodeModuleFingerprintKey), []string{"ace", "web", hex}},
|
||||
{must(asks.BackupAskKey("ace", "web", fp)), three(meshwants.ParseAsksByBackupNodeModuleFingerprintKey), []string{"ace", "web", hex}},
|
||||
{must(asks.OutsideAskKey("ace", "web", fp)), three(meshwants.ParseAsksByOutsideNodeModuleFingerprintKey), []string{"ace", "web", hex}},
|
||||
{must(asks.RevertAskKey("ace", "web", fp)), three(meshwants.ParseAsksByRevertNodeModuleFingerprintKey), []string{"ace", "web", hex}},
|
||||
{must(asks.RecordAskKey("ace", "web", digest)), three(meshwants.ParseAsksByRecordNodeModuleDigestKey), []string{"ace", "web", "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}},
|
||||
{must(asks.AssignmentsAskKey("p-20261028t183000-1a2b3c")), func(k string) []string {
|
||||
if a, ok := meshwants.ParseAsksByAssignmentsProposalKey(k); ok {
|
||||
return []string{a}
|
||||
}
|
||||
return nil
|
||||
}, []string{"p-20261028t183000-1a2b3c"}},
|
||||
} {
|
||||
got := row.parse(row.key)
|
||||
if len(got) != len(row.want) {
|
||||
t.Errorf("%s is no key form of mesh-wants' asks: read as %v", row.key, got)
|
||||
continue
|
||||
}
|
||||
for i := range got {
|
||||
if got[i] != row.want[i] {
|
||||
t.Errorf("%s reads as %v, want %v", row.key, got, row.want)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
key := must(asks.HoldAskKey("web", fp))
|
||||
raw, err := asks.EncodeAsk(key, asks.Ask{Ask: json.RawMessage(`{"id":"x"}`), Asking: 2})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if v, err := meshwants.DecodeAsksByHoldModuleFingerprintValue(raw); err != nil || v.Asking != 2 {
|
||||
t.Errorf("the ask %s is not the seat's Ask: %+v, %v", raw, v, err)
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,8 @@ var firstViewTools = []viewedTool{
|
||||
{"assignments", mma.StateAssignments, "where each module is placed: the seat mesh-module-assigner's assignments, by module."},
|
||||
{"seat-holders", mma.StateSeatHolders, "who holds which seat on which node."},
|
||||
{"wants", "wants", "what each node should run: want.<node>.<module>, its fingerprint and the rule that gave it."},
|
||||
// The seat mesh-wants' asks (design 47 G §717): the asks the assigner put to a person about what a node runs.
|
||||
{"asks", "asks", "the asks the assigner put to a person about what a node runs, and their answers."},
|
||||
}
|
||||
|
||||
// readTools are the assigner's ordinary read tools, one per state its readers read (design 25 § 12.2).
|
||||
@@ -48,7 +50,6 @@ var readTools = []viewedTool{
|
||||
{"assigner_read_seat_holders", mma.StateSeatHolders, "who holds which seat on which node."},
|
||||
{"assigner_read_wants", "wants", "what each node should run: want.<node>.<module>."},
|
||||
{"assigner_read_findings", assign.FindingsState, "the assigner's findings, which the condition keeper raises and clears."},
|
||||
{"assigner_read_asks", "asks", "the asks the assigner put to a person, and their answers."},
|
||||
{"assigner_read_differences", "differences", "every difference between a want and what a node runs."},
|
||||
{"assigner_read_copies", copiesState, "the copies the assigner made of a retired state: when the copy into assignments ended and how many keys it copied."},
|
||||
}
|
||||
|
||||
@@ -100,11 +100,11 @@ func TestManifest(t *testing.T) {
|
||||
t.Errorf("objects = %+v, want assignment-revisions, 512 MiB, form 1", m.Objects)
|
||||
}
|
||||
// Whether the seats' definitions let it hold them is the manifest validator's (the judge, at the seat list).
|
||||
// ADR 0621 §1: the first-view tools assignments, seat-holders and wants and design 25 § 12.2's six read tools, of the
|
||||
// ADR 0621 §1: the first-view tools assignments, seat-holders, wants and asks (§717) and design 25 § 12.2's six read tools, of the
|
||||
// program's bundle, which runs in a runtime of its own on the assigner's account; ADR 0618 §3: and assigner_engine_reads,
|
||||
// which lists and asks again what each node's engine reads.
|
||||
if !slices.Equal(m.Tools, []string{"assigner_put", "assigner_release", "assigner_puts", "assigner_waits", "assigner_inputs", "assignments", "seat-holders", "wants",
|
||||
"assigner_read_assignments", "assigner_read_seat_holders", "assigner_read_wants", "assigner_read_findings", "assigner_read_asks", "assigner_read_differences", "assigner_read_copies",
|
||||
if !slices.Equal(m.Tools, []string{"assigner_put", "assigner_release", "assigner_puts", "assigner_waits", "assigner_inputs", "assignments", "seat-holders", "wants", "asks",
|
||||
"assigner_read_assignments", "assigner_read_seat_holders", "assigner_read_wants", "assigner_read_findings", "assigner_read_differences", "assigner_read_copies",
|
||||
"assigner_first_views", "assigner_first_view_again", "assigner_engine_reads", "assigner_seat_list", "assigner_seat_list_again", "assigner_ask_again", "assigner_written", "assigner_pins", "assigner_unpin", "assigner_delivered_again"}) {
|
||||
t.Errorf("the assigner serves tools %v, want its three put tools, three first views, six read tools, assigner_engine_reads, the seat list's two (ADR 0636 §7) and assigner_ask_again (ADR 0668 §5)", m.Tools)
|
||||
}
|
||||
@@ -112,7 +112,10 @@ func TestManifest(t *testing.T) {
|
||||
t.Errorf("runs-as = %q: the bundle runs on the assigner's own account (ADR 0621 §1)", m.RunsAs)
|
||||
}
|
||||
// ADR 0621 §2: each first-view tool answers exactly its readers, never the assigner.
|
||||
callers := map[string]string{"assignments": "mesh-grants,node-tools,mesh-delivery-indexer,mesh-delivery-builder,mesh-delivery-checker", "seat-holders": "node-tools,mesh-delivery-builder,mesh-delivery-view", "wants": "mesh-grants"}
|
||||
// Design 47 G §717: the teller and the status view take their first views of the seat mesh-wants' asks and wants, and of
|
||||
// the assignments, from the tools named for the states.
|
||||
callers := map[string]string{"assignments": "mesh-grants,node-tools,mesh-delivery-indexer,mesh-delivery-builder,mesh-delivery-checker,mesh-delivery-view",
|
||||
"seat-holders": "node-tools,mesh-delivery-builder,mesh-delivery-view", "wants": "mesh-grants,mesh-delivery-view", "asks": "mesh-delivery-teller,mesh-delivery-view"}
|
||||
env := m.Build.Artifacts[0].Env
|
||||
for tool, list := range callers {
|
||||
if env[views.CallersEnv(tool)] != list || views.ParseCallers(env[views.CallersEnv(tool)]).Allows("n1."+m.Module) {
|
||||
|
||||
@@ -115,11 +115,11 @@
|
||||
"assignments",
|
||||
"seat-holders",
|
||||
"wants",
|
||||
"asks",
|
||||
"assigner_read_assignments",
|
||||
"assigner_read_seat_holders",
|
||||
"assigner_read_wants",
|
||||
"assigner_read_findings",
|
||||
"assigner_read_asks",
|
||||
"assigner_read_differences",
|
||||
"assigner_read_copies",
|
||||
"assigner_first_views",
|
||||
@@ -247,9 +247,10 @@
|
||||
"mesh-delivery-assigner"
|
||||
],
|
||||
"env": {
|
||||
"MESH_VIEW_CALLERS_ASSIGNMENTS": "mesh-grants,node-tools,mesh-delivery-indexer,mesh-delivery-builder,mesh-delivery-checker",
|
||||
"MESH_VIEW_CALLERS_ASKS": "mesh-delivery-teller,mesh-delivery-view",
|
||||
"MESH_VIEW_CALLERS_ASSIGNMENTS": "mesh-grants,node-tools,mesh-delivery-indexer,mesh-delivery-builder,mesh-delivery-checker,mesh-delivery-view",
|
||||
"MESH_VIEW_CALLERS_SEAT_HOLDERS": "node-tools,mesh-delivery-builder,mesh-delivery-view",
|
||||
"MESH_VIEW_CALLERS_WANTS": "mesh-grants"
|
||||
"MESH_VIEW_CALLERS_WANTS": "mesh-grants,mesh-delivery-view"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -121,6 +121,7 @@ const AcceptSubjectStep = "mesh.seat.mesh-wants.accept.step"
|
||||
|
||||
const (
|
||||
StateWants = "wants"
|
||||
StateAsks = "asks"
|
||||
StateDifferences = "differences"
|
||||
StateCompositions = "compositions"
|
||||
StateAssignmentRevisions = "assignment-revisions"
|
||||
@@ -244,6 +245,318 @@ func DecodeWantsByHeldModuleFingerprintValue(raw []byte) (WantsByHeldModuleFinge
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// AsksByHoldModuleFingerprintKey is the key of one value of the state asks under the form "hold.<module>.<fingerprint>".
|
||||
func AsksByHoldModuleFingerprintKey(module, fingerprint string) string {
|
||||
return "hold." + module + "." + fingerprint
|
||||
}
|
||||
|
||||
// ParseAsksByHoldModuleFingerprintKey reads the parts of a key of the form "hold.<module>.<fingerprint>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseAsksByHoldModuleFingerprintKey(key string) (string, string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "hold.") {
|
||||
return "", "", false
|
||||
}
|
||||
rest = rest[5:]
|
||||
v1, after1, found1 := strings.Cut(rest, ".")
|
||||
if !found1 || v1 == "" {
|
||||
return "", "", false
|
||||
}
|
||||
rest = after1
|
||||
if rest == "" {
|
||||
return "", "", false
|
||||
}
|
||||
v3 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", false
|
||||
}
|
||||
return v1, v3, true
|
||||
}
|
||||
|
||||
// DecodeAsksByHoldModuleFingerprintValue reads one value of the state asks under the form "hold.<module>.<fingerprint>", refusing a field AsksByHoldModuleFingerprintValue does not know and any text after the value.
|
||||
func DecodeAsksByHoldModuleFingerprintValue(raw []byte) (AsksByHoldModuleFingerprintValue, error) {
|
||||
var v AsksByHoldModuleFingerprintValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// AsksByRestoreNodeModuleFingerprintKey is the key of one value of the state asks under the form "restore.<node>.<module>.<fingerprint>".
|
||||
func AsksByRestoreNodeModuleFingerprintKey(node, module, fingerprint string) string {
|
||||
return "restore." + node + "." + module + "." + fingerprint
|
||||
}
|
||||
|
||||
// ParseAsksByRestoreNodeModuleFingerprintKey reads the parts of a key of the form "restore.<node>.<module>.<fingerprint>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseAsksByRestoreNodeModuleFingerprintKey(key string) (string, string, string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "restore.") {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = rest[8:]
|
||||
v1, after1, found1 := strings.Cut(rest, ".")
|
||||
if !found1 || v1 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after1
|
||||
v3, after3, found3 := strings.Cut(rest, ".")
|
||||
if !found3 || v3 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after3
|
||||
if rest == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
v5 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
return v1, v3, v5, true
|
||||
}
|
||||
|
||||
// DecodeAsksByRestoreNodeModuleFingerprintValue reads one value of the state asks under the form "restore.<node>.<module>.<fingerprint>", refusing a field AsksByRestoreNodeModuleFingerprintValue does not know and any text after the value.
|
||||
func DecodeAsksByRestoreNodeModuleFingerprintValue(raw []byte) (AsksByRestoreNodeModuleFingerprintValue, error) {
|
||||
var v AsksByRestoreNodeModuleFingerprintValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// AsksByBackupNodeModuleFingerprintKey is the key of one value of the state asks under the form "backup.<node>.<module>.<fingerprint>".
|
||||
func AsksByBackupNodeModuleFingerprintKey(node, module, fingerprint string) string {
|
||||
return "backup." + node + "." + module + "." + fingerprint
|
||||
}
|
||||
|
||||
// ParseAsksByBackupNodeModuleFingerprintKey reads the parts of a key of the form "backup.<node>.<module>.<fingerprint>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseAsksByBackupNodeModuleFingerprintKey(key string) (string, string, string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "backup.") {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = rest[7:]
|
||||
v1, after1, found1 := strings.Cut(rest, ".")
|
||||
if !found1 || v1 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after1
|
||||
v3, after3, found3 := strings.Cut(rest, ".")
|
||||
if !found3 || v3 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after3
|
||||
if rest == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
v5 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
return v1, v3, v5, true
|
||||
}
|
||||
|
||||
// DecodeAsksByBackupNodeModuleFingerprintValue reads one value of the state asks under the form "backup.<node>.<module>.<fingerprint>", refusing a field AsksByBackupNodeModuleFingerprintValue does not know and any text after the value.
|
||||
func DecodeAsksByBackupNodeModuleFingerprintValue(raw []byte) (AsksByBackupNodeModuleFingerprintValue, error) {
|
||||
var v AsksByBackupNodeModuleFingerprintValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// AsksByRecordNodeModuleDigestKey is the key of one value of the state asks under the form "record.<node>.<module>.<digest>".
|
||||
func AsksByRecordNodeModuleDigestKey(node, module, digest string) string {
|
||||
return "record." + node + "." + module + "." + digest
|
||||
}
|
||||
|
||||
// ParseAsksByRecordNodeModuleDigestKey reads the parts of a key of the form "record.<node>.<module>.<digest>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseAsksByRecordNodeModuleDigestKey(key string) (string, string, string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "record.") {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = rest[7:]
|
||||
v1, after1, found1 := strings.Cut(rest, ".")
|
||||
if !found1 || v1 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after1
|
||||
v3, after3, found3 := strings.Cut(rest, ".")
|
||||
if !found3 || v3 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after3
|
||||
if rest == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
v5 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
return v1, v3, v5, true
|
||||
}
|
||||
|
||||
// DecodeAsksByRecordNodeModuleDigestValue reads one value of the state asks under the form "record.<node>.<module>.<digest>", refusing a field AsksByRecordNodeModuleDigestValue does not know and any text after the value.
|
||||
func DecodeAsksByRecordNodeModuleDigestValue(raw []byte) (AsksByRecordNodeModuleDigestValue, error) {
|
||||
var v AsksByRecordNodeModuleDigestValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// AsksByOutsideNodeModuleFingerprintKey is the key of one value of the state asks under the form "outside.<node>.<module>.<fingerprint>".
|
||||
func AsksByOutsideNodeModuleFingerprintKey(node, module, fingerprint string) string {
|
||||
return "outside." + node + "." + module + "." + fingerprint
|
||||
}
|
||||
|
||||
// ParseAsksByOutsideNodeModuleFingerprintKey reads the parts of a key of the form "outside.<node>.<module>.<fingerprint>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseAsksByOutsideNodeModuleFingerprintKey(key string) (string, string, string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "outside.") {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = rest[8:]
|
||||
v1, after1, found1 := strings.Cut(rest, ".")
|
||||
if !found1 || v1 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after1
|
||||
v3, after3, found3 := strings.Cut(rest, ".")
|
||||
if !found3 || v3 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after3
|
||||
if rest == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
v5 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
return v1, v3, v5, true
|
||||
}
|
||||
|
||||
// DecodeAsksByOutsideNodeModuleFingerprintValue reads one value of the state asks under the form "outside.<node>.<module>.<fingerprint>", refusing a field AsksByOutsideNodeModuleFingerprintValue does not know and any text after the value.
|
||||
func DecodeAsksByOutsideNodeModuleFingerprintValue(raw []byte) (AsksByOutsideNodeModuleFingerprintValue, error) {
|
||||
var v AsksByOutsideNodeModuleFingerprintValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// AsksByRevertNodeModuleFingerprintKey is the key of one value of the state asks under the form "revert.<node>.<module>.<fingerprint>".
|
||||
func AsksByRevertNodeModuleFingerprintKey(node, module, fingerprint string) string {
|
||||
return "revert." + node + "." + module + "." + fingerprint
|
||||
}
|
||||
|
||||
// ParseAsksByRevertNodeModuleFingerprintKey reads the parts of a key of the form "revert.<node>.<module>.<fingerprint>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseAsksByRevertNodeModuleFingerprintKey(key string) (string, string, string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "revert.") {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = rest[7:]
|
||||
v1, after1, found1 := strings.Cut(rest, ".")
|
||||
if !found1 || v1 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after1
|
||||
v3, after3, found3 := strings.Cut(rest, ".")
|
||||
if !found3 || v3 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after3
|
||||
if rest == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
v5 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
return v1, v3, v5, true
|
||||
}
|
||||
|
||||
// DecodeAsksByRevertNodeModuleFingerprintValue reads one value of the state asks under the form "revert.<node>.<module>.<fingerprint>", refusing a field AsksByRevertNodeModuleFingerprintValue does not know and any text after the value.
|
||||
func DecodeAsksByRevertNodeModuleFingerprintValue(raw []byte) (AsksByRevertNodeModuleFingerprintValue, error) {
|
||||
var v AsksByRevertNodeModuleFingerprintValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// AsksByAssignmentsProposalKey is the key of one value of the state asks under the form "assignments.<proposal>".
|
||||
func AsksByAssignmentsProposalKey(proposal string) string { return "assignments." + proposal }
|
||||
|
||||
// ParseAsksByAssignmentsProposalKey reads the parts of a key of the form "assignments.<proposal>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseAsksByAssignmentsProposalKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "assignments.") {
|
||||
return "", false
|
||||
}
|
||||
rest = rest[12:]
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v1 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v1, true
|
||||
}
|
||||
|
||||
// DecodeAsksByAssignmentsProposalValue reads one value of the state asks under the form "assignments.<proposal>", refusing a field AsksByAssignmentsProposalValue does not know and any text after the value.
|
||||
func DecodeAsksByAssignmentsProposalValue(raw []byte) (AsksByAssignmentsProposalValue, error) {
|
||||
var v AsksByAssignmentsProposalValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// DifferencesByNodeModuleKey is the key of one value of the state differences under the form "<node>.<module>".
|
||||
func DifferencesByNodeModuleKey(node, module string) string { return node + "." + module }
|
||||
|
||||
@@ -464,6 +777,15 @@ func DecodeInputsByTimeDigestValue(raw []byte) (InputsByTimeDigestValue, error)
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Ask is an ask the assigner puts to a person: the router's ask whole, as the assigner composes it, and how many times it was written at its key.
|
||||
type Ask struct {
|
||||
// the seat operator-channel's ask, whole
|
||||
Ask map[string]any `json:"ask"`
|
||||
// the times the assigner wrote the ask at this key: 0 or 1 for the first, n for the n-th
|
||||
Asking int64 `json:"asking,omitempty"`
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// AssignmentEntry is one module version on a node of an assignment graph revision, stored once by its digest (ADR 0656).
|
||||
type AssignmentEntry struct {
|
||||
// the watched branch its placement names, whose catalog graph the entry comes from (design 47 lines 523-525)
|
||||
@@ -975,6 +1297,27 @@ type WantsByHeldModuleFingerprintValue struct {
|
||||
Words string `json:"words,omitempty"`
|
||||
}
|
||||
|
||||
// AsksByHoldModuleFingerprintValue is one value of the state asks under the key hold.<module>.<fingerprint>.
|
||||
type AsksByHoldModuleFingerprintValue = Ask
|
||||
|
||||
// AsksByRestoreNodeModuleFingerprintValue is one value of the state asks under the key restore.<node>.<module>.<fingerprint>.
|
||||
type AsksByRestoreNodeModuleFingerprintValue = Ask
|
||||
|
||||
// AsksByBackupNodeModuleFingerprintValue is one value of the state asks under the key backup.<node>.<module>.<fingerprint>.
|
||||
type AsksByBackupNodeModuleFingerprintValue = Ask
|
||||
|
||||
// AsksByRecordNodeModuleDigestValue is one value of the state asks under the key record.<node>.<module>.<digest>.
|
||||
type AsksByRecordNodeModuleDigestValue = Ask
|
||||
|
||||
// AsksByOutsideNodeModuleFingerprintValue is one value of the state asks under the key outside.<node>.<module>.<fingerprint>.
|
||||
type AsksByOutsideNodeModuleFingerprintValue = Ask
|
||||
|
||||
// AsksByRevertNodeModuleFingerprintValue is one value of the state asks under the key revert.<node>.<module>.<fingerprint>.
|
||||
type AsksByRevertNodeModuleFingerprintValue = Ask
|
||||
|
||||
// AsksByAssignmentsProposalValue is one value of the state asks under the key assignments.<proposal>.
|
||||
type AsksByAssignmentsProposalValue = Ask
|
||||
|
||||
// DifferencesByNodeModuleValue is one value of the state differences under the key <node>.<module>.
|
||||
type DifferencesByNodeModuleValue struct {
|
||||
Rule int64 `json:"rule,omitempty"`
|
||||
|
||||
@@ -113,6 +113,12 @@ func TestFixtures(t *testing.T) {
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "an ask about a held fingerprint, asked a second time", subject: "", given: "{\"ask\":{\"headline\":\"web 0123456789ab is held\",\"id\":\"hold.web.0123456789ab.2\"},\"asking\":2,\"v\":1}", wire: "{\"ask\":{\"headline\":\"web 0123456789ab is held\",\"id\":\"hold.web.0123456789ab.2\"},\"asking\":2,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v AsksByHoldModuleFingerprintValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "revision asks the trunk's newest", subject: "", given: "{}", wire: "{}",
|
||||
decode: func(b []byte) (any, error) { var v RevisionInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "revision asks a candidate's", subject: "", given: "{\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\"}", wire: "{\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\"}",
|
||||
|
||||
@@ -151,5 +151,17 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "an ask about a held fingerprint, asked a second time",
|
||||
"of": "state:asks/hold.<module>.<fingerprint>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"ask": {
|
||||
"id": "hold.web.0123456789ab.2",
|
||||
"headline": "web 0123456789ab is held"
|
||||
},
|
||||
"asking": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -489,6 +489,7 @@
|
||||
{
|
||||
"name": "wants",
|
||||
"template": "state",
|
||||
"view": true,
|
||||
"key-forms": [
|
||||
{
|
||||
"key": "want.<node>.<module>",
|
||||
@@ -618,6 +619,64 @@
|
||||
"history": 20,
|
||||
"description": "what each node should run, and the fingerprints held back"
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"template": "state",
|
||||
"view": true,
|
||||
"history": 5,
|
||||
"description": "the asks the assigner puts to a person about what a node runs, one key per ask, each the ask as the assigner composes it (design 47 G section 717)",
|
||||
"key-forms": [
|
||||
{
|
||||
"key": "hold.<module>.<fingerprint>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Ask"
|
||||
},
|
||||
"description": "the ask about a module's held fingerprint whose health check failed: release it or keep it held"
|
||||
},
|
||||
{
|
||||
"key": "restore.<node>.<module>.<fingerprint>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Ask"
|
||||
},
|
||||
"description": "the ask about a data module set back on a node: restore and lose newer writes, or leave it stopped (ADR 0429 section 6)"
|
||||
},
|
||||
{
|
||||
"key": "backup.<node>.<module>.<fingerprint>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Ask"
|
||||
},
|
||||
"description": "the ask about a backup that failed before a node applies a fingerprint: back up again, or go on without one (ADR 0539 section 16)"
|
||||
},
|
||||
{
|
||||
"key": "record.<node>.<module>.<digest>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Ask"
|
||||
},
|
||||
"description": "the ask about a move a person must allow for a module of policy record, naming the composition's digest (ADR 0539 section 14)"
|
||||
},
|
||||
{
|
||||
"key": "outside.<node>.<module>.<fingerprint>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Ask"
|
||||
},
|
||||
"description": "the ask about a moved module whose failing health check waited past its bound on an outside cause (design 47 G section 706)"
|
||||
},
|
||||
{
|
||||
"key": "revert.<node>.<module>.<fingerprint>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Ask"
|
||||
},
|
||||
"description": "the ask about a held revert with no restore point, the reverted build's fingerprint (design 47 G section 710)"
|
||||
},
|
||||
{
|
||||
"key": "assignments.<proposal>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Ask"
|
||||
},
|
||||
"description": "the authorising ask about a proposal of assignments (ADR 0567 section 5)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "differences",
|
||||
"template": "state",
|
||||
@@ -1409,6 +1468,26 @@
|
||||
"branch",
|
||||
"revision"
|
||||
]
|
||||
},
|
||||
"Ask": {
|
||||
"type": "object",
|
||||
"description": "an ask the assigner puts to a person: the router's ask whole, as the assigner composes it, and how many times it was written at its key",
|
||||
"properties": {
|
||||
"v": {
|
||||
"type": "integer"
|
||||
},
|
||||
"ask": {
|
||||
"type": "object",
|
||||
"description": "the seat operator-channel's ask, whole"
|
||||
},
|
||||
"asking": {
|
||||
"type": "integer",
|
||||
"description": "the times the assigner wrote the ask at this key: 0 or 1 for the first, n for the n-th"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"ask"
|
||||
]
|
||||
}
|
||||
},
|
||||
"acts": [
|
||||
|
||||
@@ -74,6 +74,7 @@ export declare const stepSubject: "mesh.seat.mesh-wants.accept.step";
|
||||
|
||||
export declare const states: {
|
||||
readonly wants: "wants";
|
||||
readonly asks: "asks";
|
||||
readonly differences: "differences";
|
||||
readonly compositions: "compositions";
|
||||
readonly assignmentRevisions: "assignment-revisions";
|
||||
@@ -98,6 +99,48 @@ export declare function wantsByHeldModuleFingerprintKey(module: string, fingerpr
|
||||
/** The parts of a key of the form "held.<module>.<fingerprint>", or undefined for a key of another form. */
|
||||
export declare function parseWantsByHeldModuleFingerprintKey(_key: string): { module: string; fingerprint: string } | undefined;
|
||||
|
||||
/** The key of one value of the state asks under the form "hold.<module>.<fingerprint>". */
|
||||
export declare function asksByHoldModuleFingerprintKey(module: string, fingerprint: string): string;
|
||||
|
||||
/** The parts of a key of the form "hold.<module>.<fingerprint>", or undefined for a key of another form. */
|
||||
export declare function parseAsksByHoldModuleFingerprintKey(_key: string): { module: string; fingerprint: string } | undefined;
|
||||
|
||||
/** The key of one value of the state asks under the form "restore.<node>.<module>.<fingerprint>". */
|
||||
export declare function asksByRestoreNodeModuleFingerprintKey(node: string, module: string, fingerprint: string): string;
|
||||
|
||||
/** The parts of a key of the form "restore.<node>.<module>.<fingerprint>", or undefined for a key of another form. */
|
||||
export declare function parseAsksByRestoreNodeModuleFingerprintKey(_key: string): { node: string; module: string; fingerprint: string } | undefined;
|
||||
|
||||
/** The key of one value of the state asks under the form "backup.<node>.<module>.<fingerprint>". */
|
||||
export declare function asksByBackupNodeModuleFingerprintKey(node: string, module: string, fingerprint: string): string;
|
||||
|
||||
/** The parts of a key of the form "backup.<node>.<module>.<fingerprint>", or undefined for a key of another form. */
|
||||
export declare function parseAsksByBackupNodeModuleFingerprintKey(_key: string): { node: string; module: string; fingerprint: string } | undefined;
|
||||
|
||||
/** The key of one value of the state asks under the form "record.<node>.<module>.<digest>". */
|
||||
export declare function asksByRecordNodeModuleDigestKey(node: string, module: string, digest: string): string;
|
||||
|
||||
/** The parts of a key of the form "record.<node>.<module>.<digest>", or undefined for a key of another form. */
|
||||
export declare function parseAsksByRecordNodeModuleDigestKey(_key: string): { node: string; module: string; digest: string } | undefined;
|
||||
|
||||
/** The key of one value of the state asks under the form "outside.<node>.<module>.<fingerprint>". */
|
||||
export declare function asksByOutsideNodeModuleFingerprintKey(node: string, module: string, fingerprint: string): string;
|
||||
|
||||
/** The parts of a key of the form "outside.<node>.<module>.<fingerprint>", or undefined for a key of another form. */
|
||||
export declare function parseAsksByOutsideNodeModuleFingerprintKey(_key: string): { node: string; module: string; fingerprint: string } | undefined;
|
||||
|
||||
/** The key of one value of the state asks under the form "revert.<node>.<module>.<fingerprint>". */
|
||||
export declare function asksByRevertNodeModuleFingerprintKey(node: string, module: string, fingerprint: string): string;
|
||||
|
||||
/** The parts of a key of the form "revert.<node>.<module>.<fingerprint>", or undefined for a key of another form. */
|
||||
export declare function parseAsksByRevertNodeModuleFingerprintKey(_key: string): { node: string; module: string; fingerprint: string } | undefined;
|
||||
|
||||
/** The key of one value of the state asks under the form "assignments.<proposal>". */
|
||||
export declare function asksByAssignmentsProposalKey(proposal: string): string;
|
||||
|
||||
/** The parts of a key of the form "assignments.<proposal>", or undefined for a key of another form. */
|
||||
export declare function parseAsksByAssignmentsProposalKey(_key: string): { proposal: string } | undefined;
|
||||
|
||||
/** The key of one value of the state differences under the form "<node>.<module>". */
|
||||
export declare function differencesByNodeModuleKey(node: string, module: string): string;
|
||||
|
||||
@@ -134,6 +177,15 @@ export declare function inputsByTimeDigestKey(time: string, digest: string): str
|
||||
/** The parts of a key of the form "<time>.<digest>", or undefined for a key of another form. */
|
||||
export declare function parseInputsByTimeDigestKey(_key: string): { time: string; digest: string } | undefined;
|
||||
|
||||
/** an ask the assigner puts to a person: the router's ask whole, as the assigner composes it, and how many times it was written at its key */
|
||||
export interface Ask {
|
||||
/** the seat operator-channel's ask, whole */
|
||||
"ask": Record<string, unknown>;
|
||||
/** the times the assigner wrote the ask at this key: 0 or 1 for the first, n for the n-th */
|
||||
"asking"?: number;
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** one module version on a node of an assignment graph revision, stored once by its digest (ADR 0656) */
|
||||
export interface AssignmentEntry {
|
||||
/** the watched branch its placement names, whose catalog graph the entry comes from (design 47 lines 523-525) */
|
||||
@@ -581,6 +633,27 @@ export interface WantsByHeldModuleFingerprintValue {
|
||||
"words"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state asks under the key hold.<module>.<fingerprint>. */
|
||||
export type AsksByHoldModuleFingerprintValue = Ask;
|
||||
|
||||
/** is one value of the state asks under the key restore.<node>.<module>.<fingerprint>. */
|
||||
export type AsksByRestoreNodeModuleFingerprintValue = Ask;
|
||||
|
||||
/** is one value of the state asks under the key backup.<node>.<module>.<fingerprint>. */
|
||||
export type AsksByBackupNodeModuleFingerprintValue = Ask;
|
||||
|
||||
/** is one value of the state asks under the key record.<node>.<module>.<digest>. */
|
||||
export type AsksByRecordNodeModuleDigestValue = Ask;
|
||||
|
||||
/** is one value of the state asks under the key outside.<node>.<module>.<fingerprint>. */
|
||||
export type AsksByOutsideNodeModuleFingerprintValue = Ask;
|
||||
|
||||
/** is one value of the state asks under the key revert.<node>.<module>.<fingerprint>. */
|
||||
export type AsksByRevertNodeModuleFingerprintValue = Ask;
|
||||
|
||||
/** is one value of the state asks under the key assignments.<proposal>. */
|
||||
export type AsksByAssignmentsProposalValue = Ask;
|
||||
|
||||
/** is one value of the state differences under the key <node>.<module>. */
|
||||
export interface DifferencesByNodeModuleValue {
|
||||
"rule"?: number;
|
||||
|
||||
@@ -80,6 +80,7 @@ export const stepSubject = "mesh.seat.mesh-wants.accept.step";
|
||||
|
||||
export const states = {
|
||||
wants: "wants",
|
||||
asks: "asks",
|
||||
differences: "differences",
|
||||
compositions: "compositions",
|
||||
assignmentRevisions: "assignment-revisions",
|
||||
@@ -146,6 +147,169 @@ export function parseWantsByHeldModuleFingerprintKey(_key) {
|
||||
return { module, fingerprint };
|
||||
}
|
||||
|
||||
/** The key of one value of the state asks under the form "hold.<module>.<fingerprint>". */
|
||||
export function asksByHoldModuleFingerprintKey(module, fingerprint) {
|
||||
return "hold." + module + "." + fingerprint;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "hold.<module>.<fingerprint>", or undefined for a key of another form. */
|
||||
export function parseAsksByHoldModuleFingerprintKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("hold.")) return undefined;
|
||||
_rest = _rest.slice(5);
|
||||
const _at1 = _rest.indexOf(".");
|
||||
if (_at1 <= 0) return undefined;
|
||||
const module = _rest.slice(0, _at1);
|
||||
_rest = _rest.slice(_at1 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const fingerprint = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { module, fingerprint };
|
||||
}
|
||||
|
||||
/** The key of one value of the state asks under the form "restore.<node>.<module>.<fingerprint>". */
|
||||
export function asksByRestoreNodeModuleFingerprintKey(node, module, fingerprint) {
|
||||
return "restore." + node + "." + module + "." + fingerprint;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "restore.<node>.<module>.<fingerprint>", or undefined for a key of another form. */
|
||||
export function parseAsksByRestoreNodeModuleFingerprintKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("restore.")) return undefined;
|
||||
_rest = _rest.slice(8);
|
||||
const _at1 = _rest.indexOf(".");
|
||||
if (_at1 <= 0) return undefined;
|
||||
const node = _rest.slice(0, _at1);
|
||||
_rest = _rest.slice(_at1 + 1);
|
||||
const _at3 = _rest.indexOf(".");
|
||||
if (_at3 <= 0) return undefined;
|
||||
const module = _rest.slice(0, _at3);
|
||||
_rest = _rest.slice(_at3 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const fingerprint = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { node, module, fingerprint };
|
||||
}
|
||||
|
||||
/** The key of one value of the state asks under the form "backup.<node>.<module>.<fingerprint>". */
|
||||
export function asksByBackupNodeModuleFingerprintKey(node, module, fingerprint) {
|
||||
return "backup." + node + "." + module + "." + fingerprint;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "backup.<node>.<module>.<fingerprint>", or undefined for a key of another form. */
|
||||
export function parseAsksByBackupNodeModuleFingerprintKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("backup.")) return undefined;
|
||||
_rest = _rest.slice(7);
|
||||
const _at1 = _rest.indexOf(".");
|
||||
if (_at1 <= 0) return undefined;
|
||||
const node = _rest.slice(0, _at1);
|
||||
_rest = _rest.slice(_at1 + 1);
|
||||
const _at3 = _rest.indexOf(".");
|
||||
if (_at3 <= 0) return undefined;
|
||||
const module = _rest.slice(0, _at3);
|
||||
_rest = _rest.slice(_at3 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const fingerprint = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { node, module, fingerprint };
|
||||
}
|
||||
|
||||
/** The key of one value of the state asks under the form "record.<node>.<module>.<digest>". */
|
||||
export function asksByRecordNodeModuleDigestKey(node, module, digest) {
|
||||
return "record." + node + "." + module + "." + digest;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "record.<node>.<module>.<digest>", or undefined for a key of another form. */
|
||||
export function parseAsksByRecordNodeModuleDigestKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("record.")) return undefined;
|
||||
_rest = _rest.slice(7);
|
||||
const _at1 = _rest.indexOf(".");
|
||||
if (_at1 <= 0) return undefined;
|
||||
const node = _rest.slice(0, _at1);
|
||||
_rest = _rest.slice(_at1 + 1);
|
||||
const _at3 = _rest.indexOf(".");
|
||||
if (_at3 <= 0) return undefined;
|
||||
const module = _rest.slice(0, _at3);
|
||||
_rest = _rest.slice(_at3 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const digest = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { node, module, digest };
|
||||
}
|
||||
|
||||
/** The key of one value of the state asks under the form "outside.<node>.<module>.<fingerprint>". */
|
||||
export function asksByOutsideNodeModuleFingerprintKey(node, module, fingerprint) {
|
||||
return "outside." + node + "." + module + "." + fingerprint;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "outside.<node>.<module>.<fingerprint>", or undefined for a key of another form. */
|
||||
export function parseAsksByOutsideNodeModuleFingerprintKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("outside.")) return undefined;
|
||||
_rest = _rest.slice(8);
|
||||
const _at1 = _rest.indexOf(".");
|
||||
if (_at1 <= 0) return undefined;
|
||||
const node = _rest.slice(0, _at1);
|
||||
_rest = _rest.slice(_at1 + 1);
|
||||
const _at3 = _rest.indexOf(".");
|
||||
if (_at3 <= 0) return undefined;
|
||||
const module = _rest.slice(0, _at3);
|
||||
_rest = _rest.slice(_at3 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const fingerprint = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { node, module, fingerprint };
|
||||
}
|
||||
|
||||
/** The key of one value of the state asks under the form "revert.<node>.<module>.<fingerprint>". */
|
||||
export function asksByRevertNodeModuleFingerprintKey(node, module, fingerprint) {
|
||||
return "revert." + node + "." + module + "." + fingerprint;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "revert.<node>.<module>.<fingerprint>", or undefined for a key of another form. */
|
||||
export function parseAsksByRevertNodeModuleFingerprintKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("revert.")) return undefined;
|
||||
_rest = _rest.slice(7);
|
||||
const _at1 = _rest.indexOf(".");
|
||||
if (_at1 <= 0) return undefined;
|
||||
const node = _rest.slice(0, _at1);
|
||||
_rest = _rest.slice(_at1 + 1);
|
||||
const _at3 = _rest.indexOf(".");
|
||||
if (_at3 <= 0) return undefined;
|
||||
const module = _rest.slice(0, _at3);
|
||||
_rest = _rest.slice(_at3 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const fingerprint = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { node, module, fingerprint };
|
||||
}
|
||||
|
||||
/** The key of one value of the state asks under the form "assignments.<proposal>". */
|
||||
export function asksByAssignmentsProposalKey(proposal) {
|
||||
return "assignments." + proposal;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "assignments.<proposal>", or undefined for a key of another form. */
|
||||
export function parseAsksByAssignmentsProposalKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("assignments.")) return undefined;
|
||||
_rest = _rest.slice(12);
|
||||
if (_rest === "") return undefined;
|
||||
const proposal = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { proposal };
|
||||
}
|
||||
|
||||
/** The key of one value of the state differences under the form "<node>.<module>". */
|
||||
export function differencesByNodeModuleKey(node, module) {
|
||||
return node + "." + module;
|
||||
|
||||
@@ -109,7 +109,7 @@ func fullConf(dir string) string {
|
||||
teller = append(teller, keepsOf(bucketsOf(tellerModule).marks)...)
|
||||
// The assigner's asks and the view's answers, each by its read tool and its views family (ADR 0615, DLV-M3; A-175), and the
|
||||
// teller's own first-views and findings; the buckets themselves are no longer the teller's to read.
|
||||
teller = append(append(append(teller, viewstest.Grants(assignerModule, assignerModule+".assigner_read_asks", tellerConsumer)...), viewstest.Grants(viewModule, viewModule+"."+viewstate.ViewAnswersReadTool, tellerConsumer)...), keepsOf(bucketsOf(tellerModule).firstViews)...)
|
||||
teller = append(append(append(teller, viewstest.Grants(assignerModule, assignerModule+"."+assignerAsksState, tellerConsumer)...), viewstest.Grants(viewModule, viewModule+"."+viewstate.ViewAnswersReadTool, tellerConsumer)...), keepsOf(bucketsOf(tellerModule).firstViews)...)
|
||||
teller = append(teller, keepsOf(bucketsOf(tellerModule).findings)...)
|
||||
view := append(append(readOf(tellerAnswers), readOf(assignerAsks)...), keepsOf(viewAnswers)...)
|
||||
assigner := keepsOf(assignerAsks)
|
||||
@@ -192,7 +192,7 @@ func startFull(t *testing.T) *fullBed {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// The assigner as the owner of its asks: its read tool and its views family (ADR 0615).
|
||||
viewstest.Serve(t, ctx, js, ctl, assignerModule, "asks", assignerModule+".assigner_read_asks", tellerConsumer)
|
||||
viewstest.Serve(t, ctx, js, ctl, assignerModule, "asks", assignerModule+"."+assignerAsksState, tellerConsumer)
|
||||
// The view as the owner of its answers, as the teller follows them (A-175, A-178).
|
||||
viewstest.Serve(t, ctx, js, ctl, viewModule, viewstate.ViewAnswersState, viewModule+"."+viewstate.ViewAnswersReadTool, tellerConsumer)
|
||||
return &fullBed{srv: srv, ctl: ctl, js: js, ctx: ctx}
|
||||
|
||||
@@ -122,7 +122,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro
|
||||
}
|
||||
defer writer.Close()
|
||||
reader.Findings = func() views.WireWriter { return writer }
|
||||
asks, err := reader.Follow(assignerModule, assignerAsksState, assignerModule+".assigner_read_asks")
|
||||
asks, err := reader.Follow(assignerModule, assignerAsksState, assignerModule+"."+assignerAsksState)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -174,5 +174,5 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro
|
||||
}
|
||||
}
|
||||
|
||||
// assignerAsksState is the assigner's state of its asks (assignerAsksBucket).
|
||||
// assignerAsksState is the seat mesh-wants' state asks, which the assigner keeps, and its first-view tool's name (design 47 G §717).
|
||||
const assignerAsksState = "asks"
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-view/viewstate"
|
||||
@@ -36,6 +37,10 @@ func TestTheNamesAreTheManifests(t *testing.T) {
|
||||
if len(m.Reads) != 0 {
|
||||
t.Errorf("the teller reads no other module's state, its manifest's reads are %v", m.Reads)
|
||||
}
|
||||
// Design 47 G §717: the assigner's asks are the seat mesh-wants' view, followed in seat form; no invoke names its tool.
|
||||
if want := "seat:mesh-wants.views." + assignerAsksState; !slices.Contains(m.Consumes, want) || slices.ContainsFunc(m.Invokes, func(e string) bool { return strings.HasPrefix(e, assignerModule+".") }) {
|
||||
t.Errorf("the teller follows %s and invokes nothing of the assigner's, its manifest's consumes are %v and invokes %v", want, m.Consumes, m.Invokes)
|
||||
}
|
||||
if want := viewModule + "." + viewstate.ViewAnswersReadTool; !slices.Contains(m.Invokes, want) {
|
||||
t.Errorf("the teller follows the view's answers by %s, its manifest's invokes are %v", want, m.Invokes)
|
||||
}
|
||||
|
||||
@@ -104,14 +104,14 @@ func TestManifestDeclarations(t *testing.T) { // 1240/AC1
|
||||
}
|
||||
// Its own states answers and teller-marks are said as its views family views.answers, read by teller_read_answers (A-175, A-178).
|
||||
// The join: its first view asked again by hand is a hand act, recorded through the seat (views.StatusTools).
|
||||
if want := []string{"mesh-delivery-assigner.assigner_read_asks", "mesh-delivery-view.view_read_answers", "seat:mesh-hand-acts.hand-act", "seat:mesh-catalog.registrations", "seat:mesh-broker.show", "seat:operator-channel.notify",
|
||||
if want := []string{"mesh-delivery-view.view_read_answers", "seat:mesh-hand-acts.hand-act", "seat:mesh-catalog.registrations", "seat:mesh-broker.show", "seat:operator-channel.notify",
|
||||
// A-126: who holds the seat operator-channel, whose state asks holds the router's record of its asks (operatorask.Bucket).
|
||||
"seat:mesh-module-assigner.assignments"}; !reflect.DeepEqual(m.Invokes, want) {
|
||||
t.Errorf("invokes = %v, want %v", m.Invokes, want)
|
||||
}
|
||||
// design 47 G §335 (TL1): the widening of a pipeline end is told through the seat operator-channel and kept in widens-said.
|
||||
// design 47 G §387: the keeper's ask for the findings is heard, and the finding stream is declared (§383).
|
||||
if want := []string{"mesh-conditions.findings-asked", "mesh-delivery-assigner.views.asks", "mesh-delivery-view.views.answers", "mesh-catalog.registration-changed", "mesh-pipeline-runner.pipeline-ended", "mesh-delivery.recovery-merged", "mesh-delivery.record-opened", "mesh-broker.recreated", "mesh-broker.dropped"}; !reflect.DeepEqual(m.Consumes, want) {
|
||||
if want := []string{"mesh-conditions.findings-asked", "seat:mesh-wants.views.asks", "mesh-delivery-view.views.answers", "mesh-catalog.registration-changed", "mesh-pipeline-runner.pipeline-ended", "mesh-delivery.recovery-merged", "mesh-delivery.record-opened", "mesh-broker.recreated", "mesh-broker.dropped"}; !reflect.DeepEqual(m.Consumes, want) {
|
||||
t.Errorf("consumes = %v, want %v", m.Consumes, want)
|
||||
}
|
||||
if want := []string{"operator-channel"}; !reflect.DeepEqual(sorted(m.Uses), want) {
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"teller_widens_said"
|
||||
],
|
||||
"invokes": [
|
||||
"mesh-delivery-assigner.assigner_read_asks",
|
||||
"mesh-delivery-view.view_read_answers",
|
||||
"seat:mesh-hand-acts.hand-act",
|
||||
"seat:mesh-catalog.registrations",
|
||||
@@ -21,7 +20,7 @@
|
||||
],
|
||||
"consumes": [
|
||||
"mesh-conditions.findings-asked",
|
||||
"mesh-delivery-assigner.views.asks",
|
||||
"seat:mesh-wants.views.asks",
|
||||
"mesh-delivery-view.views.answers",
|
||||
"mesh-catalog.registration-changed",
|
||||
"mesh-pipeline-runner.pipeline-ended",
|
||||
|
||||
Reference in New Issue
Block a user