Documentation
¶
Overview ¶
Package core provides the shared engine that manages the knowledge graph, indexes, embedding, and persistence. Both the HTTP server and CLI thin client operate through this engine. The engine is safe for concurrent use via an internal RWMutex.
Package core provides the shared engine. write_session.go defines WriteSession, the batched-write API used inside Engine.WithWriteBatch closures.
Index ¶
- func ActiveBranch(dataDir string) string
- func AtomicWriteFile(path string, data []byte, perm os.FileMode) error
- func CheckFormatVersion(dataDir string) error
- func DeleteRef(dataDir, name string) error
- func IsContextLengthError(err error) bool
- func MigrateStore(cfgDir string, globalCfgDirs []string) error
- func ReadFormatVersion(dataDir string) (int, error)
- func ReadRef(dataDir, name string) (string, error)
- func RecordContent(n *graph.Node, contentFields []string) string
- func RecordContentFromFields(contentFields []string, fields map[string]any) string
- func RecordIndexText(n *graph.Node) string
- func RefsDir(dataDir string) string
- func SetActiveBranch(dataDir, name string) error
- func TruncHash(h string) string
- func ValidBranchName(name string) error
- func WriteFormatVersion(dataDir string) error
- func WriteRef(dataDir, name, hash string) error
- type Engine
- func (e *Engine) ApplyChunks(parentID string, pre *PreChunkResult, parentProps graph.Properties) int
- func (e *Engine) BM25Full() index.BM25Index
- func (e *Engine) BatchIndexWrites(fn func(*WriteSession)) error
- func (e *Engine) CheckDedup(nodeID string) (string, float64)
- func (e *Engine) Close() error
- func (e *Engine) CloseFiles() error
- func (e *Engine) CollCache() *index.BboltCollectionCache
- func (e *Engine) Config() config.Config
- func (e *Engine) EdgeCount() int
- func (e *Engine) EdgeStore() *graph.BboltEdgeStore
- func (e *Engine) Embedder() embed.Provider
- func (e *Engine) FlushAccess()
- func (e *Engine) Graph() *graph.Graph
- func (e *Engine) HeadHash() string
- func (e *Engine) HeadHashLocked() string
- func (e *Engine) IndexNode(nodeID, content string, vec []float32)
- func (e *Engine) JobStore() *jobs.Store
- func (e *Engine) LLM() llm.Provider
- func (e *Engine) Lock()
- func (e *Engine) MarkAccessDirty()
- func (e *Engine) NodeCount() int
- func (e *Engine) OpenFiles() error
- func (e *Engine) PreChunk(ctx context.Context, content, medium, summary string) *PreChunkResult
- func (e *Engine) PropIdx() index.PropertyIndex
- func (e *Engine) RLock()
- func (e *Engine) RUnlock()
- func (e *Engine) RebuildAllIndexes()
- func (e *Engine) Repair() *RepairResult
- func (e *Engine) Save(message string, actions ...graph.CommitAction) (*graph.Commit, error)
- func (e *Engine) SaveOrLog(message string, actions ...graph.CommitAction)
- func (e *Engine) SearchSnapshots() *SnapshotStore
- func (e *Engine) Searcher() *search.Tool
- func (e *Engine) SecIdx() *index.BboltSecondaryIndex
- func (e *Engine) SetContentProp(nodeID, key, content string)
- func (e *Engine) SetProp(nodeID, key string, val graph.Property)
- func (e *Engine) Store() *storage.Store
- func (e *Engine) SwapGraph(g *graph.Graph)
- func (e *Engine) TSIndex() *graph.TSIndex
- func (e *Engine) TryRLock() bool
- func (e *Engine) Unlock()
- func (e *Engine) Validate() *ValidationResult
- func (e *Engine) VecIdx() index.VectorIndex
- func (e *Engine) WithWriteBatch(message string, fn func(*WriteSession) (mutated bool, err error)) error
- func (e *Engine) WrapLLM(fn func(llm.Provider) llm.Provider)
- type EngineOption
- type PreChunkResult
- type RepairResult
- type SearchSnapshot
- type SnapshotStore
- type ValidateStats
- type ValidationResult
- type WriteSession
- func (ws *WriteSession) AddAction(a graph.CommitAction)
- func (ws *WriteSession) AddEdge(sourceID, targetID, edgeType string, weight float64, props graph.Properties) (*graph.Edge, error)
- func (ws *WriteSession) AddNode(props graph.Properties) *graph.Node
- func (ws *WriteSession) Graph() *graph.Graph
- func (ws *WriteSession) IndexNode(nodeID, content string, vec []float32)
- func (ws *WriteSession) PropIdx() index.PropertyIndex
- func (ws *WriteSession) SetContentProp(nodeID, key, content string)
- func (ws *WriteSession) SetProp(nodeID, key string, val graph.Property)
- func (ws *WriteSession) Tx() *bolt.Tx
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ActiveBranch ¶
ActiveBranch returns the name of the active branch.
func AtomicWriteFile ¶
AtomicWriteFile writes data to a file atomically via temp file + rename. The parent directory is fsynced after the rename so that a crash between the rename(2) syscall and the next sync cannot lose the directory entry change. POSIX requires this -- a fsync on the regular file does NOT make the rename durable.
func CheckFormatVersion ¶
CheckFormatVersion reads the store format version and enforces the boot-time compatibility gate. Behaviors by read value:
- v == 0 (no FORMAT file): treated as a fresh store. Writes the current version and returns nil.
- v == current: compatible. Returns nil.
- v < current: OLDER than current. Returns an error telling the user to run `gramaton migrate`. No auto-upgrade at boot by design (see feedback_ad_hoc_migrations). Migration paths call this function's peer, ReadFormatVersion, to inspect without enforcing.
- v > current: NEWER than the running binary. Returns an error asking the user to upgrade gramaton.
func IsContextLengthError ¶
IsContextLengthError reports whether an embedding error indicates the input exceeded the model's context window. Delegates to the chunking package which owns the detection logic.
func MigrateStore ¶
MigrateStore brings a store up to the current StoreFormatVersion. Called from the `gramaton migrate` CLI. Idempotent: safe to rerun.
Currently-supported upgrade path:
v0 -> v2 (fresh store that had no FORMAT file; no backfill needed) v1 -> v2 (D7 timestamp index backfill) v2 -> v2 (no-op)
Opens the engine via the migration-private skipFormatCheck path; the normal LoadEngine boot gate refuses v1 stores and this is the only codepath that bypasses it. The engine is closed before the FORMAT file is bumped so a crash between the two leaves FORMAT at the older version and a rerun re-migrates cleanly.
Collection-level defaults (clear_mode, curation) are intentionally NOT set here. Those fields arrive in Phase 4 of the temporal- queries build with read-time fallbacks; an explicit sweep costs complexity for no behavioral gain. If a future phase wants populated defaults for visibility, that phase owns its own sweep.
func ReadFormatVersion ¶
ReadFormatVersion reads the store format version from the FORMAT file in the data directory. Returns 0 if the file does not exist (new or pre-format-version store).
func RecordContent ¶
RecordContent returns the LLM/embedding-grade text representation of a node. For Memory records (content_full present), returns content_full unchanged. For collection items in schema'd collections, joins the field.<name> values for each name in contentFields in the declared order, newline-separated. Falls back to RecordIndexText output when contentFields is empty (the schemaless ad-hoc path).
Missing or empty fields named in contentFields are skipped -- not rendered as blank lines. Non-string field types named in contentFields would be skipped here, but schema validation rejects them at the collection-create boundary so that case shouldn't reach this helper.
func RecordContentFromFields ¶
RecordContentFromFields returns the LLM/embedding-grade text for a collection item being constructed from a fields map, before the item's graph node exists. Output matches RecordContent(n, contentFields) for any node built from these fields. Used by CollectionAdd / CollectionAddBatch at insert time, where the embedding must be computed outside the engine lock and the authoritative node is only created later under the lock.
When contentFields is empty, falls back to a wide concatenation of every string-typed value (schemaless / no-template path), parallel to RecordIndexText for finished nodes.
func RecordIndexText ¶
RecordIndexText returns the lexical-recall text representation of a node, for use by BM25 indexing and other "wide" text consumers. For Memory records (content_full present), returns content_full unchanged. For collection items (no content_full), concatenates every field.* string property with single-space separators -- a bag-of-words form suited to lexical recall, where users typing enum values like "P1" or "open" into search still surface hits.
Iteration order over field.* properties is non-deterministic (map iteration). Acceptable for BM25 (bag of words); callers needing deterministic order use RecordContent.
func SetActiveBranch ¶
SetActiveBranch sets the active branch.
func ValidBranchName ¶
ValidBranchName validates a branch name.
func WriteFormatVersion ¶
WriteFormatVersion writes the current store format version to the FORMAT file in the data directory.
Types ¶
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine holds the loaded graph state, indexes, and providers. All public methods are safe for concurrent use.
func LoadEngine ¶
LoadEngine loads config, storage, graph state, and rebuilds indexes. The embedder may be nil if no embedding provider is configured. Ollama auto-start is NOT performed -- the caller is responsible for ensuring the embedding provider is reachable.
If globalCfgDir is provided and differs from cfgDir, the config is loaded with fallback: store-specific config first, then global. This supports named stores that inherit the global config.
func LoadEngineWithOptions ¶
func LoadEngineWithOptions(cfgDir string, globalCfgDirs []string, opts []EngineOption) (*Engine, error)
LoadEngineWithOptions is like LoadEngine but accepts functional options for dependency injection. Options are applied after all default initialization is complete.
func (*Engine) ApplyChunks ¶
func (e *Engine) ApplyChunks(parentID string, pre *PreChunkResult, parentProps graph.Properties) int
ApplyChunks creates section/chunk nodes from pre. Caller must hold the engine write lock.
func (*Engine) BatchIndexWrites ¶
func (e *Engine) BatchIndexWrites(fn func(*WriteSession)) error
BatchIndexWrites executes fn within a single bbolt write transaction shared across all bbolt-backed indexes (PropIdx, BM25, SecIdx, EdgeStore). Use this when creating many nodes at once (e.g., observation extraction) to avoid per-node fsync overhead. Caller must hold the engine write lock.
Returns any error from the underlying bbolt transaction. A non-nil return means the entire batch was rolled back; index writes inside fn did not persist. Callers must check the error -- silently ignoring it loses every write inside the closure.
Prefer WithWriteBatch for write-phase callers that also need Lock + Save. BatchIndexWrites remains the right call for code paths that are already under the write lock and want to batch a sub-section of their work. fn receives a *WriteSession, matching the WithWriteBatch closure shape.
func (*Engine) CheckDedup ¶
CheckDedup checks if a node's embedding is too similar to existing records. Delegates to dedup.Check; the Engine method exists to provide the natural entry point and preserve the historical API. Caller must hold at least a read lock.
func (*Engine) Close ¶
Close releases resources held by the engine (bbolt DB, mmap files). Flushes buffered vectors and closes the bbolt database. Returns the first error encountered; all resources are closed regardless.
Equivalent to CloseFiles for terminal shutdown. After Close the engine struct still owns cfg/store/prov/opts but its file-backed state is gone; callers should not reuse it.
func (*Engine) CloseFiles ¶
CloseFiles releases just the file-backed resources (bbolt indexes, mmap vec idx, jobs store) and stops their dependent goroutines (job sweeper, snapshot eviction). Used by both terminal Close and the Restore lifecycle (where it is paired with a subsequent OpenFiles against the post-swap data directory). Caller MUST hold the engine write lock.
Returns the first error encountered; all resources are closed regardless. Idempotent: every field is nil-checked and re-nilled, so a second call is a no-op.
Drops in-memory state that depends on the closed file-backed resources (graph, searcher, headHash) so OpenFiles starts from a clean slate. cfg, store, prov, opts survive across CloseFiles.
func (*Engine) CollCache ¶
func (e *Engine) CollCache() *index.BboltCollectionCache
CollCache returns the collection membership cache. May be nil in tests that don't create one.
func (*Engine) EdgeStore ¶
func (e *Engine) EdgeStore() *graph.BboltEdgeStore
EdgeStore returns the engine's persistent edge store. Used by SwapGraph callers (BranchCheckout/Merge) to construct a replacement graph that shares the engine's BboltEdgeStore.
func (*Engine) FlushAccess ¶
func (e *Engine) FlushAccess()
FlushAccess saves the current graph state if access metadata is dirty. Acquires the write lock internally. Safe to call from a background goroutine.
Save failures are counted and logged with dedup: first failure at Warn, suppressed at Debug for runs 2-9, every 10th failure at Error with the consecutive count. A stuck disk under the 30s flusher would otherwise emit one Error log + full err every 30s indefinitely. Counter resets on the next success.
func (*Engine) Graph ¶
Graph returns the underlying graph. Callers must hold the appropriate lock via RLock/RUnlock or Lock/Unlock.
func (*Engine) HeadHash ¶
HeadHash returns the current HEAD commit hash. Acquires a read lock -- do NOT call while holding the write lock.
func (*Engine) HeadHashLocked ¶
HeadHashLocked returns the current HEAD commit hash. Caller must already hold at least a read lock.
func (*Engine) IndexNode ¶
IndexNode populates all indexes for a node already added to the graph. When vec is non-nil it is also written back as the embedding_full property -- the vector index is a derived structure and the property is the source of truth. The cross-index update is delegated to indexSet.applyToNode so a future index gets picked up automatically. Caller must hold the write lock.
func (*Engine) JobStore ¶
JobStore returns the engine's job store. F1 capture_batch and future async operations use this for tracking. Returns nil if the engine was constructed in a way that bypassed jobs init (test harnesses).
func (*Engine) Lock ¶
func (e *Engine) Lock()
Lock acquires a write lock. Use for write operations (capture, update, classify, delete, etc.). Exclusive -- blocks all other readers and writers.
func (*Engine) MarkAccessDirty ¶
func (e *Engine) MarkAccessDirty()
MarkAccessDirty records that access metadata has been modified in memory but not yet persisted. Caller must hold the write lock.
func (*Engine) OpenFiles ¶
OpenFiles opens the engine's file-backed resources (bbolt indexes, mmap vec index, jobs store) and rebuilds the dependent in-memory state (graph from HEAD, searcher subsystem, in-flight job recovery, background sweeper, search-snapshot store). EngineOptions retained from construction are re-applied so test-injected indexes/providers survive a reload.
Used during initial construction and after Restore swaps the data directory. Caller MUST hold the engine write lock and MUST have closed the prior file-backed state via CloseFiles first; openFiles trusts the relevant Engine fields to be nil.
On error, all partially-opened resources are closed before returning, so the engine's file-backed fields are guaranteed nil and a subsequent CloseFiles is a no-op.
func (*Engine) PreChunk ¶
func (e *Engine) PreChunk(ctx context.Context, content, medium, summary string) *PreChunkResult
PreChunk determines whether content needs splitting and pre-embeds the pieces. Runs OUTSIDE the engine lock (embedding is I/O-bound); call ApplyChunks with the result under the write lock. Returns nil when content fits in a single embedding.
func (*Engine) PropIdx ¶
func (e *Engine) PropIdx() index.PropertyIndex
PropIdx returns the property index.
func (*Engine) RLock ¶
func (e *Engine) RLock()
RLock acquires a read lock. Use for read operations (search, inspect, explore, etc.). Multiple readers can hold the lock concurrently.
func (*Engine) RebuildAllIndexes ¶
func (e *Engine) RebuildAllIndexes()
RebuildAllIndexes rebuilds all indexes from graph state and refreshes the searcher to point at them. Idempotent. Caller must hold the write lock.
func (*Engine) Repair ¶
func (e *Engine) Repair() *RepairResult
Repair fixes structural issues found by Validate. Caller must hold the write lock.
func (*Engine) Save ¶
Save commits the current graph state and updates HEAD and the active branch ref. Caller must hold the write lock. Clears the accessDirty flag since all in-memory state is now persisted.
Persists indexes (BM25, vector, property) alongside the commit so startup can skip expensive rebuilds.
actions is the optional D3 structured action descriptor list. Empty variadic = no structured actions (commit still filterable via Message-prefix matching for pre-D3 consumers). Cluster migration to explicit action emission lands incrementally per the Phase 3 build plan.
func (*Engine) SaveOrLog ¶
func (e *Engine) SaveOrLog(message string, actions ...graph.CommitAction)
SaveOrLog wraps Save for callers that have no meaningful path to surface a persistence failure (background flushes, fire-and-forget curation writes, mid-loop saves). Errors are logged at Error level with the message label so operators can see silent persistence failures that would otherwise vanish.
Callers that CAN handle the error (HTTP handlers returning 5xx, import operations that should abort) MUST use Save directly.
Caller must hold the write lock. Accepts variadic CommitAction values matching Save's signature so curation passes can emit per-record action descriptors alongside the cycle's batch save.
func (*Engine) SearchSnapshots ¶
func (e *Engine) SearchSnapshots() *SnapshotStore
SearchSnapshots returns the engine's search snapshot store. Used by api.Search to populate snapshots after a fresh query and to look them up on cursor-paginated calls. May be nil only if the engine was constructed in a way that bypassed standard init.
func (*Engine) SecIdx ¶
func (e *Engine) SecIdx() *index.BboltSecondaryIndex
SecIdx returns the secondary index (time, edge counts, field existence). May be nil in tests that don't create one.
func (*Engine) SetContentProp ¶
SetContentProp updates a string property and refreshes the BM25 index if the property is content_full. Use this instead of SetProp when changing content fields to keep BM25 in sync (D12: single BM25 layer, content_full only). Caller must hold the write lock.
func (*Engine) SetProp ¶
SetProp sets a property on a node and updates the property index. Caller must hold the write lock.
func (*Engine) SwapGraph ¶
SwapGraph replaces the engine's graph with g. The replacement is a single pointer assignment; the old graph becomes GC-eligible as soon as no one retains a reference. Caller MUST hold the write lock (Lock/Unlock).
This is the primitive for "load a new state off-lock, then apply under lock" -- callers construct a fresh *graph.Graph via graph.NewWithCapacity(cap, graph.WithEdgeStore(engine.EdgeStore())) + Load(store, hash) outside the lock, then take the write lock, call SwapGraph, write HEAD/refs, call RebuildAllIndexes, release. BranchCheckout/Merge use this to keep the expensive parse off-lock.
IMPORTANT: the new graph must share the engine's BboltEdgeStore. If you build it with the default graph.New() it gets a fresh MemoryEdgeStore and any subsequent edge writes silently bypass bbolt persistence. Use EdgeStore() to grab the engine's store and inject via graph.WithEdgeStore.
Incremental-commit state (lastNodeTreeRoot/lastEdgeTreeRoot) is carried on the graph itself and was set by Load, so subsequent saves on the swapped-in graph commit correctly.
func (*Engine) TSIndex ¶
TSIndex returns the commit-timestamp index (D7). Used by temporal queries (Phase 2+) and the `gramaton migrate` backfill path.
func (*Engine) TryRLock ¶
TryRLock attempts to acquire a read lock without blocking. Returns true on success (caller MUST RUnlock) and false if the write lock is held by any goroutine (including the caller -- RWMutex is not reentrant). Use when a background refresh should be skipped rather than blocked when the engine is in a write phase.
func (*Engine) Validate ¶
func (e *Engine) Validate() *ValidationResult
Validate checks the store for integrity issues. Caller must hold at least a read lock on the engine.
func (*Engine) VecIdx ¶
func (e *Engine) VecIdx() index.VectorIndex
VecIdx returns the vector index.
func (*Engine) WithWriteBatch ¶
func (e *Engine) WithWriteBatch(message string, fn func(*WriteSession) (mutated bool, err error)) error
WithWriteBatch runs fn under the engine write lock with bbolt index writes batched into a single transaction, then Saves under the label `message` when fn reports mutations.
Standardises the three-step write-phase recipe (Lock -> batched writes -> Save) so callers don't drift on error handling, logging, or the "skip save when nothing changed" gate. Caller MUST NOT hold the engine lock. Caller is responsible for short-circuiting *before* calling when there is no work to do -- WithWriteBatch always takes the write lock.
fn returns (mutated, err). When err is non-nil, Save is skipped and the error is wrapped with the message label. When mutated is false, Save is skipped (no-op commits waste bbolt fsync + HEAD writes). When both are clean, a single Save fires with the message as the commit label.
Logs batch_ms and save_ms at Info so lock-hold duration is observable per phase. fn receives a *WriteSession with the session's tx and companion caches; call ws.SetProp, ws.AddEdge, ws.IndexNode etc. inside to thread tx through the bbolt-backed indexes.
func (*Engine) WrapLLM ¶
WrapLLM replaces the engine's LLM provider with the value returned by fn (passed the current provider), then rebuilds the searcher subsystem so search-time consumers (reranker, decompose) pick up the new reference. No-op when the engine has no LLM configured.
Intended for one-time setup of middleware wrappers — e.g. wrapping with llm.Metered so every consumer records into the UsageTracker instead of bypassing it. Takes the write lock internally; safe at construction because no other callers hold it yet. Do NOT use at runtime with RPCs in flight — the wrap would block until every reader released, then the rebuild would invalidate their searcher references.
fn is invoked under the write lock. It MUST be fast and MUST NOT perform I/O (network calls, disk writes). Stick to struct composition / wrapper construction.
type EngineOption ¶
type EngineOption func(*Engine)
EngineOption configures an engine at construction time. Options are applied after default initialization, overriding config-derived values. This is the only supported way to inject dependencies -- the engine's wiring (indexes, embedder) is immutable after construction.
func WithEmbedder ¶
func WithEmbedder(p embed.Provider) EngineOption
WithEmbedder overrides the embedding provider. Use in tests to inject a mock embedder without requiring a real Ollama/API endpoint.
func WithLLM ¶
func WithLLM(p llm.Provider) EngineOption
WithLLM overrides the LLM provider. Use in tests to inject a mock LLM without requiring a real API key.
func WithVectorIndex ¶
func WithVectorIndex(v index.VectorIndex) EngineOption
WithVectorIndex overrides the vector index. Use in tests to inject an in-memory FlatIndex instead of the disk-backed MmapFlatIndex. When set, the engine skips creating/opening the mmap vector file.
type PreChunkResult ¶
PreChunkResult is an alias for chunking.Result, preserved so callers that reference the historical name continue to compile.
type RepairResult ¶
type RepairResult struct {
DanglingEdgesRemoved int `json:"dangling_edges_removed,omitempty"`
OrphanChunksRemoved int `json:"orphan_chunks_removed,omitempty"`
IndexesRebuilt bool `json:"indexes_rebuilt,omitempty"`
StaleEmbeddings int `json:"stale_embeddings,omitempty"`
Messages []string `json:"messages,omitempty"`
}
RepairResult holds the outcome of a store repair.
type SearchSnapshot ¶
type SearchSnapshot struct {
// QueryID is the unique handle for this snapshot. ULID-shaped
// so debugging and log correlation work like for any other
// node ID in the system.
QueryID string
// IDs are the matched record IDs in ranked order. The order is
// load-bearing -- pagination slices into this slice by index.
IDs []string
// Scores parallel IDs (Scores[i] is the score for IDs[i]).
// Stale relative to the live index by the time a paginated
// call slices the snapshot, but recorded for debugging /
// auditing. Scores are not re-computed on cursor pages.
Scores []float32
// Total is the count materialized into the snapshot. Equal to
// len(IDs); cached for response shape clarity.
Total int
// Truncated indicates the underlying ranked candidate set
// exceeded the snapshot's candidate cap. Callers should signal
// this in the response so agents know more results exist
// beyond the snapshot.
Truncated bool
// ExpiresAt is when this snapshot becomes invalid. Lazy
// eviction on Get + periodic sweep both honor this.
ExpiresAt time.Time
}
SearchSnapshot captures the result set of a search query at a point in time. Stores IDs + scores only -- record content is fetched fresh on each page response so modifications to a still-present record show up on subsequent reads. Deletions manifest as silently-missing records (page returns N-1).
Snapshots are short-lived (TTL configured at the store) and keyed by a ULID QueryID generated at creation time. Pagination cursor tokens encode (QueryID, start, end) into the snapshot.
type SnapshotStore ¶
type SnapshotStore struct {
// contains filtered or unexported fields
}
SnapshotStore caches recent search results so paginated calls slice into a stable matched-set without re-running the query. Eviction is periodic (background goroutine) plus lazy (on Get of an expired snapshot). Safe for concurrent use.
One store per engine; lifetime tied to engine lifetime. Caller must call Stop on shutdown to terminate the eviction goroutine cleanly.
func NewSnapshotStore ¶
func NewSnapshotStore(ttl time.Duration) *SnapshotStore
NewSnapshotStore creates a SnapshotStore with the given TTL and starts the background eviction loop. Caller must call Stop on shutdown.
func (*SnapshotStore) Get ¶
func (s *SnapshotStore) Get(queryID string) (*SearchSnapshot, bool)
Get returns the snapshot for queryID, or nil + false if missing or expired. Expired snapshots are removed on access (lazy eviction) so successive Gets after expiry don't repeatedly surface a doomed entry.
func (*SnapshotStore) Len ¶
func (s *SnapshotStore) Len() int
Len returns the number of currently-stored snapshots, including any that are expired but not yet swept. For tests and metrics.
func (*SnapshotStore) NewQueryID ¶
func (s *SnapshotStore) NewQueryID() string
NewQueryID mints a fresh ULID for use as a snapshot's QueryID. Exposed so callers can pre-mint the ID before populating the rest of the snapshot.
func (*SnapshotStore) Put ¶
func (s *SnapshotStore) Put(snap *SearchSnapshot)
Put stores a snapshot. If snap.ExpiresAt is the zero time, it's set from the store's TTL; tests can pre-set it for deterministic expiry behavior.
func (*SnapshotStore) Stop ¶
func (s *SnapshotStore) Stop()
Stop terminates the eviction goroutine and blocks until it exits. Idempotent; subsequent calls are no-ops.
type ValidateStats ¶
type ValidateStats struct {
Nodes int `json:"nodes"`
Edges int `json:"edges"`
Collections int `json:"collections"`
Chunks int `json:"chunks"`
Observations int `json:"observations"`
BM25Docs int `json:"bm25_docs"`
VecDocs int `json:"vec_docs"`
}
ValidateStats reports counts checked during validation.
type ValidationResult ¶
type ValidationResult struct {
Errors []string `json:"errors,omitempty"`
Warnings []string `json:"warnings,omitempty"`
Stats ValidateStats `json:"stats"`
}
ValidationResult holds the outcome of a store integrity check.
func (*ValidationResult) OK ¶
func (r *ValidationResult) OK() bool
OK returns true if no errors were found.
type WriteSession ¶
type WriteSession struct {
// contains filtered or unexported fields
}
WriteSession owns a shared bbolt transaction and the companion caches for one batched write phase. All mutations inside a session land under ws.tx; BM25 and EdgeStore changes accumulate in ws.bm25 / ws.edges and flush at session end.
Callers obtain a WriteSession from Engine.WithWriteBatch; non- batched callers continue to use Engine.SetProp/Graph.AddEdge/etc. directly (those open their own bbolt Update per call).
The fields are unexported; the type exposes caller-facing methods that mirror the engine's non-batched mutation API. See D40.
func (*WriteSession) AddAction ¶
func (ws *WriteSession) AddAction(a graph.CommitAction)
AddAction records a D3 structured action for the current batch. Callers emit one per record-scoped change (capture, resolve, collection_add, curation-touch-record, etc.). Duplicate actions are stored verbatim -- consumers that want dedup should filter at read time. Thread-safe only under the engine write lock, which WithWriteBatch already holds while fn runs.
func (*WriteSession) AddEdge ¶
func (ws *WriteSession) AddEdge(sourceID, targetID, edgeType string, weight float64, props graph.Properties) (*graph.Edge, error)
AddEdge creates a new edge in the graph via the session's tx + edge-batch cache.
func (*WriteSession) AddNode ¶
func (ws *WriteSession) AddNode(props graph.Properties) *graph.Node
AddNode creates a new node in the graph. Does NOT populate the indexes -- call IndexNode or the appropriate per-index add once the node's full property set is assembled.
func (*WriteSession) Graph ¶
func (ws *WriteSession) Graph() *graph.Graph
Graph returns the underlying graph for read-side access within the session. Read methods (GetNode, EdgesFrom, etc.) see the committed state plus in-memory changes made during this session.
func (*WriteSession) IndexNode ¶
func (ws *WriteSession) IndexNode(nodeID, content string, vec []float32)
IndexNode populates every index for a node via the session's tx + caches. Mirrors Engine.IndexNode.
func (*WriteSession) PropIdx ¶
func (ws *WriteSession) PropIdx() index.PropertyIndex
PropIdx returns the property index for callers that need to query by key during a write phase.
func (*WriteSession) SetContentProp ¶
func (ws *WriteSession) SetContentProp(nodeID, key, content string)
SetContentProp updates a string property and refreshes the BM25 index if the property is content_full. Mirrors Engine.SetContentProp.
func (*WriteSession) SetProp ¶
func (ws *WriteSession) SetProp(nodeID, key string, val graph.Property)
SetProp removes the prior value (if any) from the property index, writes the new value to the graph, and re-indexes -- all via the session's tx. Mirrors Engine.SetProp.
func (*WriteSession) Tx ¶
func (ws *WriteSession) Tx() *bolt.Tx
Tx returns the underlying bbolt transaction. Exposed for low-level callers that need direct tx access (e.g. backup/import walking raw records). Most callers use the higher-level WriteSession methods.