Skip to content

feat: add GraphCache β€” write-through MemoryStore with SQLite persistence#79

Merged
jamestexas merged 2 commits intomainfrom
feat/graph-cache
Mar 12, 2026
Merged

feat: add GraphCache β€” write-through MemoryStore with SQLite persistence#79
jamestexas merged 2 commits intomainfrom
feat/graph-cache

Conversation

@jamestexas
Copy link
Copy Markdown
Contributor

Summary

  • Adds graph.GraphCache β€” a thread-safe MemoryStore wrapper with automatic SQLite write-through persistence via ExportSQLite/ImportSQLite
  • Provides tree manipulation helpers: PutDir, PutFile, AppendChild, RemoveChild, ClearChildren, plus read methods and a Store() escape hatch for batch operations
  • Extracted from x-ray's SchemaCache pattern (808 LOC domain-specific cache) β€” this is the generic ~240-line core that any mache consumer can reuse

Motivation

x-ray's internal/api/schemacache.go mixes generic caching logic (mutex + MemoryStore + persist-on-write) with domain-specific code (URL keys, fingerprints, NavSections). Extracting the generic part into mache means:

  • x-ray can compose GraphCache with its domain logic instead of reimplementing the plumbing
  • Other consumers (hotsheaf, cairn, any tool caching structured data) get the same pattern for free

API

c := graph.NewGraphCache("/path/to/cache.db") // or "" for in-memory
c.PutDir("root", true)
c.PutFile("root/key", []byte("value"))
c.AppendChild("root", "root/key")

data, ok := c.GetData("root/key")       // read
children, ok := c.ListChildren("root")  // list

store := c.Store()  // escape hatch for batch ops
// ... mutate store directly ...
c.Persist()         // flush once

Test plan

  • 14 tests in graph/cache_test.go covering CRUD, SQLite persistence reload, dedup, concurrency, escape hatch
  • All existing graph/ tests still pass
  • Race detector clean (go test -race)
  • All pre-commit hooks pass (gofumpt, go vet, golangci-lint)

πŸ€– Generated with Claude Code

Generic cache extracted from x-ray's SchemaCache pattern. Wraps
MemoryStore with sync.RWMutex and automatic ExportSQLite on every
mutation. Provides tree manipulation helpers (PutDir, PutFile,
AppendChild, RemoveChild, ClearChildren) and a Store() escape
hatch for batch operations.

14 tests covering CRUD, SQLite reload, dedup, concurrency, and
the escape hatch pattern.
Batch acquires the write lock, calls the provided function with the
underlying MemoryStore, then persists once. This enables complex
operations (backup β†’ clear β†’ rebuild β†’ restore) to run atomically
without exposing intermediate state to concurrent readers, and with
a single SQLite write instead of N individual ExportSQLite calls.

Motivated by x-ray's SchemaCache.PutZones which does 30-50 store
operations under one lock β€” individual PutDir/PutFile/AppendChild
calls would break both atomicity and persistence efficiency.
@jamestexas jamestexas merged commit c4ece3d into main Mar 12, 2026
13 checks passed
@jamestexas jamestexas deleted the feat/graph-cache branch March 12, 2026 00:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant