Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/changes/unreleased/1962-furrow-store-compat-test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
kind: changed
title: The embedded storage engine is furrow 0.3.3, which opens a large store without scanning it
pr: 1962
surface: [engine]
invalidates: []
---
furrow 0.3.3 validates a store's pack checkpoint with one index seek instead of counting every object, opens a settled store without taking the pack lock, and answers `status` without writing. Saving and attaching no longer slow down as the store grows. A compat test seals with furrow 0.2.0, then the embedded engine, then 0.2.0 again on the same store, so existing stores keep working in both directions.
87 changes: 87 additions & 0 deletions internal/cellstore/storecompat_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package cellstore

import (
"context"
"os"
"path/filepath"
"testing"

"github.com/Agent-Field/codeaf/internal/cell"
"github.com/Agent-Field/codeaf/internal/furrow"
)

// oldEngineEnv names an older furrow release binary. The store-format tests
// below skip without it: they prove that a store written by that release opens
// and keeps capturing under the embedded engine, and the other way round.
const oldEngineEnv = "CODEAF_FURROW_OLD"

// TestStoreWrittenByAnOlderEngineOpensUnderTheEmbeddedOne seals and captures a
// cell with the old release, then with the embedded engine on the SAME data
// root, then with the old release again. The chain must continue unbroken in
// both directions: a user who upgrades keeps their history, and a codeaf that
// is rolled back still reads what the newer one wrote.
func TestStoreWrittenByAnOlderEngineOpensUnderTheEmbeddedOne(t *testing.T) {
old := os.Getenv(oldEngineEnv)
if old == "" {
t.Skipf("%s not set", oldEngineEnv)
}
current, err := furrow.ResolveOwned()
if err != nil {
t.Skipf("no embedded engine: %v", err)
}
if current == old {
t.Skip("the embedded engine is the old engine")
}
ctx := context.Background()
dataRoot := t.TempDir()
c, err := cell.CreateIn(t.TempDir(), cell.Options{Class: cell.Sandboxed})
if err != nil {
t.Fatal(err)
}
engineOf := func(bin string) Engine {
return Engine{Binary: bin, DataRoot: dataRoot, Transport: Spawn{Binary: bin}}
}
note := filepath.Join(c.Root, "note.txt")
write := func(s string) {
t.Helper()
if err := os.WriteFile(note, []byte(s), 0o600); err != nil {
t.Fatal(err)
}
}

write("written by the old engine")
first, err := engineOf(old).Seal(ctx, c, TurnInfo{})
if err != nil {
t.Fatalf("old engine seal: %v", err)
}

write("written under the new engine")
second, err := engineOf(current).Seal(ctx, c, TurnInfo{})
if err != nil {
t.Fatalf("embedded engine could not seal into the old store: %v", err)
}
if second.Turn.Parent != first.Turn.ID {
t.Fatalf("chain broke across the upgrade: parent %q, want %q", second.Turn.Parent, first.Turn.ID)
}

snap, err := engineOf(current).Capture(ctx, c)
if err != nil || snap == "" {
t.Fatalf("embedded engine capture in the old store: %q, %v", snap, err)
}
write("scribbled over")
if err := engineOf(current).Restore(ctx, c, snap, []string{"note.txt"}); err != nil {
t.Fatalf("embedded engine restore: %v", err)
}
if got, _ := os.ReadFile(note); string(got) != "written under the new engine" {
t.Fatalf("restore gave %q", got)
}

write("written after rolling back")
third, err := engineOf(old).Seal(ctx, c, TurnInfo{})
if err != nil {
t.Fatalf("old engine could not seal into a store the newer engine wrote: %v", err)
}
if third.Turn.Parent != second.Turn.ID {
t.Fatalf("chain broke across the rollback: parent %q, want %q", third.Turn.Parent, second.Turn.ID)
}
}
16 changes: 8 additions & 8 deletions internal/furrowbin/pin.json
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
{
"repository": "Agent-Field/furrow",
"tag": "v0.2.0",
"version": "0.2.0",
"tag": "v0.3.3",
"version": "0.3.3",
"artifacts": {
"darwin-amd64": {
"asset": "furrow-darwin-amd64",
"sha256": "fc9ead1c78582086d05f859f354fac2ade8b28b43ea54a4e04f9f03a3fb92ed1"
"sha256": "a1b689f8863b578de10caef5d6cf5d09c4de1959b4f6256574e0e748687f36db"
},
"darwin-arm64": {
"asset": "furrow-darwin-arm64",
"sha256": "23c713db4544de5e169a902d6d42e581c205d7c85e3605fb28bbf1250bdd0c86"
"sha256": "6599f2e58bd2652610099956756de229ef2762cb4cf378a2c7f3533711e8cef1"
},
"linux-amd64": {
"asset": "furrow-linux-amd64",
"sha256": "be982dc8e991192d338b6daaa4f9a5765e7598eb3664b3dafd2f8e4834c4b508"
"sha256": "7ed29c0de43988c9c550426c8494b8a114c9b15a3a17a160a18d16c47d2eca4f"
},
"linux-arm64": {
"asset": "furrow-linux-arm64",
"sha256": "b9cecb657ee253116ebd7c1969e920d9b95cdd99267b2068e8e78b07277b1e2c"
"sha256": "4cdb22b14f11338ecab250a812bd2d25ff75aa6395eb5d7d6a0ff6c34c6c2acd"
},
"windows-amd64": {
"asset": "furrow-windows-amd64.exe",
"sha256": "327cc31320544e4c24f101cecc71ec7f68feae68921f7bb1ab1a6d165d0e01c7"
"sha256": "52d2223f1eb181cf4a3486bd6dfca906d99238ae92dbbe77c50ec955f91ed3a3"
},
"windows-arm64": {
"asset": "furrow-windows-arm64.exe",
"sha256": "f5435d6d38c87d001a008fd19db399dd8e722ca3044c2f236c3174b0a7827e77"
"sha256": "dc351ae8b48aee76fc70b142623b11a0b90da828000614aa3ced24017b3420f0"
}
}
}
Loading