Phase 0 -- Hardening: - Fix SQLITE_BUSY under concurrent writes by setting SetMaxOpenConns(1) and PRAGMA busy_timeout=5000 - Add comprehensive tests: concurrent read/write (10 goroutines), edge cases (unicode, null bytes, SQL injection, long keys), error paths (closed store, invalid paths, corrupt files), group isolation, upsert verification, WAL mode verification, ErrNotFound wrapping - Add benchmarks: Set, Get, GetAll (10K keys), file-backed Set Phase 1 -- TTL Support: - Add expires_at nullable column with schema migration for pre-TTL DBs - SetWithTTL(group, key, value, duration) stores keys that auto-expire - Lazy deletion on Get for expired keys - Background purge goroutine (configurable interval, default 60s) - Public PurgeExpired() method for manual cleanup - Count, GetAll, Render all exclude expired entries - Set clears TTL when overwriting a TTL key Coverage: 73.1% -> 90.9% (48 tests, 0 races) Co-Authored-By: Charon <developers@lethean.io>
1.1 KiB
1.1 KiB
CLAUDE.md
What This Is
SQLite key-value store wrapper with TTL support. Module: forge.lthn.ai/core/go-store
Commands
go test ./... # Run all tests
go test -v -run Name # Run single test
go test -race ./... # Race detector
go test -cover ./... # Coverage (target: 90%+)
go test -bench=. ./... # Benchmarks
Key API
st, _ := store.New(":memory:") // or store.New("/path/to/db")
defer st.Close()
st.Set("group", "key", "value") // no expiry
st.SetWithTTL("group", "key", "value", 5*time.Minute) // expires after TTL
val, _ := st.Get("group", "key") // lazy-deletes expired
st.Delete("group", "key")
st.DeleteGroup("group")
all, _ := st.GetAll("group") // excludes expired
n, _ := st.Count("group") // excludes expired
out, _ := st.Render(tmpl, "group") // excludes expired
removed, _ := st.PurgeExpired() // manual purge
Coding Standards
- UK English
go test ./...must pass before commit- Conventional commits:
type(scope): description - Co-Author:
Co-Authored-By: Virgil <virgil@lethean.io>