core

package
v0.3.0-alpha.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 10, 2026 License: Apache-2.0 Imports: 25 Imported by: 0

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

Constants

This section is empty.

Variables

This section is empty.

Functions

func ActiveBranch

func ActiveBranch(dataDir string) string

ActiveBranch returns the name of the active branch.

func AtomicWriteFile

func AtomicWriteFile(path string, data []byte, perm os.FileMode) error

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

func CheckFormatVersion(dataDir string) error

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 DeleteRef

func DeleteRef(dataDir, name string) error

DeleteRef removes a branch ref.

func IsContextLengthError

func IsContextLengthError(err error) bool

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

func MigrateStore(cfgDir string, globalCfgDirs []string) error

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

func ReadFormatVersion(dataDir string) (int, error)

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 ReadRef

func ReadRef(dataDir, name string) (string, error)

ReadRef reads the commit hash for a named branch ref.

func RecordContent

func RecordContent(n *graph.Node, contentFields []string) string

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

func RecordContentFromFields(contentFields []string, fields map[string]any) string

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

func RecordIndexText(n *graph.Node) string

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 RefsDir

func RefsDir(dataDir string) string

RefsDir returns the refs directory for the given data directory.

func SetActiveBranch

func SetActiveBranch(dataDir, name string) error

SetActiveBranch sets the active branch.

func TruncHash

func TruncHash(h string) string

TruncHash returns the first 12 characters of a hash for display.

func ValidBranchName

func ValidBranchName(name string) error

ValidBranchName validates a branch name.

func WriteFormatVersion

func WriteFormatVersion(dataDir string) error

WriteFormatVersion writes the current store format version to the FORMAT file in the data directory.

func WriteRef

func WriteRef(dataDir, name, hash string) error

WriteRef writes a commit hash for a named branch ref.

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

func LoadEngine(cfgDir string, globalCfgDir ...string) (*Engine, error)

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) BM25Full

func (e *Engine) BM25Full() index.BM25Index

BM25Full returns the BM25 index for content_full.

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

func (e *Engine) CheckDedup(nodeID string) (string, float64)

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

func (e *Engine) Close() error

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

func (e *Engine) CloseFiles() error

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) Config

func (e *Engine) Config() config.Config

Config returns the engine's config. Safe for concurrent read.

func (*Engine) EdgeCount

func (e *Engine) EdgeCount() int

EdgeCount returns the number of edges. Acquires a read lock.

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) Embedder

func (e *Engine) Embedder() embed.Provider

Embedder returns the embedding provider (may be nil).

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

func (e *Engine) Graph() *graph.Graph

Graph returns the underlying graph. Callers must hold the appropriate lock via RLock/RUnlock or Lock/Unlock.

func (*Engine) HeadHash

func (e *Engine) HeadHash() string

HeadHash returns the current HEAD commit hash. Acquires a read lock -- do NOT call while holding the write lock.

func (*Engine) HeadHashLocked

func (e *Engine) HeadHashLocked() string

HeadHashLocked returns the current HEAD commit hash. Caller must already hold at least a read lock.

func (*Engine) IndexNode

func (e *Engine) IndexNode(nodeID, content string, vec []float32)

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

func (e *Engine) JobStore() *jobs.Store

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) LLM

func (e *Engine) LLM() llm.Provider

LLM returns the LLM provider (may be nil if not configured).

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) NodeCount

func (e *Engine) NodeCount() int

NodeCount returns the number of nodes. Acquires a read lock.

func (*Engine) OpenFiles

func (e *Engine) OpenFiles() error

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) RUnlock

func (e *Engine) RUnlock()

RUnlock releases the read lock.

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

func (e *Engine) Save(message string, actions ...graph.CommitAction) (*graph.Commit, error)

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) Searcher

func (e *Engine) Searcher() *search.Tool

Searcher returns the search tool.

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

func (e *Engine) SetContentProp(nodeID, key, content string)

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

func (e *Engine) SetProp(nodeID, key string, val graph.Property)

SetProp sets a property on a node and updates the property index. Caller must hold the write lock.

func (*Engine) Store

func (e *Engine) Store() *storage.Store

Store returns the storage backend.

func (*Engine) SwapGraph

func (e *Engine) SwapGraph(g *graph.Graph)

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

func (e *Engine) TSIndex() *graph.TSIndex

TSIndex returns the commit-timestamp index (D7). Used by temporal queries (Phase 2+) and the `gramaton migrate` backfill path.

func (*Engine) TryRLock

func (e *Engine) TryRLock() bool

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) Unlock

func (e *Engine) Unlock()

Unlock releases the write lock.

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

func (e *Engine) WrapLLM(fn func(llm.Provider) llm.Provider)

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

type PreChunkResult = chunking.Result

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL