57 lines
2.4 KiB
Go
57 lines
2.4 KiB
Go
package runner
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"io/fs"
|
|
"os"
|
|
|
|
"textmachine/platform/internal/ingest"
|
|
)
|
|
|
|
// artifacts.go: the engine's FILE channels, as opposed to its command channels.
|
|
//
|
|
// The bank is the one read-out the engine publishes as a file rather than on stdout (D39.122): it
|
|
// lives beside the project database, is written atomically, and can therefore be read while a run is
|
|
// going — which is exactly what a signing stop needs, since the stop IS a live run waiting.
|
|
|
|
// ErrNoBank is a book that has no bank read-out yet: it has never been through a run that produced
|
|
// one. An ordinary state and not a failure — and the caller saves NOTHING on it: an empty bank
|
|
// written over a real one would erase a read-out the engine has simply not made yet.
|
|
var ErrNoBank = errors.New("runner: this book has no bank read-out")
|
|
|
|
// maxBank bounds the read-out — three orders of magnitude above any real bank, so it refuses a file
|
|
// that is not one rather than sizing one that is.
|
|
const maxBank = 256 << 20
|
|
|
|
// ReadBank decodes a book's whole-bank read-out at the path the ENGINE published for it — the
|
|
// `artifacts.bank_export` of its manifest and status documents (row 213).
|
|
//
|
|
// The path is taken rather than derived: this function used to parse `book.yaml` and re-derive
|
|
// `<project_db>.bank.json` by copying the engine's default from backend/internal/config/book.go,
|
|
// which is another zone's convention — a changed default there would have silently walked this read
|
|
// off to a path where no file ever appears.
|
|
func ReadBank(path string) (ingest.Bank, error) {
|
|
if path == "" {
|
|
// An engine build from before the artifact envelope (D39.158). Loud, because the quiet
|
|
// alternative is a bank that silently never refreshes on such a deployment.
|
|
return ingest.Bank{}, errors.New("runner: the engine published no bank read-out path: its manifest carries no artifacts envelope")
|
|
}
|
|
f, err := os.Open(path)
|
|
if errors.Is(err, fs.ErrNotExist) {
|
|
return ingest.Bank{}, ErrNoBank
|
|
}
|
|
if err != nil {
|
|
return ingest.Bank{}, fmt.Errorf("runner: open bank read-out: %w", err)
|
|
}
|
|
defer f.Close()
|
|
raw, err := io.ReadAll(io.LimitReader(f, maxBank+1))
|
|
if err != nil {
|
|
return ingest.Bank{}, fmt.Errorf("runner: read bank read-out: %w", err)
|
|
}
|
|
if len(raw) > maxBank {
|
|
return ingest.Bank{}, errors.New("runner: the bank read-out is larger than this platform will read")
|
|
}
|
|
return ingest.DecodeBank(raw)
|
|
}
|