mesh-recovery: aside sets the live data aside from the placement's entry, names as a list
Builds: design 47 G §516, §554, §566, A-123, A-124 aside takes the bus names from the catalog entry of the fingerprint the node-engine's placement runs, takes the aside whole and checked, removes the live objects, says set-aside; restore-aside puts it back. Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -122,6 +122,8 @@ func (s *fakeSeats) Streams(context.Context, string, string, string) ([]string,
|
||||
return s.streams, nil
|
||||
}
|
||||
|
||||
func (s *fakeSeats) RunningFingerprint(context.Context, string) (string, error) { return "fp-run", nil }
|
||||
|
||||
func (s *fakeSeats) Backup(context.Context, string) (string, error) {
|
||||
if s.backup == "" {
|
||||
return "", errors.New("no repository snapshot holds it")
|
||||
|
||||
@@ -28,6 +28,8 @@ func (e *Engine) run(ctx context.Context, a *Act) {
|
||||
e.expire(a.ID)
|
||||
case KindRestore:
|
||||
err = e.restore(ctx, a)
|
||||
case KindAside:
|
||||
err = e.aside(ctx, a)
|
||||
case KindRestoreAside:
|
||||
err = e.restoreAside(ctx, a)
|
||||
case KindDiscardAside:
|
||||
|
||||
@@ -76,6 +76,8 @@ type Seats interface {
|
||||
HandAct(caller, asker, what, why string) error
|
||||
// Streams are the bus names of a module's kept data at a fingerprint, from its catalog graph entry (§554 Bus names).
|
||||
Streams(ctx context.Context, module, kept, fingerprint string) ([]string, error)
|
||||
// RunningFingerprint is the fingerprint the node-engine's placement runs for the module (A-123).
|
||||
RunningFingerprint(ctx context.Context, module string) (string, error)
|
||||
// Backup brings the points directory of the module's item back beside its path through the backup holder and
|
||||
// answers where (§516); an error when no repository snapshot holds it.
|
||||
Backup(ctx context.Context, module string) (dir string, err error)
|
||||
|
||||
@@ -35,7 +35,7 @@ type asideRecord struct {
|
||||
}
|
||||
|
||||
func (r asideRecord) aside() seat.Aside {
|
||||
return seat.Aside{ID: r.ID, Name: strings.Join(r.Streams, ","), Size: r.Size}
|
||||
return seat.Aside{ID: r.ID, Names: r.Streams, Size: r.Size}
|
||||
}
|
||||
|
||||
func (e *Engine) asideRoot(module, kept string) (string, error) {
|
||||
@@ -279,6 +279,29 @@ func (e *Engine) readAside(module, kept, id string) (*asideRecord, error) {
|
||||
return &rec, nil
|
||||
}
|
||||
|
||||
// aside is the hand verb `aside` (§516, §554, A-123): it sets the live kept data aside without restoring it, taking the bus
|
||||
// names from the catalog entry of the fingerprint the node-engine's placement runs for the module, and removes the live
|
||||
// objects once the aside is whole and checked (a move, not a removal: the data stays in the aside until it is discarded or
|
||||
// put back by `restore-aside`); it ends with `set-aside`.
|
||||
func (e *Engine) aside(ctx context.Context, a *Act) error {
|
||||
fp, err := e.Seats.RunningFingerprint(ctx, a.Module)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.Fingerprint = fp
|
||||
names, err := e.Seats.Streams(ctx, a.Module, a.Kept, fp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rec, err := e.setAside(ctx, a, names, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
x := rec.aside()
|
||||
e.say(seat.EventSetAside, seat.SetAsideEvent{Act: a.ID, At: e.now(), ID: x.ID, Names: x.Names, Size: x.Size}, a.Module, a.Kept)
|
||||
return nil
|
||||
}
|
||||
|
||||
// restoreAside is `restore-aside` (§566): it puts an aside whose record ends at `removed` back under the live names it
|
||||
// was taken from, refusing while a live object of those names exists, and ends with `restored`.
|
||||
func (e *Engine) restoreAside(ctx context.Context, a *Act) error {
|
||||
@@ -312,7 +335,7 @@ func (e *Engine) discardAside(a *Act) error {
|
||||
return err
|
||||
}
|
||||
x := rec.aside()
|
||||
e.say(seat.EventAsideDiscarded, seat.AsideDiscardedEvent{Act: a.ID, At: e.now(), ID: x.ID, Name: x.Name, Size: x.Size}, a.Module, a.Kept)
|
||||
e.say(seat.EventAsideDiscarded, seat.AsideDiscardedEvent{Act: a.ID, At: e.now(), ID: x.ID, Names: x.Names, Size: x.Size}, a.Module, a.Kept)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -232,3 +232,26 @@ func TestRestoreAsideRefusesLiveNamesAndDiscardAsideRemovesTheDirectory(t *testi
|
||||
t.Errorf("asides %+v", kp.Asides)
|
||||
}
|
||||
}
|
||||
|
||||
// The hand verb aside sets the live data aside whole and removes it, naming the streams as a list, and restore-aside puts
|
||||
// it back once no live name exists (§516, §554, §566, A-123, A-124).
|
||||
func TestAsideMovesTheLiveDataIntoAnAsideAndRestoreAsidePutsItBack(t *testing.T) {
|
||||
r := newRig(t)
|
||||
ans := r.do(recovery.Act{Kind: recovery.KindAside, Module: "app", Kept: "notes", Why: "look at it", Caller: "tools", Asker: "op"})
|
||||
ev := r.s.named(seat.EventSetAside)
|
||||
if ans.Accepted == "" || len(ev) != 1 {
|
||||
t.Fatalf("answer %+v events %+v", ans, r.s.events)
|
||||
}
|
||||
sa := ev[0].Body.(seat.SetAsideEvent)
|
||||
if sa.Act != ans.Accepted || len(sa.Names) != 2 || sa.Size == 0 || len(r.b.streams) != 0 {
|
||||
t.Errorf("set-aside %+v streams %v", sa, r.b.streams)
|
||||
}
|
||||
if got := r.e.Unrestored(); len(got) != 1 {
|
||||
t.Errorf("unrestored %+v", got)
|
||||
}
|
||||
r.s.events = nil
|
||||
r.do(recovery.Act{Kind: recovery.KindRestoreAside, Module: "app", Kept: "notes", AsideID: sa.ID, Why: "done looking", Caller: "tools"})
|
||||
if lastRestored(t, r).Outcome != "done" || r.b.streams["app_notes"] != "hello" || len(r.e.Unrestored()) != 0 {
|
||||
t.Errorf("streams %v", r.b.streams)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user