Files
mesh-catalog/modules/mesh-hand-acts/cmd/mesh-hand-acts/copy.go
T
jschoubben 432de55186 mesh-hand-acts and mesh-healers stop reading the controller's hand-act log (ADR 0571 §13)
mesh-hand-acts lists acts from its own log alone and no longer copies: its copy tools answer that the copy is over,
with the marker of the copy that was made (the live top-up runs before this delivery). mesh-healers drops the watch of
mesh-controller_hand-acts and counts the seat's acts: it asks the seat's `hand-acts` once at its start for the
fortnight (new invoke) and hears act-recorded after, an act listed and heard counting once, so a restart does not
forget the fortnight. Tests: the two-log listing and the copy table became one listing and one copy-is-over test; the
healers' count test lost its controller-bucket helper and gained the seat listing; the integration test now proves the
old bucket is not copied.

(issue 774, 774/S10)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 00:17:52 +01:00

82 lines
3.2 KiB
Go

package main
// The one-time copy of the controller's hand-act log into this seat's log is over (novox/hq research 072 row 26, ADR 0571
// §13, issue 774). The controller kept every act of its life in its bucket `mesh-controller_hand-acts`; they were copied
// once into `acts`, each as the controller wrote it, by the earlier builds of this module, which left the marker
// `controller-hand-acts` of the state `copied`. This module no longer reads that bucket, so the copy cannot run: the
// tools `hand_acts_copy` and `hand_acts_copied` stay and say so, with the marker's figures when it exists.
import (
"encoding/json"
"fmt"
"time"
)
// CopiedState is the state that holds the marker, and CopyKey the marker's key.
const (
CopiedState = "copied"
CopyKey = "controller-hand-acts"
)
// CopyMarker is what the copy leaves behind once it is whole: when, by what, how many acts, and which entries could not
// be read as acts (copied unchanged all the same, so nothing is lost).
type CopyMarker struct {
At time.Time `json:"at"`
By string `json:"by"`
Source string `json:"source"`
Found int `json:"found"`
Copied int `json:"copied"`
Already int `json:"already-there"`
// Unreadable are the keys whose value is not an act; they were copied as they were.
Unreadable []string `json:"unreadable,omitempty"`
FirstKey string `json:"first-key,omitempty"`
LastKey string `json:"last-key,omitempty"`
}
// CopyStatus is what the tools answer: the marker if the copy is whole, and how the two logs stand now.
type CopyStatus struct {
Done bool `json:"done"`
Marker *CopyMarker `json:"marker,omitempty"`
// Said is a sentence for a person: what this call did or found.
Said string `json:"said"`
// New is how many acts this seat's log holds.
New *int `json:"new-log-entries,omitempty"`
}
// gone is what a call to copy answers.
const gone = "the controller's hand-act log is no longer read, so nothing can be copied (novox/hq ADR 0571 §13, issue 774); " +
"the acts copied before are in the log `acts`"
// Copy answers that the copy is over: it reads and writes nothing of the controller's. The marker, when the copy once
// ran to its end, is returned with the answer.
func (l *Log) Copy(by string, topUp bool) (CopyStatus, error) {
st, err := l.Copied()
if err != nil {
return st, err
}
st.Said = gone + "; " + st.Said
return st, nil
}
// Copied says where the copy ended: the marker with its figures, or that none was left, and how many acts the log holds.
func (l *Log) Copied() (CopyStatus, error) {
raw, found, err := l.Store.Get(CopiedState, CopyKey)
if err != nil {
return CopyStatus{}, fmt.Errorf("the copy's marker cannot be read: %w", err)
}
st := CopyStatus{Said: "no marker of a finished copy is left"}
if found {
var m CopyMarker
if err := json.Unmarshal(raw, &m); err != nil {
return CopyStatus{}, fmt.Errorf("the copy's marker is not readable: %w", err)
}
st = CopyStatus{Done: true, Marker: &m, Said: fmt.Sprintf("copied at %s by %s: %d copied, %d already there, of %d in %s",
m.At.Format(time.RFC3339), m.By, m.Copied, m.Already, m.Found, m.Source)}
}
if f, err := l.Store.Fill(ActsLog); err == nil {
n := int(f.Entries)
st.New = &n
}
return st, nil
}