aboutsummaryrefslogtreecommitdiff
path: root/internal/persistence/txn.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-10-05 17:49:48 -0400
committerhistoria <[not public]>2026-10-05 17:49:48 -0400
commit7a15a5d70004b28bf2a710fa0f536af2446e5b17 (patch)
tree920705853f79bb13a65fcb2f89cee38e6f2efab8 /internal/persistence/txn.go
parentec703a39738fefb60817f5659f76f8e683f8d301 (diff)
downloadthehouseoficarus-7a15a5d70004b28bf2a710fa0f536af2446e5b17.tar.gz
fix: production multi-step recipes, drop-weight validation, journal versioning
Diffstat (limited to 'internal/persistence/txn.go')
-rw-r--r--internal/persistence/txn.go14
1 files changed, 12 insertions, 2 deletions
diff --git a/internal/persistence/txn.go b/internal/persistence/txn.go
index a12e227..988af23 100644
--- a/internal/persistence/txn.go
+++ b/internal/persistence/txn.go
@@ -34,6 +34,10 @@ import (
// as a committed transaction that the next startup will roll back.
const journalRemoveAttempts = 3
+// journalVersion is the current journal schema version. Recover refuses a
+// version it does not understand rather than misreading a newer journal.
+const journalVersion = 1
+
type fileOp struct {
// Replace / Delete / Move data
Path string `json:"path"` // file this record is keyed by (its before-image lives here)
@@ -57,7 +61,10 @@ const (
)
type journalEntry struct {
- Ops []fileOp `json:"ops"`
+ // Version guards against a downgrade silently misreading a newer journal.
+ // 0 is the legacy unversioned format; unknown future versions are refused.
+ Version int `json:"version"`
+ Ops []fileOp `json:"ops"`
}
type Transaction struct {
@@ -244,7 +251,7 @@ func (t *Transaction) MarshalJournal() ([]byte, error) {
for _, p := range t.order {
ops = append(ops, *t.ops[p])
}
- return json.Marshal(journalEntry{Ops: ops})
+ return json.Marshal(journalEntry{Version: journalVersion, Ops: ops})
}
// Commit writes the journal (durable), applies all operations, and removes the
@@ -432,6 +439,9 @@ func Recover(journalDir string) error {
}
continue
}
+ if entry.Version != 0 && entry.Version != journalVersion {
+ return fmt.Errorf("journal %s: unsupported version %d", path, entry.Version)
+ }
t := &Transaction{ops: make(map[string]*fileOp), journalDir: journalDir}
for i := range entry.Ops {
op := entry.Ops[i]