fix(brain): context, brain_get and brain_read read through brainfs (#157, slice 2)
Option 1 of #157, slice 2. readExcerpt (brain_context), api.ReadNote (brain_get / read-after-write) and notes.ReadScoped (brain_read) read the Syncthing-shared brain by path. Under a symlink swap race each leaked an outside file hundreds of thousands of times in 1.5s, including brain_read, whose Lstat check was raced by the reopen-by-name; a FIFO blocked os.ReadFile. - All three read through brainfs (os.Root, regular files only, non-blocking open, type check on the handle). - brainfs.ReadRegularMax checks a size limit on the opened handle; notes keeps its ErrTooLarge. - New internal/brainfs/brainfstest: the shared swap-race harness (symlink and held-writer FIFO swappers, awaited before TempDir cleanup; AssertNoLeak / AssertNoHang) for this and later slices. Tests red first: each reader under a symlink-swap race and a held-writer FIFO race, plus static checks. Flipped: readExcerpt back to os.ReadFile is red. Refs #157 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/brainfs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -174,11 +175,17 @@ func UpdateNote(brainDir string, opts UpdateNoteOptions) (relPath, contentHash,
|
||||
// write primitive behind brain_get: the hash it returns equals the hash
|
||||
// brain_write / brain_update returned for the same bytes.
|
||||
func ReadNote(brainDir, relPath string) (fm map[string]string, body, contentHash string, err error) {
|
||||
_, abs, err := resolveWithin(brainDir, relPath)
|
||||
rel, _, err := resolveWithin(brainDir, relPath)
|
||||
if err != nil {
|
||||
return nil, "", "", err
|
||||
}
|
||||
raw, err := os.ReadFile(abs)
|
||||
// Through the brain root, regular files only (hyperguild#157).
|
||||
bfs, err := brainfs.Open(brainDir)
|
||||
if err != nil {
|
||||
return nil, "", "", fmt.Errorf("read note: %w", err)
|
||||
}
|
||||
defer func() { _ = bfs.Close() }()
|
||||
raw, err := bfs.ReadRegular(rel)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, "", "", fmt.Errorf("note %q does not exist", relPath)
|
||||
|
||||
Reference in New Issue
Block a user