K24 (mesh-recovery's hand verbs): take, restore, retry, aside, discard-aside and expire-points, asker and why on every hand verb, one answer form with cancel
Builds: design 47 G §682, §691 (§516, §554, §566, §656, §681) Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
@@ -14,6 +14,12 @@ const (
|
||||
VerbKeptPoints = "kept-points"
|
||||
VerbRestoreAside = "restore-aside"
|
||||
VerbCancel = "cancel"
|
||||
VerbTake = "take"
|
||||
VerbRestore = "restore"
|
||||
VerbRetry = "retry"
|
||||
VerbAside = "aside"
|
||||
VerbDiscardAside = "discard-aside"
|
||||
VerbExpirePoints = "expire-points"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -28,7 +34,7 @@ const (
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbSnapshotKept, VerbRestoreKept, VerbKeptPoints, VerbRestoreAside, VerbCancel}
|
||||
return []string{VerbSnapshotKept, VerbRestoreKept, VerbKeptPoints, VerbRestoreAside, VerbCancel, VerbTake, VerbRestore, VerbRetry, VerbAside, VerbDiscardAside, VerbExpirePoints}
|
||||
}
|
||||
|
||||
// Events is every event published on the seat's subject: a new copy each call.
|
||||
@@ -244,6 +250,8 @@ type KeptPointsAnswer struct {
|
||||
|
||||
// RestoreAsideInput is what restore-aside takes.
|
||||
type RestoreAsideInput struct {
|
||||
// who asked: the caller the tool runner proved and recorded for the call (who@node, or operator), which the tools bundle's recovery tool passes and a module's process leaves out; the hand-act log names it beside the account the bus proved (design 47 G 682)
|
||||
Asker string `json:"asker,omitempty"`
|
||||
// the aside's id
|
||||
ID string `json:"id"`
|
||||
// the kept data, its local name in the module's manifest
|
||||
@@ -268,18 +276,160 @@ type RestoreAsideAnswer struct {
|
||||
type CancelInput struct {
|
||||
// the act's id
|
||||
Act string `json:"act"`
|
||||
// who asked: the caller the tool runner proved and recorded for the call (who@node, or operator), which the tools bundle's recovery tool passes and a module's process leaves out; the hand-act log names it beside the account the bus proved (design 47 G 682)
|
||||
Asker string `json:"asker,omitempty"`
|
||||
// why, which the hand-act log keeps
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// CancelAnswer is what cancel answers.
|
||||
type CancelAnswer struct {
|
||||
// the act ended cancelled
|
||||
Cancelled bool `json:"cancelled,omitempty"`
|
||||
// accepted: the id of the act it cancelled, whose ending event follows under that id
|
||||
Accepted string `json:"accepted,omitempty"`
|
||||
// busy: the id of the act that runs; it keeps no queue, so the caller asks again on that act's ending event
|
||||
Busy string `json:"busy,omitempty"`
|
||||
// why not, naming the step an act has begun; set alone
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// TakeInput is what take takes.
|
||||
type TakeInput struct {
|
||||
// who asked: the caller the tool runner proved and recorded for the call (who@node, or operator), which the tools bundle's recovery tool passes and a module's process leaves out; the hand-act log names it beside the account the bus proved (design 47 G 682)
|
||||
Asker string `json:"asker,omitempty"`
|
||||
// the fingerprint whose form the point is taken at
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
// the kept data, its local name in the module's manifest
|
||||
Kept string `json:"kept"`
|
||||
// the module
|
||||
Module string `json:"module"`
|
||||
// why, which the hand-act log keeps
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// TakeAnswer is what take answers.
|
||||
type TakeAnswer struct {
|
||||
// accepted: the act's id, which the ending event carries
|
||||
Accepted string `json:"accepted,omitempty"`
|
||||
// busy: the id of the act that runs; it keeps no queue, so the caller asks again on that act's ending event
|
||||
Busy string `json:"busy,omitempty"`
|
||||
// why it was not taken; set alone
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// RestoreInput is what restore takes.
|
||||
type RestoreInput struct {
|
||||
// who asked: the caller the tool runner proved and recorded for the call (who@node, or operator), which the tools bundle's recovery tool passes and a module's process leaves out; the hand-act log names it beside the account the bus proved (design 47 G 682)
|
||||
Asker string `json:"asker,omitempty"`
|
||||
// ask the backup holder for the points directory when the point is missing there; only with snapshot
|
||||
FromBackup bool `json:"from-backup,omitempty"`
|
||||
// the kept data, its local name in the module's manifest
|
||||
Kept string `json:"kept"`
|
||||
// the module
|
||||
Module string `json:"module"`
|
||||
// a keeper's snapshot by its request (design 47 G 681)
|
||||
Request string `json:"request,omitempty"`
|
||||
// a restore point's name
|
||||
Snapshot string `json:"snapshot,omitempty"`
|
||||
// why, which the hand-act log keeps
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// RestoreAnswer is what restore answers.
|
||||
type RestoreAnswer struct {
|
||||
// accepted: the act's id, which the ending event carries
|
||||
Accepted string `json:"accepted,omitempty"`
|
||||
// busy: the id of the act that runs; it keeps no queue, so the caller asks again on that act's ending event
|
||||
Busy string `json:"busy,omitempty"`
|
||||
// why it was not taken; set alone
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// RetryInput is what retry takes.
|
||||
type RetryInput struct {
|
||||
// who asked: the caller the tool runner proved and recorded for the call (who@node, or operator), which the tools bundle's recovery tool passes and a module's process leaves out; the hand-act log names it beside the account the bus proved (design 47 G 682)
|
||||
Asker string `json:"asker,omitempty"`
|
||||
// the kept data, its local name in the module's manifest
|
||||
Kept string `json:"kept"`
|
||||
// the module
|
||||
Module string `json:"module"`
|
||||
// why, which the hand-act log keeps
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// RetryAnswer is what retry answers.
|
||||
type RetryAnswer struct {
|
||||
// accepted: the act's id, which the ending event carries
|
||||
Accepted string `json:"accepted,omitempty"`
|
||||
// busy: the id of the act that runs; it keeps no queue, so the caller asks again on that act's ending event
|
||||
Busy string `json:"busy,omitempty"`
|
||||
// why it was not taken; set alone
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// AsideInput is what aside takes.
|
||||
type AsideInput struct {
|
||||
// who asked: the caller the tool runner proved and recorded for the call (who@node, or operator), which the tools bundle's recovery tool passes and a module's process leaves out; the hand-act log names it beside the account the bus proved (design 47 G 682)
|
||||
Asker string `json:"asker,omitempty"`
|
||||
// the kept data, its local name in the module's manifest
|
||||
Kept string `json:"kept"`
|
||||
// the module
|
||||
Module string `json:"module"`
|
||||
// why, which the hand-act log keeps
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// AsideAnswer is what aside answers.
|
||||
type AsideAnswer struct {
|
||||
// accepted: the act's id, which the ending event carries
|
||||
Accepted string `json:"accepted,omitempty"`
|
||||
// busy: the id of the act that runs; it keeps no queue, so the caller asks again on that act's ending event
|
||||
Busy string `json:"busy,omitempty"`
|
||||
// why it was not taken; set alone
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// DiscardAsideInput is what discard-aside takes.
|
||||
type DiscardAsideInput struct {
|
||||
// who asked: the caller the tool runner proved and recorded for the call (who@node, or operator), which the tools bundle's recovery tool passes and a module's process leaves out; the hand-act log names it beside the account the bus proved (design 47 G 682)
|
||||
Asker string `json:"asker,omitempty"`
|
||||
// the aside's id
|
||||
ID string `json:"id"`
|
||||
// the kept data, its local name in the module's manifest
|
||||
Kept string `json:"kept"`
|
||||
// the module
|
||||
Module string `json:"module"`
|
||||
// why, which the hand-act log keeps
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// DiscardAsideAnswer is what discard-aside answers.
|
||||
type DiscardAsideAnswer struct {
|
||||
// accepted: the act's id, which the ending event carries
|
||||
Accepted string `json:"accepted,omitempty"`
|
||||
// busy: the id of the act that runs; it keeps no queue, so the caller asks again on that act's ending event
|
||||
Busy string `json:"busy,omitempty"`
|
||||
// why it was not taken; set alone
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// ExpirePointsInput is what expire-points takes.
|
||||
type ExpirePointsInput struct {
|
||||
// who asked: the caller the tool runner proved and recorded for the call (who@node, or operator), which the tools bundle's recovery tool passes and a module's process leaves out; the hand-act log names it beside the account the bus proved (design 47 G 682)
|
||||
Asker string `json:"asker,omitempty"`
|
||||
// why, which the hand-act log keeps
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// ExpirePointsAnswer is what expire-points answers.
|
||||
type ExpirePointsAnswer struct {
|
||||
// accepted: the act's id, which the ending event carries
|
||||
Accepted string `json:"accepted,omitempty"`
|
||||
// busy: the id of the act that runs; it keeps no queue, so the caller asks again on that act's ending event
|
||||
Busy string `json:"busy,omitempty"`
|
||||
// why it was not taken; set alone
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// EndedEvent is the body of the event ended.
|
||||
type EndedEvent struct {
|
||||
// the id the act was answered accepted with, or a hand act's own id (design 47 G 560)
|
||||
|
||||
@@ -45,12 +45,42 @@ func TestFixtures(t *testing.T) {
|
||||
decode: func(b []byte) (any, error) { var v RestoreKeptAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-points lists a point, an aside and the act that runs", subject: "", given: "{\"asides\":[{\"id\":\"20261111T121200Z\",\"name\":\"mesh-knowledge_ledger\",\"size\":4096}],\"points\":[{\"at\":\"2026-11-11T10:00:00Z\",\"catch-up\":{\"tool\":\"knowledge_catch_up\"},\"consumers\":[{\"name\":\"c1\",\"sequence\":42,\"stream\":\"KV_x\"}],\"digests\":[{\"digest\":\"sha256:00\",\"name\":\"KV_x\"}],\"fingerprint\":\"0123456789ab\",\"form\":2,\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"size\":2048,\"snapshot\":\"2-0123456789ab\"}],\"running\":{\"act\":\"a-1\",\"since\":\"2026-11-11T10:00:00Z\",\"step\":\"waiting on the dump\",\"waits-on\":\"item-ended of the bus item\"}}", wire: "{\"asides\":[{\"id\":\"20261111T121200Z\",\"name\":\"mesh-knowledge_ledger\",\"size\":4096}],\"points\":[{\"at\":\"2026-11-11T10:00:00Z\",\"catch-up\":{\"tool\":\"knowledge_catch_up\"},\"consumers\":[{\"name\":\"c1\",\"sequence\":42,\"stream\":\"KV_x\"}],\"digests\":[{\"digest\":\"sha256:00\",\"name\":\"KV_x\"}],\"fingerprint\":\"0123456789ab\",\"form\":2,\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"size\":2048,\"snapshot\":\"2-0123456789ab\"}],\"running\":{\"act\":\"a-1\",\"since\":\"2026-11-11T10:00:00Z\",\"step\":\"waiting on the dump\",\"waits-on\":\"item-ended of the bus item\"}}",
|
||||
decode: func(b []byte) (any, error) { var v KeptPointsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "restore-aside names the aside", subject: "", given: "{\"id\":\"20261111T121200Z\",\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"why\":\"an aside left at removed\"}", wire: "{\"id\":\"20261111T121200Z\",\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"why\":\"an aside left at removed\"}",
|
||||
{name: "restore-aside names the aside", subject: "", given: "{\"asker\":\"jochen@shanks\",\"id\":\"20261111T121200Z\",\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"why\":\"an aside left at removed\"}", wire: "{\"asker\":\"jochen@shanks\",\"id\":\"20261111T121200Z\",\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"why\":\"an aside left at removed\"}",
|
||||
decode: func(b []byte) (any, error) { var v RestoreAsideInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "cancel names the act", subject: "", given: "{\"act\":\"a-1\",\"why\":\"the dump waits too long\"}", wire: "{\"act\":\"a-1\",\"why\":\"the dump waits too long\"}",
|
||||
{name: "cancel names the act", subject: "", given: "{\"act\":\"a-1\",\"asker\":\"jochen@shanks\",\"why\":\"the dump waits too long\"}", wire: "{\"act\":\"a-1\",\"asker\":\"jochen@shanks\",\"why\":\"the dump waits too long\"}",
|
||||
decode: func(b []byte) (any, error) { var v CancelInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "take names the fingerprint whose form the point is taken at", subject: "", given: "{\"asker\":\"jochen@shanks\",\"fingerprint\":\"0123456789ab\",\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"why\":\"the operator's hand act\"}", wire: "{\"asker\":\"jochen@shanks\",\"fingerprint\":\"0123456789ab\",\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"why\":\"the operator's hand act\"}",
|
||||
decode: func(b []byte) (any, error) { var v TakeInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "take answers accepted with the act", subject: "", given: "{\"accepted\":\"a-20261111t100000\"}", wire: "{\"accepted\":\"a-20261111t100000\"}",
|
||||
decode: func(b []byte) (any, error) { var v TakeAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "restore takes a point by its name", subject: "", given: "{\"asker\":\"jochen@shanks\",\"from-backup\":true,\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"snapshot\":\"2-0123456789ab\",\"why\":\"the operator's hand act\"}", wire: "{\"asker\":\"jochen@shanks\",\"from-backup\":true,\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"snapshot\":\"2-0123456789ab\",\"why\":\"the operator's hand act\"}",
|
||||
decode: func(b []byte) (any, error) { var v RestoreInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "restore takes a keeper's snapshot by its request", subject: "", given: "{\"asker\":\"jochen@shanks\",\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"request\":\"r-20261111t100000\",\"why\":\"the operator's hand act\"}", wire: "{\"asker\":\"jochen@shanks\",\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"request\":\"r-20261111t100000\",\"why\":\"the operator's hand act\"}",
|
||||
decode: func(b []byte) (any, error) { var v RestoreInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "restore answers busy with the act that runs", subject: "", given: "{\"busy\":\"a-20261111t100000\"}", wire: "{\"busy\":\"a-20261111t100000\"}",
|
||||
decode: func(b []byte) (any, error) { var v RestoreAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "retry names the module and its kept data", subject: "", given: "{\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"why\":\"a failed take\"}", wire: "{\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"why\":\"a failed take\"}",
|
||||
decode: func(b []byte) (any, error) { var v RetryInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "retry answers an error when nothing failed", subject: "", given: "{\"error\":\"nothing to retry\"}", wire: "{\"error\":\"nothing to retry\"}",
|
||||
decode: func(b []byte) (any, error) { var v RetryAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "aside sets the live kept data aside", subject: "", given: "{\"asker\":\"jochen@shanks\",\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"why\":\"the operator's hand act\"}", wire: "{\"asker\":\"jochen@shanks\",\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"why\":\"the operator's hand act\"}",
|
||||
decode: func(b []byte) (any, error) { var v AsideInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "aside answers accepted with the act", subject: "", given: "{\"accepted\":\"a-20261111t100000\"}", wire: "{\"accepted\":\"a-20261111t100000\"}",
|
||||
decode: func(b []byte) (any, error) { var v AsideAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "discard-aside names the aside", subject: "", given: "{\"asker\":\"jochen@shanks\",\"id\":\"20261111T121200Z\",\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"why\":\"the operator's hand act\"}", wire: "{\"asker\":\"jochen@shanks\",\"id\":\"20261111T121200Z\",\"kept\":\"ledger\",\"module\":\"mesh-knowledge\",\"why\":\"the operator's hand act\"}",
|
||||
decode: func(b []byte) (any, error) { var v DiscardAsideInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "discard-aside answers an error", subject: "", given: "{\"error\":\"no such aside\"}", wire: "{\"error\":\"no such aside\"}",
|
||||
decode: func(b []byte) (any, error) { var v DiscardAsideAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "expire-points has no field of its own", subject: "", given: "{\"asker\":\"operator\",\"why\":\"the points past 90 days\"}", wire: "{\"asker\":\"operator\",\"why\":\"the points past 90 days\"}",
|
||||
decode: func(b []byte) (any, error) { var v ExpirePointsInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "expire-points answers accepted with the act", subject: "", given: "{\"accepted\":\"a-20261111t100000\"}", wire: "{\"accepted\":\"a-20261111t100000\"}",
|
||||
decode: func(b []byte) (any, error) { var v ExpirePointsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "cancel answers accepted with the act it cancelled", subject: "", given: "{\"accepted\":\"a-1\"}", wire: "{\"accepted\":\"a-1\"}",
|
||||
decode: func(b []byte) (any, error) { var v CancelAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "cancel answers an error naming the step an act has begun", subject: "", given: "{\"error\":\"the act has begun: step restoring\"}", wire: "{\"error\":\"the act has begun: step restoring\"}",
|
||||
decode: func(b []byte) (any, error) { var v CancelAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "cancel answers busy with the act that runs", subject: "", given: "{\"busy\":\"a-20261111t100000\"}", wire: "{\"busy\":\"a-20261111t100000\"}",
|
||||
decode: func(b []byte) (any, error) { var v CancelAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
}
|
||||
for _, c := range cases {
|
||||
v, err := c.decode([]byte(c.given))
|
||||
|
||||
Reference in New Issue
Block a user