1 Commits
9 changed files with 21 additions and 21 deletions
+1 -1
View File
@@ -60,7 +60,7 @@ type Membership struct {
Emits string `json:"emits"`
Reaches map[string][]string `json:"reaches,omitempty"`
Tools string `json:"tools"`
// State is every bucket the module's code may reach, by the name it uses (novox/hq ADR 0201).
// State is every bucket the module's code may reach, by the name it uses (novox/hq ADR 0202).
State []StateIssued `json:"state,omitempty"`
}
+8 -8
View File
@@ -14,7 +14,7 @@ import (
"github.com/nats-io/nats.go/jetstream"
)
// A module's state on the bus (novox/hq ADR 0201): key-value buckets the controller creates from what
// A module's state on the bus (novox/hq ADR 0202): key-value buckets the controller creates from what
// the module declared, and issues to each assignment in its membership by the name the module uses —
// its own state by the local name, another module's as `<module>.<name>`.
//
@@ -23,7 +23,7 @@ import (
// timeout, not a refusal (measured, novox/hq research 024). So what a module may reach is decided here,
// from its membership, and refused with the reason before anything is sent.
// StateIssued is one bucket an assignment may reach (ADR 0201).
// StateIssued is one bucket an assignment may reach (ADR 0202).
type StateIssued struct {
Name string `json:"name"`
Bucket string `json:"bucket"`
@@ -61,7 +61,7 @@ func (c *Conn) issuedState(module, name string) (StateIssued, error) {
m := c.Membership(module)
if m == nil {
return StateIssued{}, fmt.Errorf("%s has no membership issued on %s yet, so no state of it is reachable "+
"until the mesh issues one (novox/hq ADR 0201)", module, c.node)
"until the mesh issues one (novox/hq ADR 0202)", module, c.node)
}
var names []string
for _, s := range m.State {
@@ -76,7 +76,7 @@ func (c *Conn) issuedState(module, name string) (StateIssued, error) {
issued = strings.Join(names, ", ")
}
return StateIssued{}, fmt.Errorf("%s keeps and reads no state called %q: it declares what it keeps under "+
"`state` and what it reads under `reads` as <module>.<name>, and was issued: %s (novox/hq ADR 0201)",
"`state` and what it reads under `reads` as <module>.<name>, and was issued: %s (novox/hq ADR 0202)",
module, name, issued)
}
@@ -144,7 +144,7 @@ func (c *Conn) StatePut(module, name, key string, value json.RawMessage) (uint64
if field := credentialField(value); field != "" {
return 0, fmt.Errorf("%s's %s.%s carries a field %q, which names a credential: no secret is kept in state, "+
"sealed or not — a bucket is a stream, and a machine joining a year later reads it whole. Name the "+
"secret and fetch it on request/reply (novox/hq ADR 0201, design 32 §10)", module, name, key, field)
"secret and fetch it on request/reply (novox/hq ADR 0202, design 32 §10)", module, name, key, field)
}
ctx, cancel := context.WithTimeout(context.Background(), StateTimeout)
defer cancel()
@@ -209,14 +209,14 @@ func (c *Conn) writable(module, name string) (StateIssued, error) {
if dot := strings.LastIndex(name, "."); dot > 0 {
owner = name[:dot]
}
return s, fmt.Errorf("%s reads %s and does not keep it: only %s's own instances write it (novox/hq ADR 0201)",
return s, fmt.Errorf("%s reads %s and does not keep it: only %s's own instances write it (novox/hq ADR 0202)",
module, name, owner)
}
return s, nil
}
// StateWatch hands deliver the current value of every key matching the pattern — none that is
// deleted — and then every change, in order (ADR 0201). It returns once the current values are
// deleted — and then every change, in order (ADR 0202). It returns once the current values are
// delivered; deliver is called from one goroutine, one change at a time, and an error from it is said
// and the watch goes on: state is not a queue, and the next change, or the next start, reads it again.
// The pattern is a key, with `*` for one name and `**` for the rest; empty is every key.
@@ -314,7 +314,7 @@ func valueOf(raw []byte) json.RawMessage {
// credentialEndings are the ends of a field name that say its value is a credential. A guard against
// the ordinary mistake, not a determined one: a sealed value is plain text to anything inspecting it,
// so the rule is checked where it can be and said to be partial (ADR 0201).
// so the rule is checked where it can be and said to be partial (ADR 0202).
var credentialEndings = []string{"password", "passwd", "secret", "token", "credential", "credentials",
"authorization", "apikey", "privatekey", "accesskey", "cookie"}
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"testing"
)
// A value naming a credential anywhere in it is found (novox/hq ADR 0201) — the guard against the
// A value naming a credential anywhere in it is found (novox/hq ADR 0202) — the guard against the
// ordinary mistake — and a value that only mentions tokens as a count is not.
func TestACredentialNamedFieldIsFoundAnywhereInAValue(t *testing.T) {
for value, want := range map[string]string{
+3 -3
View File
@@ -51,7 +51,7 @@ type Registration struct {
// code subscribes; the runtime binds the module's consumer once and calls deliver for every event,
// acknowledging it on the bus when deliver returns nil.
//
// State and Watch reach the module's state (novox/hq ADR 0201): State answers `get`, `put`, `delete`
// State and Watch reach the module's state (novox/hq ADR 0202): State answers `get`, `put`, `delete`
// and `keys`; Watch hands deliver the current values and then every change, and returns once the
// current values are delivered — the watch is the child's, and stops when the child does.
type Bus interface {
@@ -110,7 +110,7 @@ type child struct {
next int64
dead chan struct{}
why error
// watches are the state watches this child asked for, stopped when it exits (ADR 0201): a child
// watches are the state watches this child asked for, stopped when it exits (ADR 0202): a child
// that starts again watches again, as its code runs again.
watches []func()
}
@@ -234,7 +234,7 @@ func Start(module, entry string, env []string, mesh Bus, logf func(string, ...an
// Each change is asked of this child, in order, naming the watch it is for by
// the id the child asked it with — two watches of one state are two handlers;
// the watch is answered once the current values have been handed over, so a
// bundle that awaits it has the whole of the state before it goes on (ADR 0201).
// bundle that awaits it has the whole of the state before it goes on (ADR 0202).
var stop func()
watch := m.ID
stop, err = mesh.Watch(m.Params, func(change json.RawMessage) error {
+1 -1
View File
@@ -183,7 +183,7 @@ func (m *Mesh) Pending(t *testing.T, node, module string) (ackPending, notDelive
return uint64(info.NumAckPending), info.NumPending
}
// Bucket makes a module's state afresh as the controller does from the catalogue (novox/hq ADR 0201),
// Bucket makes a module's state afresh as the controller does from the catalogue (novox/hq ADR 0202),
// and answers it for writing what is there before a bundle starts.
func (m *Mesh) Bucket(t *testing.T, name string) nats.KeyValue {
t.Helper()
+3 -3
View File
@@ -579,7 +579,7 @@ func (b *moduleBus) Subscribe(deliver func(json.RawMessage) error) error {
return nil
}
// stateAsked is what a bundle names when it reaches its state (ADR 0201): the state by the name its
// stateAsked is what a bundle names when it reaches its state (ADR 0202): the state by the name its
// module uses, a key, and for a put the value.
type stateAsked struct {
State string `json:"state"`
@@ -587,7 +587,7 @@ type stateAsked struct {
Value json.RawMessage `json:"value"`
}
// State answers a bundle's `get`, `put`, `delete` and `keys` on its module's state (ADR 0201). The
// State answers a bundle's `get`, `put`, `delete` and `keys` on its module's state (ADR 0202). The
// runtime refuses, with the reason, a state the module was not issued and a write to one it only reads.
func (b *moduleBus) State(verb string, params json.RawMessage) (json.RawMessage, error) {
var asked stateAsked
@@ -629,7 +629,7 @@ func (b *moduleBus) State(verb string, params json.RawMessage) (json.RawMessage,
return json.Marshal(answer)
}
// Watch hands a bundle its module's state as it is and as it changes (ADR 0201): `{state, key}`, the
// Watch hands a bundle its module's state as it is and as it changes (ADR 0202): `{state, key}`, the
// key a pattern with `*` and `**`, empty for every key.
func (b *moduleBus) Watch(params json.RawMessage, deliver func(json.RawMessage) error) (func(), error) {
var asked stateAsked
+2 -2
View File
@@ -10,7 +10,7 @@ import (
mt "github.com/novox/mesh-tools/node-tools/internal/meshtest"
)
// novox/hq ADR 0201: a module keeps its current state in buckets it declares, and its code reaches
// novox/hq ADR 0202: a module keeps its current state in buckets it declares, and its code reaches
// them through the runtime. The owner's instances write and read; a reader only reads; a watch hands
// the current values — none that is deleted — and then every change; the runtime refuses, with the
// reason, what the module was not issued, a write to state it only reads, and a value naming a
@@ -136,7 +136,7 @@ func waitFor(t *testing.T, path, line string) {
})
}
// The TypeScript SDK against the runtime (ADR 0201): two watches of one state, each handed only its
// The TypeScript SDK against the runtime (ADR 0202): two watches of one state, each handed only its
// own changes, the current values handled before the module's import goes on.
func TestTheSDKsStateReachesTheRuntime(t *testing.T) {
mesh := mt.New(t)
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env node
// A bundle that keeps and reads state through the runtime (novox/hq ADR 0201), written against the
// A bundle that keeps and reads state through the runtime (novox/hq ADR 0202), written against the
// protocol with no SDK: on start it watches STATE_NAME and writes every change it is handed to
// STATE_LOG; its tools put, get, delete and list keys of whichever state they name.
import { appendFileSync } from "node:fs";
+1 -1
View File
@@ -1,4 +1,4 @@
// A module that keeps state through the SDK (novox/hq ADR 0201): it watches its servers as it is
// A module that keeps state through the SDK (novox/hq ADR 0202): it watches its servers as it is
// imported, and writes each change it is handed to STATE_LOG; one tool registers a server.
import { appendFileSync } from "node:fs";
import { state } from "@novox/mesh-sdk/state";