Documentation
¶
Overview ¶
Package storage - AsyncEngine provides write-behind caching for eventual consistency.
AsyncEngine wraps a storage engine and provides:
- Immediate writes to in-memory cache (fast)
- Background writes to underlying engine (async)
- Reads check cache first, then engine (eventual consistency)
Trade-offs:
- Much faster writes (returns immediately)
- Reads may see stale data briefly (eventual consistency)
- Data loss risk if crash before flush (use with WAL for durability)
Package storage provides storage engine implementations for NornicDB.
BadgerEngine provides persistent disk-based storage using BadgerDB. It implements the Engine interface with full ACID transaction support.
Package storage provides storage engine implementations for NornicDB.
Package storage provides storage engine implementations for NornicDB.
Package storage provides storage engine implementations for NornicDB.
Package storage provides storage engine implementations for NornicDB.
Package storage provides storage engine implementations for NornicDB.
Package storage provides storage engine implementations for NornicDB.
Package storage provides storage engine implementations for NornicDB.
Package storage - Serialization helpers for BadgerDB.
Package storage provides storage engine implementations for NornicDB.
Package storage - BadgerDB transaction wrapper with ACID guarantees.
This file implements atomic transactions for BadgerDB with full constraint validation and rollback support.
Package storage provides composite engine for composite database support.
CompositeEngine implements the Engine interface by routing operations to multiple constituent databases and merging results transparently.
Package storage provides routing logic for composite engines.
This file implements query analysis and routing for composite databases, determining which constituents should be queried based on query patterns.
Package storage - Constraint validation when constraints are created.
Package storage provides edge provenance logging for NornicDB.
Edge provenance tracks the audit trail for edges - why they were created, when, what evidence supports them, and their lifecycle state.
Feature flag: NORNICDB_EDGE_PROVENANCE_ENABLED (enabled by default)
Usage:
store := NewEdgeMetaStore()
meta := EdgeMeta{
Src: "node-A",
Dst: "node-B",
Label: "relates_to",
Score: 0.85,
SignalType: "similarity",
}
store.Append(ctx, meta)
// Query history
history, _ := store.GetHistory(ctx, "node-A", "node-B", "relates_to")
Package storage provides storage implementations and data import/export functionality.
This file specifically handles Neo4j JSON import/export functionality, enabling NornicDB to interoperate with Neo4j databases through standard JSON export formats.
Supported Formats:
- Neo4j APOC JSON exports (nodes.json + relationships.json)
- Combined Neo4j export format (single JSON file)
- NornicDB native format with full fidelity
Key Features:
- Bidirectional Neo4j compatibility
- Bulk loading for performance
- Property type preservation
- Label and relationship type mapping
- Error handling and validation
Example Usage:
// Load from Neo4j APOC export
engine := storage.NewMemoryEngine()
err := storage.LoadFromNeo4jJSON(engine, "./neo4j-export/")
if err != nil {
log.Fatal(err)
}
// Load from combined export file
err = storage.LoadFromNeo4jExport(engine, "./data.json")
if err != nil {
log.Fatal(err)
}
// Export to Neo4j format
err = storage.SaveToNeo4jExport(engine, "./nornicdb-export.json")
if err != nil {
log.Fatal(err)
}
Neo4j APOC Export Format:
The APOC export format consists of two files:
- nodes.json: One JSON object per line, each representing a node
- relationships.json: One JSON object per line, each representing a relationship
Example nodes.json:
{"id":"0","labels":["Person"],"properties":{"name":"Alice","age":30}}
{"id":"1","labels":["Person"],"properties":{"name":"Bob","age":25}}
Example relationships.json:
{"id":"0","type":"KNOWS","startNode":"0","endNode":"1","properties":{"since":2020}}
Combined Export Format:
The combined format includes both nodes and relationships in a single JSON file:
{
"nodes": [...],
"relationships": [...]
}
Data Type Mapping:
Neo4j types are mapped to Go types as follows:
- String -> string
- Integer -> int64
- Float -> float64
- Boolean -> bool
- Array -> []interface{}
- Object -> map[string]interface{}
Performance:
- Bulk operations are used for efficient loading
- Streaming JSON parsing for large files
- Memory-efficient processing
- Progress reporting for large imports
ELI12 (Explain Like I'm 12):
Think of this like moving between different types of photo albums:
**Neo4j format**: Like a specific brand of photo album with a special way of organizing photos (nodes) and the connections between them (relationships).
**Loading**: Like taking photos from a Neo4j album and putting them into a NornicDB album, making sure each photo goes in the right place and keeps all its information.
**Exporting**: Like taking photos from a NornicDB album and organizing them in the Neo4j format so they can be used in Neo4j tools.
**Bulk operations**: Instead of moving photos one by one, we move whole pages at a time to make it much faster.
This lets you easily move your data between NornicDB and Neo4j!
Package storage provides storage engine implementations for NornicDB.
The storage package defines the Engine interface and provides multiple implementations:
- MemoryEngine: In-memory storage using BadgerDB's in-memory mode (for testing)
- BadgerEngine: Persistent disk-based storage
All storage engines are thread-safe and support concurrent operations.
Example Usage:
// Create in-memory storage (for testing)
engine := storage.NewMemoryEngine()
defer engine.Close()
// Create a node
node := &storage.Node{
ID: "user-001",
Labels: []string{"User"},
Properties: map[string]any{
"name": "Alice",
},
}
engine.CreateNode(node)
Package storage provides namespaced storage engine wrapper for multi-database support.
NamespacedEngine wraps any storage.Engine with automatic key prefixing for database isolation. This enables multiple logical databases (tenants) to share a single physical storage backend while maintaining complete data isolation.
Key Design:
- All node and edge IDs are prefixed with the namespace: "tenant_a:123" instead of "123"
- Queries only see data in the current namespace
- DROP DATABASE = delete all keys with namespace prefix
Thread Safety:
Delegates to underlying engine's thread safety guarantees.
Example:
inner := storage.NewBadgerEngine("./data")
tenantA := storage.NewNamespacedEngine(inner, "tenant_a")
// Creates node with ID "tenant_a:123" in BadgerDB
tenantA.CreateNode(&Node{ID: "123", Labels: []string{"Person"}})
// Only sees nodes with "tenant_a:" prefix
nodes, _ := tenantA.AllNodes()
Package storage provides per-node configuration for NornicDB inference.
Per-node config allows fine-grained control over edge materialization: - Pin list: edges to these targets never decay - Deny list: never create edges to these targets - Edge caps: maximum edges per node (in/out/total) - Per-label caps: limits on specific edge types - Trust level: affects confidence thresholds
Feature flags:
- NORNICDB_PER_NODE_CONFIG_ENABLED=true (enabled by default)
- NORNICDB_PER_NODE_CONFIG_AUTO_INTEGRATION_ENABLED=true (enabled by default)
Real-World Example 1: User preferences (social network)
// User wants max 50 friends, never connect to blocked users
store := storage.NewNodeConfigStore()
userConfig := storage.NewNodeConfig("user-alice")
userConfig.MaxOutEdges = 50 // Max 50 outgoing friendships
userConfig.DenyList = []string{"user-spammer", "user-troll"} // Blocked users
userConfig.PinList = []string{"user-bestfriend"} // Never decay this friendship
store.Set(userConfig)
// Later, inference engine checks before creating edge
if allowed, _ := store.IsEdgeAllowedWithReason("user-alice", "user-bob", "friend"); allowed {
db.CreateEdge("user-alice", "user-bob", "friend")
store.RecordEdgeCreation("user-alice", "user-bob") // Update count (now at 23/50)
}
Real-World Example 2: Document categorization limits (knowledge base)
// Document should have max 5 categories, but unlimited references
docConfig := storage.NewNodeConfig("doc-123")
docConfig.LabelConfigs = map[string]storage.LabelConfig{
"category": {MaxEdges: 5}, // Max 5 category tags
"references": {MaxEdges: 0}, // Unlimited references (0 = no limit)
"deprecated": {Disabled: true}, // Never create deprecated edges
}
store.Set(docConfig)
// Try to add 6th category - denied!
allowed, reason := store.IsEdgeAllowedWithReason("doc-123", "category-ai", "category")
// → (false, "label 'category' at max capacity (5/5)")
Real-World Example 3: Low-trust nodes (spam prevention)
// New users start with low trust - require higher confidence
newUserConfig := storage.NewNodeConfig("user-newbie")
newUserConfig.TrustLevel = storage.TrustLevelLow // Requires +20% confidence
newUserConfig.MaxOutEdges = 10 // Limited connections until trust increases
store.Set(newUserConfig)
// After user proves trustworthy, upgrade trust
if userIsActive && userNotSpamming {
newUserConfig.TrustLevel = storage.TrustLevelDefault
newUserConfig.MaxOutEdges = 100
store.Set(newUserConfig) // Update config
}
ELI12 (Explain Like I'm 12):
Per-node config is like house rules for each person:
**Pin List**: "These are my best friends - never unfriend them!"
- In NornicDB: Edges in pin list never decay, always kept
**Deny List**: "I never want to talk to these people"
- In NornicDB: Never create edges to denied nodes (like blocking someone)
**Edge Caps**: "I can only have 50 friends max"
- In NornicDB: Limits prevent one node from connecting to everything
**Trust Level**: "I just moved here, so teachers are extra careful with me"
- Low trust: Requires stronger evidence before creating edges
- High trust: Can create edges more easily
- Pinned: Always trust (like family members)
Think of it like a bouncer at a party:
- Deny list = banned from party
- Pin list = VIP, always allowed
- Max edges = party capacity (50 people max)
- Trust level = how strict the bouncer is checking IDs
Package storage provides receipt generation for mutation auditing.
Package storage schema management for constraints and indexes.
This file implements Neo4j-compatible schema management including:
- Unique constraints
- Property indexes (single and composite)
- Range indexes (for efficient range queries)
- Full-text indexes
- Vector indexes
Schema definitions are stored in memory and enforced during node operations.
Package storage - Transaction types shared between storage implementations.
This file defines shared transaction types used by BadgerTransaction. All transactions in NornicDB use Badger's native transaction system which provides real ACID guarantees through the Write-Ahead Log (WAL).
ACID Guarantees ¶
Transactions provide:
- Atomicity: All operations commit together or none do
- Consistency: Constraints validated before commit
- Isolation: Changes invisible until commit
- Durability: WAL ensures persistence even on crash
Usage ¶
All engines (including MemoryEngine) use BadgerTransaction:
engine := storage.NewMemoryEngine() // or NewBadgerEngine()
tx, err := engine.BeginTransaction()
if err != nil {
return err
}
defer tx.Rollback() // Rollback if not committed
tx.CreateNode(&Node{ID: "n1", Labels: []string{"Person"}})
tx.CreateNode(&Node{ID: "n2", Labels: []string{"Person"}})
return tx.Commit() // Atomic - both succeed or both fail
Package storage provides the storage engine interface and implementations for NornicDB.
The storage layer is designed for Neo4j compatibility while adding NornicDB-specific extensions for memory decay, vector embeddings, and automatic relationship inference.
Design Principles:
- Neo4j JSON export/import compatibility
- Testability through dependency injection
- Thread-safe implementations
- Property graph model (labeled property graph)
Example Usage:
// Create storage engine
engine := storage.NewMemoryEngine()
defer engine.Close()
// Create nodes
node := &storage.Node{
ID: storage.NodeID("user-123"),
Labels: []string{"User", "Person"},
Properties: map[string]any{
"name": "Alice",
"email": "alice@example.com",
},
CreatedAt: time.Now(),
}
engine.CreateNode(node)
// Create relationships
edge := &storage.Edge{
ID: storage.EdgeID("follows-1"),
StartNode: storage.NodeID("user-123"),
EndNode: storage.NodeID("user-456"),
Type: "FOLLOWS",
CreatedAt: time.Now(),
}
engine.CreateEdge(edge)
// Export to Neo4j format
nodes, _ := engine.AllNodes()
edges, _ := engine.AllEdges()
export := storage.ToNeo4jExport(nodes, edges)
// Save as JSON
data, _ := json.MarshalIndent(export, "", " ")
os.WriteFile("graph-export.json", data, 0644)
Package storage provides write-ahead logging for NornicDB durability.
WAL (Write-Ahead Logging) ensures crash recovery by logging all mutations before they are applied to the storage engine. Combined with periodic snapshots, this provides:
- Durability: No data loss on crash
- Recovery: Restore state from snapshot + WAL replay
- Audit trail: Complete history of all mutations
Feature flag: NORNICDB_WAL_ENABLED (enabled by default)
Usage:
// Create WAL-backed storage
engine := NewMemoryEngine()
wal, err := NewWAL("/path/to/wal", nil)
walEngine := NewWALEngine(engine, wal)
// Operations are logged before execution
walEngine.CreateNode(&Node{ID: "n1", ...})
// Create periodic snapshots
snapshot, err := wal.CreateSnapshot(engine)
wal.SaveSnapshot(snapshot, "/path/to/snapshot.json")
// Recovery after crash
engine, err = RecoverFromWAL("/path/to/wal", "/path/to/snapshot.json")
Package storage provides write-ahead logging for NornicDB durability.
Package storage provides write-ahead logging for NornicDB durability.
Index ¶
- Constants
- Variables
- func CollectEdgeTypes(ctx context.Context, engine Engine) ([]string, error)
- func CollectLabels(ctx context.Context, engine Engine) ([]string, error)
- func CountNodesWithLabel(ctx context.Context, engine Engine, label string) (int64, error)
- func EnsureDatabasePrefix(dbName, id string) string
- func FromNeo4jExport(export *Neo4jExport) ([]*Node, []*Edge)
- func GenericSaveToNeo4jExport(engine ExportableEngine, path string) error
- func GetEntryTxID(entry WALEntry) string
- func LoadFromNeo4jExport(engine Engine, path string) error
- func LoadFromNeo4jJSON(engine Engine, dir string) error
- func NodeNeedsEmbedding(node *Node) bool
- func ParseDatabasePrefix(id string) (db string, unprefixed string, ok bool)
- func PruneOldSnapshotFiles(dir string, cfg *WALConfig) error
- func RecoverFromWALWithResult(walDir, snapshotPath string) (*MemoryEngine, ReplayResult, error)
- func RecoverWithTransactions(walDir, snapshotPath string) (*MemoryEngine, *TransactionRecoveryResult, error)
- func RefreshUniqueConstraintValuesForEngine(engine Engine, schema *SchemaManager) error
- func ReplayWALEntry(engine Engine, entry WALEntry) error
- func ResetGlobalEdgeMetaStore()
- func ResetGlobalNodeConfigStore()
- func SaveSnapshot(snapshot *Snapshot, path string) error
- func SaveToNeo4jExport(engine Engine, path string) error
- func SetStorageSerializer(serializer StorageSerializer) error
- func StreamEdgesWithFallback(ctx context.Context, engine Engine, chunkSize int, fn EdgeVisitor) error
- func StreamNodesWithFallback(ctx context.Context, engine Engine, chunkSize int, fn NodeVisitor) error
- func StripDatabasePrefix(dbName, id string) string
- func UndoWALEntry(engine Engine, entry WALEntry) error
- func ValidateConstraintContractOnCreationForEngine(engine Engine, contract ConstraintContract) error
- func ValidateConstraintOnCreationForEngine(engine Engine, c Constraint) error
- func ValidatePropertyType(value interface{}, expectedType PropertyType) error
- func ValidatePropertyTypeConstraintOnCreationForEngine(engine Engine, ptc PropertyTypeConstraint) error
- type AsyncEngine
- func (ae *AsyncEngine) AddToPendingEmbeddings(nodeID NodeID)
- func (ae *AsyncEngine) AllEdges() ([]*Edge, error)
- func (ae *AsyncEngine) AllNodes() ([]*Node, error)
- func (ae *AsyncEngine) BatchGetNodes(ids []NodeID) (map[NodeID]*Node, error)
- func (ae *AsyncEngine) BulkCreateEdges(edges []*Edge) error
- func (ae *AsyncEngine) BulkCreateNodes(nodes []*Node) error
- func (ae *AsyncEngine) BulkDeleteEdges(ids []EdgeID) error
- func (ae *AsyncEngine) BulkDeleteNodes(ids []NodeID) error
- func (ae *AsyncEngine) Close() error
- func (ae *AsyncEngine) CreateEdge(edge *Edge) error
- func (ae *AsyncEngine) CreateNode(node *Node) (NodeID, error)
- func (ae *AsyncEngine) DeleteByPrefix(prefix string) (nodesDeleted int64, edgesDeleted int64, err error)
- func (ae *AsyncEngine) DeleteEdge(id EdgeID) error
- func (ae *AsyncEngine) DeleteNode(id NodeID) error
- func (ae *AsyncEngine) EdgeCount() (int64, error)
- func (ae *AsyncEngine) EdgeCountByPrefix(prefix string) (int64, error)
- func (ae *AsyncEngine) FindNodeNeedingEmbedding() *Node
- func (ae *AsyncEngine) Flush() error
- func (ae *AsyncEngine) FlushWithResult() FlushResult
- func (ae *AsyncEngine) ForEachNodeIDByLabel(label string, visit func(NodeID) bool) error
- func (ae *AsyncEngine) GetAllNodes() []*Node
- func (ae *AsyncEngine) GetEdge(id EdgeID) (*Edge, error)
- func (ae *AsyncEngine) GetEdgeBetween(startID, endID NodeID, edgeType string) *Edge
- func (ae *AsyncEngine) GetEdgeCurrentHead(id EdgeID) (MVCCHead, error)
- func (ae *AsyncEngine) GetEdgeLatestEffective(id EdgeID) (*Edge, error)
- func (ae *AsyncEngine) GetEdgeLatestVisible(id EdgeID) (*Edge, error)
- func (ae *AsyncEngine) GetEdgeVisibleAt(id EdgeID, version MVCCVersion) (*Edge, error)
- func (ae *AsyncEngine) GetEdgesBetween(startID, endID NodeID) ([]*Edge, error)
- func (ae *AsyncEngine) GetEdgesBetweenVisibleAt(startID, endID NodeID, version MVCCVersion) ([]*Edge, error)
- func (ae *AsyncEngine) GetEdgesByType(edgeType string) ([]*Edge, error)
- func (ae *AsyncEngine) GetEdgesByTypeVisibleAt(edgeType string, version MVCCVersion) ([]*Edge, error)
- func (ae *AsyncEngine) GetEngine() Engine
- func (ae *AsyncEngine) GetFirstNodeByLabel(label string) (*Node, error)
- func (ae *AsyncEngine) GetInDegree(nodeID NodeID) int
- func (ae *AsyncEngine) GetIncomingEdges(nodeID NodeID) ([]*Edge, error)
- func (e *AsyncEngine) GetInnerEngine() Engine
- func (ae *AsyncEngine) GetNode(id NodeID) (*Node, error)
- func (ae *AsyncEngine) GetNodeCurrentHead(id NodeID) (MVCCHead, error)
- func (ae *AsyncEngine) GetNodeLatestEffective(id NodeID) (*Node, error)
- func (ae *AsyncEngine) GetNodeLatestVisible(id NodeID) (*Node, error)
- func (ae *AsyncEngine) GetNodeVisibleAt(id NodeID, version MVCCVersion) (*Node, error)
- func (ae *AsyncEngine) GetNodesByLabel(label string) ([]*Node, error)
- func (ae *AsyncEngine) GetNodesByLabelVisibleAt(label string, version MVCCVersion) ([]*Node, error)
- func (ae *AsyncEngine) GetOutDegree(nodeID NodeID) int
- func (ae *AsyncEngine) GetOutgoingEdges(nodeID NodeID) ([]*Edge, error)
- func (ae *AsyncEngine) GetSchema() *SchemaManager
- func (ae *AsyncEngine) GetSchemaForNamespace(namespace string) *SchemaManager
- func (ae *AsyncEngine) GetUnderlying() Engine
- func (ae *AsyncEngine) HasPendingWrites() bool
- func (ae *AsyncEngine) HoldFlush() func()
- func (ae *AsyncEngine) IsCurrentTemporalNode(node *Node, asOf time.Time) (bool, error)
- func (ae *AsyncEngine) IterateNodes(fn func(*Node) bool) error
- func (ae *AsyncEngine) LastWriteTime() time.Time
- func (ae *AsyncEngine) LifecycleStatus() map[string]interface{}
- func (ae *AsyncEngine) ListNamespaces() []string
- func (ae *AsyncEngine) MarkNodeEmbedded(nodeID NodeID)
- func (ae *AsyncEngine) NodeCount() (int64, error)
- func (ae *AsyncEngine) NodeCountByPrefix(prefix string) (int64, error)
- func (ae *AsyncEngine) OnEdgeCreated(callback EdgeEventCallback)
- func (ae *AsyncEngine) OnEdgeDeleted(callback EdgeDeleteCallback)
- func (ae *AsyncEngine) OnEdgeUpdated(callback EdgeEventCallback)
- func (ae *AsyncEngine) OnNodeCreated(callback NodeEventCallback)
- func (ae *AsyncEngine) OnNodeDeleted(callback NodeDeleteCallback)
- func (ae *AsyncEngine) OnNodeUpdated(callback NodeEventCallback)
- func (ae *AsyncEngine) PauseLifecycle()
- func (ae *AsyncEngine) PendingEmbeddingsCount() int
- func (ae *AsyncEngine) PruneMVCCVersions(ctx context.Context, opts MVCCPruneOptions) (int64, error)
- func (ae *AsyncEngine) PruneTemporalHistory(ctx context.Context, opts TemporalPruneOptions) (int64, error)
- func (ae *AsyncEngine) RebuildMVCCHeads(ctx context.Context) error
- func (ae *AsyncEngine) RebuildTemporalIndexes(ctx context.Context) error
- func (ae *AsyncEngine) RefreshPendingEmbeddingsIndex() int
- func (ae *AsyncEngine) RegisterSnapshotReader(info SnapshotReaderInfo) func()
- func (ae *AsyncEngine) ResumeLifecycle()
- func (ae *AsyncEngine) SetLifecycleSchedule(interval time.Duration) error
- func (ae *AsyncEngine) Stats() (pendingWrites, totalFlushes int64)
- func (ae *AsyncEngine) StreamEdges(ctx context.Context, fn func(edge *Edge) error) error
- func (ae *AsyncEngine) StreamNodeChunks(ctx context.Context, chunkSize int, fn func(nodes []*Node) error) error
- func (ae *AsyncEngine) StreamNodes(ctx context.Context, fn func(node *Node) error) error
- func (ae *AsyncEngine) StreamNodesByPrefix(ctx context.Context, prefix string, fn func(node *Node) error) error
- func (ae *AsyncEngine) TopLifecycleDebtKeys(limit int) []MVCCLifecycleDebtKey
- func (ae *AsyncEngine) TriggerPruneNow(ctx context.Context) error
- func (ae *AsyncEngine) UpdateEdge(edge *Edge) error
- func (ae *AsyncEngine) UpdateNode(node *Node) error
- func (ae *AsyncEngine) UpdateNodeEmbedding(node *Node) error
- type AsyncEngineConfig
- type BadgerEngine
- func (b *BadgerEngine) AddToPendingEmbeddings(nodeID NodeID)
- func (b *BadgerEngine) AllEdges() ([]*Edge, error)
- func (b *BadgerEngine) AllNodes() ([]*Node, error)
- func (b *BadgerEngine) AppendEdgeTombstone(id EdgeID, version MVCCVersion) error
- func (b *BadgerEngine) AppendEdgeVersion(edge *Edge, version MVCCVersion) error
- func (b *BadgerEngine) AppendNodeTombstone(id NodeID, version MVCCVersion) error
- func (b *BadgerEngine) AppendNodeVersion(node *Node, version MVCCVersion) error
- func (b *BadgerEngine) Backup(path string) error
- func (b *BadgerEngine) BatchGetNodes(ids []NodeID) (map[NodeID]*Node, error)
- func (b *BadgerEngine) BatchGetNodesLatestVisible(ids []NodeID) (map[NodeID]*Node, error)
- func (b *BadgerEngine) BeginTransaction() (*BadgerTransaction, error)
- func (b *BadgerEngine) BulkCreateEdges(edges []*Edge) error
- func (b *BadgerEngine) BulkCreateNodes(nodes []*Node) error
- func (b *BadgerEngine) BulkDeleteEdges(ids []EdgeID) error
- func (b *BadgerEngine) BulkDeleteNodes(ids []NodeID) error
- func (b *BadgerEngine) ClearAllEmbeddings() (int, error)
- func (b *BadgerEngine) ClearAllEmbeddingsForPrefix(idPrefix string) (int, error)
- func (b *BadgerEngine) Close() error
- func (b *BadgerEngine) CreateEdge(edge *Edge) error
- func (b *BadgerEngine) CreateNode(node *Node) (NodeID, error)
- func (b *BadgerEngine) DataDirFreeSpace() (int64, error)
- func (b *BadgerEngine) DeleteByPrefix(prefix string) (nodesDeleted int64, edgesDeleted int64, err error)
- func (b *BadgerEngine) DeleteEdge(id EdgeID) error
- func (b *BadgerEngine) DeleteMVCCVersion(ctx context.Context, logicalKey []byte, version MVCCVersion) error
- func (b *BadgerEngine) DeleteNode(id NodeID) error
- func (b *BadgerEngine) EdgeCount() (int64, error)
- func (b *BadgerEngine) EdgeCountByPrefix(prefix string) (int64, error)
- func (b *BadgerEngine) FindNodeNeedingEmbedding() *Node
- func (b *BadgerEngine) ForEachNodeIDByLabel(label string, visit func(NodeID) bool) error
- func (b *BadgerEngine) GetAllNodes() []*Node
- func (b *BadgerEngine) GetEdge(id EdgeID) (*Edge, error)
- func (b *BadgerEngine) GetEdgeBetween(source, target NodeID, edgeType string) *Edge
- func (b *BadgerEngine) GetEdgeCurrentHead(id EdgeID) (MVCCHead, error)
- func (b *BadgerEngine) GetEdgeLatestVisible(id EdgeID) (*Edge, error)
- func (b *BadgerEngine) GetEdgeVisibleAt(id EdgeID, version MVCCVersion) (*Edge, error)
- func (b *BadgerEngine) GetEdgesBetween(startID, endID NodeID) ([]*Edge, error)
- func (b *BadgerEngine) GetEdgesBetweenVisibleAt(startID, endID NodeID, version MVCCVersion) ([]*Edge, error)
- func (b *BadgerEngine) GetEdgesByType(edgeType string) ([]*Edge, error)
- func (b *BadgerEngine) GetEdgesByTypeVisibleAt(edgeType string, version MVCCVersion) ([]*Edge, error)
- func (b *BadgerEngine) GetFirstNodeByLabel(label string) (*Node, error)
- func (b *BadgerEngine) GetInDegree(nodeID NodeID) int
- func (b *BadgerEngine) GetIncomingEdges(nodeID NodeID) ([]*Edge, error)
- func (b *BadgerEngine) GetNode(id NodeID) (*Node, error)
- func (b *BadgerEngine) GetNodeCurrentHead(id NodeID) (MVCCHead, error)
- func (b *BadgerEngine) GetNodeLatestVisible(id NodeID) (*Node, error)
- func (b *BadgerEngine) GetNodeVisibleAt(id NodeID, version MVCCVersion) (*Node, error)
- func (b *BadgerEngine) GetNodesByLabel(label string) ([]*Node, error)
- func (b *BadgerEngine) GetNodesByLabelVisibleAt(label string, version MVCCVersion) ([]*Node, error)
- func (b *BadgerEngine) GetOutDegree(nodeID NodeID) int
- func (b *BadgerEngine) GetOutgoingEdges(nodeID NodeID) ([]*Edge, error)
- func (b *BadgerEngine) GetSchema() *SchemaManager
- func (b *BadgerEngine) GetSchemaForNamespace(namespace string) *SchemaManager
- func (b *BadgerEngine) GetTemporalNodeAsOfInNamespace(namespace, label, keyProp string, keyValue interface{}, ...) (*Node, error)
- func (b *BadgerEngine) HasLabelBatch(ids []NodeID, label string) (map[NodeID]bool, error)
- func (b *BadgerEngine) InvalidateEdgeTypeCache()
- func (b *BadgerEngine) InvalidateEdgeTypeCacheForType(edgeType string)
- func (b *BadgerEngine) InvalidatePendingEmbeddingsIndex()
- func (b *BadgerEngine) IsCurrentTemporalNode(node *Node, asOf time.Time) (bool, error)
- func (b *BadgerEngine) IsCurrentTemporalNodeInNamespace(namespace string, node *Node, asOf time.Time) (bool, error)
- func (b *BadgerEngine) IsInMemory() bool
- func (b *BadgerEngine) IterateLatestVisibleEdges(yield func(*Edge) error) error
- func (b *BadgerEngine) IterateLatestVisibleNodes(yield func(*Node) error) error
- func (b *BadgerEngine) IterateMVCCHeads(ctx context.Context, yield func(logicalKey []byte, head MVCCHead) error) error
- func (b *BadgerEngine) IterateMVCCVersions(ctx context.Context, logicalKey []byte, ...) error
- func (b *BadgerEngine) IterateNodes(fn func(*Node) bool) error
- func (b *BadgerEngine) LifecycleStatus() map[string]interface{}
- func (b *BadgerEngine) ListNamespaces() []string
- func (b *BadgerEngine) MarkNodeEmbedded(nodeID NodeID)
- func (b *BadgerEngine) NodeCount() (int64, error)
- func (b *BadgerEngine) NodeCountByPrefix(prefix string) (int64, error)
- func (b *BadgerEngine) OnEdgeCreated(callback EdgeEventCallback)
- func (b *BadgerEngine) OnEdgeDeleted(callback EdgeDeleteCallback)
- func (b *BadgerEngine) OnEdgeUpdated(callback EdgeEventCallback)
- func (b *BadgerEngine) OnNodeCreated(callback NodeEventCallback)
- func (b *BadgerEngine) OnNodeDeleted(callback NodeDeleteCallback)
- func (b *BadgerEngine) OnNodeUpdated(callback NodeEventCallback)
- func (b *BadgerEngine) PauseLifecycle()
- func (b *BadgerEngine) PendingEmbeddingsCount() int
- func (b *BadgerEngine) PruneMVCCVersions(ctx context.Context, opts MVCCPruneOptions) (int64, error)
- func (b *BadgerEngine) PruneTemporalHistory(ctx context.Context, opts TemporalPruneOptions) (int64, error)
- func (b *BadgerEngine) ReadMVCCHead(ctx context.Context, logicalKey []byte) (MVCCHead, error)
- func (b *BadgerEngine) RebuildMVCCHeads(ctx context.Context) error
- func (b *BadgerEngine) RebuildTemporalIndexes(ctx context.Context) error
- func (b *BadgerEngine) RefreshPendingEmbeddingsIndex() int
- func (b *BadgerEngine) RegisterSnapshotReader(info SnapshotReaderInfo) func()
- func (b *BadgerEngine) ResumeLifecycle()
- func (b *BadgerEngine) RunGC() error
- func (b *BadgerEngine) SetLifecycleController(controller MVCCLifecycleController)
- func (b *BadgerEngine) SetLifecycleSchedule(interval time.Duration) error
- func (b *BadgerEngine) Size() (lsm, vlog int64)
- func (b *BadgerEngine) StartLifecycleManager(ctx context.Context)
- func (b *BadgerEngine) StreamEdges(ctx context.Context, fn func(edge *Edge) error) error
- func (b *BadgerEngine) StreamNodeChunks(ctx context.Context, chunkSize int, fn func(nodes []*Node) error) error
- func (b *BadgerEngine) StreamNodes(ctx context.Context, fn func(node *Node) error) error
- func (b *BadgerEngine) StreamNodesByPrefix(ctx context.Context, prefix string, fn func(node *Node) error) error
- func (b *BadgerEngine) Sync() error
- func (b *BadgerEngine) TopLifecycleDebtKeys(limit int) []MVCCLifecycleDebtKey
- func (b *BadgerEngine) TriggerPruneNow(ctx context.Context) error
- func (b *BadgerEngine) UpdateEdge(edge *Edge) error
- func (b *BadgerEngine) UpdateEdgeCurrentHead(id EdgeID, version MVCCVersion, tombstoned bool) error
- func (b *BadgerEngine) UpdateNode(node *Node) error
- func (b *BadgerEngine) UpdateNodeCurrentHead(id NodeID, version MVCCVersion, tombstoned bool) error
- func (b *BadgerEngine) UpdateNodeEmbedding(node *Node) error
- func (b *BadgerEngine) ValidateConstraintOnCreation(c Constraint) error
- func (b *BadgerEngine) ValidatePropertyTypeConstraintOnCreation(ptc PropertyTypeConstraint) error
- func (b *BadgerEngine) ValidateRelationshipConstraint(rc RelationshipConstraint) error
- func (b *BadgerEngine) WriteMVCCHead(ctx context.Context, logicalKey []byte, head MVCCHead) error
- type BadgerOptions
- type BadgerTransaction
- func (tx *BadgerTransaction) AllNodes() ([]*Node, error)
- func (tx *BadgerTransaction) Commit() error
- func (tx *BadgerTransaction) CreateEdge(edge *Edge) error
- func (tx *BadgerTransaction) CreateNode(node *Node) (NodeID, error)
- func (tx *BadgerTransaction) DeleteEdge(edgeID EdgeID) error
- func (tx *BadgerTransaction) DeleteNode(nodeID NodeID) error
- func (tx *BadgerTransaction) GetAllNodes() []*Node
- func (tx *BadgerTransaction) GetEdge(edgeID EdgeID) (*Edge, error)
- func (tx *BadgerTransaction) GetEdgeBetween(startID, endID NodeID, edgeType string) *Edge
- func (tx *BadgerTransaction) GetEdgesBetween(startID, endID NodeID) ([]*Edge, error)
- func (tx *BadgerTransaction) GetEdgesByType(edgeType string) ([]*Edge, error)
- func (tx *BadgerTransaction) GetFirstNodeByLabel(label string) (*Node, error)
- func (tx *BadgerTransaction) GetIncomingEdges(nodeID NodeID) ([]*Edge, error)
- func (tx *BadgerTransaction) GetMetadata() map[string]interface{}
- func (tx *BadgerTransaction) GetNode(nodeID NodeID) (*Node, error)
- func (tx *BadgerTransaction) GetNodesByLabel(label string) ([]*Node, error)
- func (tx *BadgerTransaction) GetOutgoingEdges(nodeID NodeID) ([]*Edge, error)
- func (tx *BadgerTransaction) HasPendingNodeMutations() bool
- func (tx *BadgerTransaction) IsActive() bool
- func (tx *BadgerTransaction) OperationCount() int
- func (tx *BadgerTransaction) Rollback() error
- func (tx *BadgerTransaction) SetDeferredConstraintValidation(deferValidation bool) error
- func (tx *BadgerTransaction) SetMetadata(metadata map[string]interface{}) error
- func (tx *BadgerTransaction) SetSkipCreateExistenceCheck(skip bool) error
- func (tx *BadgerTransaction) UpdateEdge(edge *Edge) error
- func (tx *BadgerTransaction) UpdateNode(node *Node) error
- type BatchWriter
- func (b *BatchWriter) AppendDelete(op OperationType, id string) error
- func (b *BatchWriter) AppendEdge(op OperationType, edge *Edge) error
- func (b *BatchWriter) AppendNode(op OperationType, node *Node) error
- func (b *BatchWriter) Commit() error
- func (b *BatchWriter) CommitWithSeq() (uint64, uint64, error)
- func (b *BatchWriter) Len() int
- func (b *BatchWriter) Rollback()
- type CompositeEngine
- func (c *CompositeEngine) AllEdges() ([]*Edge, error)
- func (c *CompositeEngine) AllNodes() ([]*Node, error)
- func (c *CompositeEngine) BatchGetNodes(ids []NodeID) (map[NodeID]*Node, error)
- func (c *CompositeEngine) BulkCreateEdges(edges []*Edge) error
- func (c *CompositeEngine) BulkCreateNodes(nodes []*Node) error
- func (c *CompositeEngine) BulkDeleteEdges(ids []EdgeID) error
- func (c *CompositeEngine) BulkDeleteNodes(ids []NodeID) error
- func (c *CompositeEngine) Close() error
- func (c *CompositeEngine) CreateEdge(edge *Edge) error
- func (c *CompositeEngine) CreateNode(node *Node) (NodeID, error)
- func (c *CompositeEngine) DeleteByPrefix(prefix string) (nodesDeleted int64, edgesDeleted int64, err error)
- func (c *CompositeEngine) DeleteEdge(id EdgeID) error
- func (c *CompositeEngine) DeleteNode(id NodeID) error
- func (c *CompositeEngine) EdgeCount() (int64, error)
- func (c *CompositeEngine) GetAllNodes() []*Node
- func (c *CompositeEngine) GetConstituentByAlias(alias string) (Engine, error)
- func (c *CompositeEngine) GetEdge(id EdgeID) (*Edge, error)
- func (c *CompositeEngine) GetEdgeBetween(startID, endID NodeID, edgeType string) *Edge
- func (c *CompositeEngine) GetEdgesBetween(startID, endID NodeID) ([]*Edge, error)
- func (c *CompositeEngine) GetEdgesByType(edgeType string) ([]*Edge, error)
- func (c *CompositeEngine) GetFirstNodeByLabel(label string) (*Node, error)
- func (c *CompositeEngine) GetInDegree(nodeID NodeID) int
- func (c *CompositeEngine) GetIncomingEdges(nodeID NodeID) ([]*Edge, error)
- func (c *CompositeEngine) GetNode(id NodeID) (*Node, error)
- func (c *CompositeEngine) GetNodesByLabel(label string) ([]*Node, error)
- func (c *CompositeEngine) GetOutDegree(nodeID NodeID) int
- func (c *CompositeEngine) GetOutgoingEdges(nodeID NodeID) ([]*Edge, error)
- func (c *CompositeEngine) GetSchema() *SchemaManager
- func (c *CompositeEngine) IsComposite() bool
- func (c *CompositeEngine) NodeCount() (int64, error)
- func (c *CompositeEngine) SetLabelRouting(label string, constituents []string)
- func (c *CompositeEngine) SetPropertyDefault(propertyName string, constituent string)
- func (c *CompositeEngine) SetPropertyRouting(propertyName string, value interface{}, constituent string)
- func (c *CompositeEngine) StreamEdges(ctx context.Context, fn func(edge *Edge) error) error
- func (c *CompositeEngine) StreamNodeChunks(ctx context.Context, chunkSize int, fn func(nodes []*Node) error) error
- func (c *CompositeEngine) StreamNodes(ctx context.Context, fn func(node *Node) error) error
- func (c *CompositeEngine) UpdateEdge(edge *Edge) error
- func (c *CompositeEngine) UpdateNode(node *Node) error
- type CompositeIndex
- func (idx *CompositeIndex) IndexNode(nodeID NodeID, properties map[string]interface{}) error
- func (idx *CompositeIndex) LookupFull(values ...interface{}) []NodeID
- func (idx *CompositeIndex) LookupPrefix(values ...interface{}) []NodeID
- func (idx *CompositeIndex) LookupWithFilter(filter func(NodeID) bool, values ...interface{}) []NodeID
- func (idx *CompositeIndex) RemoveNode(nodeID NodeID, properties map[string]interface{})
- func (idx *CompositeIndex) Stats() map[string]interface{}
- type CompositeKey
- type Constraint
- type ConstraintContract
- type ConstraintContractEntry
- type ConstraintEntityType
- type ConstraintType
- type ConstraintViolationError
- type CorruptionDiagnostics
- type DB
- type Edge
- type EdgeDeleteCallback
- type EdgeEventCallback
- type EdgeID
- type EdgeMeta
- type EdgeMetaKey
- type EdgeMetaStats
- type EdgeMetaStore
- func (s *EdgeMetaStore) Append(ctx context.Context, meta EdgeMeta) error
- func (s *EdgeMetaStore) AppendFromSuggestion(ctx context.Context, src, dst, label string, score float64, ...) error
- func (s *EdgeMetaStore) Cleanup(maxAge time.Duration) int
- func (s *EdgeMetaStore) Clear()
- func (s *EdgeMetaStore) CountHistory(src, dst, label string) int
- func (s *EdgeMetaStore) Export() []*EdgeMeta
- func (s *EdgeMetaStore) GetByOrigin(ctx context.Context, origin string, limit int) ([]*EdgeMeta, error)
- func (s *EdgeMetaStore) GetBySession(ctx context.Context, sessionID string, limit int) ([]*EdgeMeta, error)
- func (s *EdgeMetaStore) GetBySignalType(ctx context.Context, signalType string, limit int) ([]*EdgeMeta, error)
- func (s *EdgeMetaStore) GetByTimeRange(ctx context.Context, start, end time.Time, limit int) ([]*EdgeMeta, error)
- func (s *EdgeMetaStore) GetHistory(ctx context.Context, src, dst, label string) ([]*EdgeMeta, error)
- func (s *EdgeMetaStore) GetLatest(ctx context.Context, src, dst, label string) (*EdgeMeta, error)
- func (s *EdgeMetaStore) GetMaterialized(ctx context.Context, limit int) ([]*EdgeMeta, error)
- func (s *EdgeMetaStore) HasHistory(src, dst, label string) bool
- func (s *EdgeMetaStore) Import(records []*EdgeMeta) int
- func (s *EdgeMetaStore) MarkMaterialized(ctx context.Context, src, dst, label, origin string) error
- func (s *EdgeMetaStore) Size() int
- func (s *EdgeMetaStore) Stats() EdgeMetaStats
- func (s *EdgeMetaStore) UniqueEdgeCount() int
- type EdgeMetaStoreOption
- type EdgeVisitor
- type Engine
- type EngineOptions
- type ExportableEngine
- type FlushResult
- type FulltextIndex
- type IndexStats
- type LabelConfig
- type LabelIndexEngine
- type LabelNodeIDLookupEngine
- type MVCCAppendEngine
- type MVCCEnumerationEngine
- type MVCCHead
- type MVCCHeadEngine
- type MVCCIndexedVisibilityEngine
- type MVCCLatestEffectiveEngine
- type MVCCLifecycleController
- type MVCCLifecycleDebtEngine
- type MVCCLifecycleDebtKey
- type MVCCLifecycleEngine
- type MVCCLifecycleScheduleEngine
- type MVCCMaintenanceEngine
- type MVCCPruneOptions
- type MVCCReadMode
- type MVCCReadSelector
- type MVCCVersion
- type MVCCVisibilityEngine
- type MemoryEngine
- type NamespaceLister
- type NamespaceSchemaProvider
- type NamespaceTemporalCurrentNodeProvider
- type NamespaceTemporalLookupProvider
- type NamespacedEngine
- func (n *NamespacedEngine) AddToPendingEmbeddings(nodeID NodeID)
- func (n *NamespacedEngine) AllEdges() ([]*Edge, error)
- func (n *NamespacedEngine) AllNodes() ([]*Node, error)
- func (n *NamespacedEngine) BatchGetNodes(ids []NodeID) (map[NodeID]*Node, error)
- func (n *NamespacedEngine) BulkCreateEdges(edges []*Edge) error
- func (n *NamespacedEngine) BulkCreateNodes(nodes []*Node) error
- func (n *NamespacedEngine) BulkDeleteEdges(ids []EdgeID) error
- func (n *NamespacedEngine) BulkDeleteNodes(ids []NodeID) error
- func (n *NamespacedEngine) Close() error
- func (n *NamespacedEngine) CreateEdge(edge *Edge) error
- func (n *NamespacedEngine) CreateNode(node *Node) (NodeID, error)
- func (n *NamespacedEngine) DeleteByPrefix(prefix string) (nodesDeleted int64, edgesDeleted int64, err error)
- func (n *NamespacedEngine) DeleteEdge(id EdgeID) error
- func (n *NamespacedEngine) DeleteNode(id NodeID) error
- func (n *NamespacedEngine) EdgeCount() (int64, error)
- func (n *NamespacedEngine) FindNodeNeedingEmbedding() *Node
- func (n *NamespacedEngine) ForEachNodeIDByLabel(label string, visit func(NodeID) bool) error
- func (n *NamespacedEngine) GetAllNodes() []*Node
- func (n *NamespacedEngine) GetEdge(id EdgeID) (*Edge, error)
- func (n *NamespacedEngine) GetEdgeBetween(startID, endID NodeID, edgeType string) *Edge
- func (n *NamespacedEngine) GetEdgeCurrentHead(id EdgeID) (MVCCHead, error)
- func (n *NamespacedEngine) GetEdgeLatestVisible(id EdgeID) (*Edge, error)
- func (n *NamespacedEngine) GetEdgeVisibleAt(id EdgeID, version MVCCVersion) (*Edge, error)
- func (n *NamespacedEngine) GetEdgesBetween(startID, endID NodeID) ([]*Edge, error)
- func (n *NamespacedEngine) GetEdgesBetweenVisibleAt(startID, endID NodeID, version MVCCVersion) ([]*Edge, error)
- func (n *NamespacedEngine) GetEdgesByType(edgeType string) ([]*Edge, error)
- func (n *NamespacedEngine) GetEdgesByTypeVisibleAt(edgeType string, version MVCCVersion) ([]*Edge, error)
- func (n *NamespacedEngine) GetFirstNodeByLabel(label string) (*Node, error)
- func (n *NamespacedEngine) GetInDegree(nodeID NodeID) int
- func (n *NamespacedEngine) GetIncomingEdges(nodeID NodeID) ([]*Edge, error)
- func (n *NamespacedEngine) GetInnerEngine() Engine
- func (n *NamespacedEngine) GetNode(id NodeID) (*Node, error)
- func (n *NamespacedEngine) GetNodeCurrentHead(id NodeID) (MVCCHead, error)
- func (n *NamespacedEngine) GetNodeLatestVisible(id NodeID) (*Node, error)
- func (n *NamespacedEngine) GetNodeVisibleAt(id NodeID, version MVCCVersion) (*Node, error)
- func (n *NamespacedEngine) GetNodesByLabel(label string) ([]*Node, error)
- func (n *NamespacedEngine) GetNodesByLabelVisibleAt(label string, version MVCCVersion) ([]*Node, error)
- func (n *NamespacedEngine) GetOutDegree(nodeID NodeID) int
- func (n *NamespacedEngine) GetOutgoingEdges(nodeID NodeID) ([]*Edge, error)
- func (n *NamespacedEngine) GetSchema() *SchemaManager
- func (n *NamespacedEngine) GetTemporalNodeAsOf(label, keyProp string, keyValue interface{}, validFromProp, validToProp string, ...) (*Node, error)
- func (n *NamespacedEngine) IsCurrentTemporalNode(node *Node, asOf time.Time) (bool, error)
- func (n *NamespacedEngine) LastWriteTime() time.Time
- func (n *NamespacedEngine) LifecycleStatus() map[string]interface{}
- func (n *NamespacedEngine) MarkNodeEmbedded(nodeID NodeID)
- func (n *NamespacedEngine) Namespace() string
- func (n *NamespacedEngine) NodeCount() (int64, error)
- func (n *NamespacedEngine) PauseLifecycle()
- func (n *NamespacedEngine) RefreshPendingEmbeddingsIndex() int
- func (n *NamespacedEngine) RegisterSnapshotReader(info SnapshotReaderInfo) func()
- func (n *NamespacedEngine) ResumeLifecycle()
- func (n *NamespacedEngine) SetLifecycleSchedule(interval time.Duration) error
- func (n *NamespacedEngine) StreamEdges(ctx context.Context, fn func(edge *Edge) error) error
- func (n *NamespacedEngine) StreamNodeChunks(ctx context.Context, chunkSize int, fn func(nodes []*Node) error) error
- func (n *NamespacedEngine) StreamNodes(ctx context.Context, fn func(node *Node) error) error
- func (n *NamespacedEngine) TopLifecycleDebtKeys(limit int) []MVCCLifecycleDebtKey
- func (n *NamespacedEngine) TriggerPruneNow(ctx context.Context) error
- func (n *NamespacedEngine) UpdateEdge(edge *Edge) error
- func (n *NamespacedEngine) UpdateNode(node *Node) error
- type Neo4jExport
- type Neo4jNode
- type Neo4jNodeRef
- type Neo4jRelationship
- type Node
- type NodeConfig
- func (c *NodeConfig) AddToDeny(targetID string)
- func (c *NodeConfig) AddToPin(targetID string)
- func (c *NodeConfig) CanAddEdge(isOutgoing bool) bool
- func (c *NodeConfig) CanAddInEdge() bool
- func (c *NodeConfig) CanAddOutEdge() bool
- func (c *NodeConfig) DecrementEdgeCount(isOutgoing bool)
- func (c *NodeConfig) GetEffectiveConfidence(label string, baseThreshold float64) float64
- func (c *NodeConfig) GetLabelConfig(label string) (LabelConfig, bool)
- func (c *NodeConfig) IncrementEdgeCount(isOutgoing bool)
- func (c *NodeConfig) IsDenied(targetID string) bool
- func (c *NodeConfig) IsPinned(targetID string) bool
- func (c *NodeConfig) RemoveFromDeny(targetID string) bool
- func (c *NodeConfig) RemoveFromPin(targetID string) bool
- func (c *NodeConfig) SetLabelConfig(label string, cfg LabelConfig)
- type NodeConfigStats
- type NodeConfigStore
- func (s *NodeConfigStore) AddToNodeDenyList(nodeID, targetID string)
- func (s *NodeConfigStore) AddToNodePinList(nodeID, targetID string)
- func (s *NodeConfigStore) Clear()
- func (s *NodeConfigStore) Delete(nodeID string) bool
- func (s *NodeConfigStore) DisableNode(nodeID string)
- func (s *NodeConfigStore) EnableNode(nodeID string)
- func (s *NodeConfigStore) Export() []*NodeConfig
- func (s *NodeConfigStore) Get(nodeID string) *NodeConfig
- func (s *NodeConfigStore) GetAllNodeIDs() []string
- func (s *NodeConfigStore) GetDeniedTargets(nodeID string) []string
- func (s *NodeConfigStore) GetEffectiveConfidence(sourceID, targetID, label string, baseThreshold float64) float64
- func (s *NodeConfigStore) GetOrCreate(nodeID string) *NodeConfig
- func (s *NodeConfigStore) GetPinnedTargets(nodeID string) []string
- func (s *NodeConfigStore) Import(configs []*NodeConfig) int
- func (s *NodeConfigStore) IsEdgeAllowed(sourceID, targetID, label string) bool
- func (s *NodeConfigStore) IsEdgeAllowedWithReason(sourceID, targetID, label string) (bool, string)
- func (s *NodeConfigStore) IsPinned(sourceID, targetID string) bool
- func (s *NodeConfigStore) RecordEdgeCreation(sourceID, targetID string)
- func (s *NodeConfigStore) RecordEdgeDeletion(sourceID, targetID string)
- func (s *NodeConfigStore) Set(cfg NodeConfig)
- func (s *NodeConfigStore) SetNodeEdgeCaps(nodeID string, maxOut, maxIn, maxTotal int)
- func (s *NodeConfigStore) SetNodeTrustLevel(nodeID string, level TrustLevel)
- func (s *NodeConfigStore) Size() int
- func (s *NodeConfigStore) Stats() NodeConfigStats
- type NodeConfigStoreOption
- type NodeDeleteCallback
- type NodeEventCallback
- type NodeID
- type NodeVisitor
- type Operation
- type OperationType
- type PrefixStatsEngine
- type PrefixStreamingEngine
- type PressureBand
- type PropertyIndex
- type PropertyType
- type PropertyTypeConstraint
- type PropertyTypeConstraintOptions
- type QueryAnalyzer
- func (a *QueryAnalyzer) AnalyzeQuery(cypher string) *QueryInfo
- func (a *QueryAnalyzer) RouteQuery(queryInfo *QueryInfo, allConstituents []string) []string
- func (a *QueryAnalyzer) SetLabelRouting(label string, constituents []string)
- func (p *QueryAnalyzer) SetPropertyDefault(propertyName string, constituent string)
- func (p *QueryAnalyzer) SetPropertyRouting(propertyName string, value interface{}, constituent string)
- type QueryInfo
- type RangeIndex
- type Receipt
- type RelationshipConstraint
- type RemoteCypherTx
- type RemoteEngine
- func (r *RemoteEngine) AllEdges() ([]*Edge, error)
- func (r *RemoteEngine) AllNodes() ([]*Node, error)
- func (r *RemoteEngine) BatchGetNodes(ids []NodeID) (map[NodeID]*Node, error)
- func (r *RemoteEngine) BeginCypherTx(ctx context.Context) (RemoteCypherTx, error)
- func (r *RemoteEngine) BulkCreateEdges(edges []*Edge) error
- func (r *RemoteEngine) BulkCreateNodes(nodes []*Node) error
- func (r *RemoteEngine) BulkDeleteEdges(ids []EdgeID) error
- func (r *RemoteEngine) BulkDeleteNodes(ids []NodeID) error
- func (r *RemoteEngine) Close() error
- func (r *RemoteEngine) CreateEdge(edge *Edge) error
- func (r *RemoteEngine) CreateNode(node *Node) (NodeID, error)
- func (r *RemoteEngine) DeleteByPrefix(prefix string) (nodesDeleted int64, edgesDeleted int64, err error)
- func (r *RemoteEngine) DeleteEdge(id EdgeID) error
- func (r *RemoteEngine) DeleteNode(id NodeID) error
- func (r *RemoteEngine) EdgeCount() (int64, error)
- func (r *RemoteEngine) GetAllNodes() []*Node
- func (r *RemoteEngine) GetEdge(id EdgeID) (*Edge, error)
- func (r *RemoteEngine) GetEdgeBetween(startID, endID NodeID, edgeType string) *Edge
- func (r *RemoteEngine) GetEdgesBetween(startID, endID NodeID) ([]*Edge, error)
- func (r *RemoteEngine) GetEdgesByType(edgeType string) ([]*Edge, error)
- func (r *RemoteEngine) GetFirstNodeByLabel(label string) (*Node, error)
- func (r *RemoteEngine) GetInDegree(nodeID NodeID) int
- func (r *RemoteEngine) GetIncomingEdges(nodeID NodeID) ([]*Edge, error)
- func (r *RemoteEngine) GetNode(id NodeID) (*Node, error)
- func (r *RemoteEngine) GetNodesByLabel(label string) ([]*Node, error)
- func (r *RemoteEngine) GetOutDegree(nodeID NodeID) int
- func (r *RemoteEngine) GetOutgoingEdges(nodeID NodeID) ([]*Edge, error)
- func (r *RemoteEngine) GetSchema() *SchemaManager
- func (r *RemoteEngine) NodeCount() (int64, error)
- func (r *RemoteEngine) QueryCypher(ctx context.Context, statement string, params map[string]interface{}) ([]string, [][]interface{}, error)
- func (r *RemoteEngine) UpdateEdge(edge *Edge) error
- func (r *RemoteEngine) UpdateNode(node *Node) error
- type RemoteEngineConfig
- type ReplayError
- type ReplayResult
- type RetentionPolicy
- type SchemaCompositeIndexDef
- type SchemaDefinition
- type SchemaManager
- func (sm *SchemaManager) AddCompositeIndex(name, label string, properties []string) error
- func (sm *SchemaManager) AddConstraint(c Constraint, ifNotExists ...bool) error
- func (sm *SchemaManager) AddConstraintContractBundle(contract ConstraintContract, compiledConstraints []Constraint, ...) error
- func (sm *SchemaManager) AddFulltextIndex(name string, labels, properties []string) error
- func (sm *SchemaManager) AddPropertyIndex(name, label string, properties []string) error
- func (sm *SchemaManager) AddPropertyTypeConstraint(name, label, property string, expectedType PropertyType, ...) error
- func (sm *SchemaManager) AddPropertyTypeConstraintWithOptions(name, label, property string, expectedType PropertyType, ...) error
- func (sm *SchemaManager) AddRangeIndex(name, label, property string) error
- func (sm *SchemaManager) AddUniqueConstraint(name, label, property string, ifNotExists ...bool) error
- func (sm *SchemaManager) AddVectorIndex(name, label, property string, dimensions int, similarityFunc string) error
- func (sm *SchemaManager) CheckUniqueConstraint(label, property string, value interface{}, excludeNode NodeID) error
- func (sm *SchemaManager) DropConstraint(name string) error
- func (sm *SchemaManager) DropIndex(name string) error
- func (sm *SchemaManager) ExportDefinition() *SchemaDefinition
- func (sm *SchemaManager) GetAllConstraintContracts() []ConstraintContract
- func (sm *SchemaManager) GetAllConstraints() []Constraint
- func (sm *SchemaManager) GetAllPropertyTypeConstraints() []PropertyTypeConstraint
- func (sm *SchemaManager) GetCompositeIndex(name string) (*CompositeIndex, bool)
- func (sm *SchemaManager) GetCompositeIndexesForLabel(label string) []*CompositeIndex
- func (sm *SchemaManager) GetConstraintContractsForTarget(entityType ConstraintEntityType, labelOrType string) []ConstraintContract
- func (sm *SchemaManager) GetConstraints() []UniqueConstraint
- func (sm *SchemaManager) GetConstraintsForLabels(labels []string) []Constraint
- func (sm *SchemaManager) GetFulltextIndex(name string) (*FulltextIndex, bool)
- func (sm *SchemaManager) GetIndexStats() []IndexStats
- func (sm *SchemaManager) GetIndexes() []interface{}
- func (sm *SchemaManager) GetPropertyIndex(label, property string) (*PropertyIndex, bool)
- func (sm *SchemaManager) GetPropertyTypeConstraintsForLabels(labels []string) []PropertyTypeConstraint
- func (sm *SchemaManager) GetRangeIndex(name string) (*RangeIndex, bool)
- func (sm *SchemaManager) GetVectorIndex(name string) (*VectorIndex, bool)
- func (sm *SchemaManager) LookupUniqueConstraintValue(label, property string, value interface{}) (NodeID, bool, bool)
- func (sm *SchemaManager) PropertyIndexAllNonNil(label, property string, descending bool) []NodeID
- func (sm *SchemaManager) PropertyIndexDelete(label, property string, nodeID NodeID, value interface{}) error
- func (sm *SchemaManager) PropertyIndexInsert(label, property string, nodeID NodeID, value interface{}) error
- func (sm *SchemaManager) PropertyIndexLookup(label, property string, value interface{}) []NodeID
- func (sm *SchemaManager) PropertyIndexTopK(label, property string, limit int, descending bool) []NodeID
- func (sm *SchemaManager) RangeIndexDelete(name string, nodeID NodeID) error
- func (sm *SchemaManager) RangeIndexInsert(name string, nodeID NodeID, value interface{}) error
- func (sm *SchemaManager) RangeQuery(name string, minVal, maxVal interface{}, includeMin, includeMax bool) ([]NodeID, error)
- func (sm *SchemaManager) RegisterUniqueValue(label, property string, value interface{}, nodeID NodeID)
- func (sm *SchemaManager) ReplaceFromDefinition(def *SchemaDefinition) error
- func (sm *SchemaManager) SetPersister(persist func(def *SchemaDefinition) error)
- func (sm *SchemaManager) UnregisterUniqueValue(label, property string, value interface{})
- type SchemaPropertyIndexDef
- type SchemaRangeIndexDef
- type SerializerMigrationOptions
- type SerializerMigrationStats
- type SignalType
- type Snapshot
- type SnapshotReaderInfo
- type SnapshotReaderRegistry
- type StorageEventNotifier
- type StorageSerializer
- type StreamingEngine
- type TemporalCurrentNodeEngine
- type TemporalLookupEngine
- type TemporalMaintenanceEngine
- type TemporalPruneOptions
- type Transaction
- type TransactionRecoveryResult
- type TransactionState
- type TransactionStatus
- type TrustLevel
- type UniqueConstraint
- type VectorIndex
- type WAL
- func (w *WAL) Append(op OperationType, data interface{}) error
- func (w *WAL) AppendReturningSeq(op OperationType, data interface{}) (uint64, error)
- func (w *WAL) AppendTxAbort(database, txID, reason string) (uint64, error)
- func (w *WAL) AppendTxBegin(database, txID string, metadata map[string]string) (uint64, error)
- func (w *WAL) AppendTxCommit(database, txID string, opCount int) (uint64, error)
- func (w *WAL) AppendWithDatabase(op OperationType, data interface{}, database string) error
- func (w *WAL) AppendWithDatabaseReturningSeq(op OperationType, data interface{}, database string) (uint64, error)
- func (w *WAL) ApplyRetention(snapshotSeq uint64) error
- func (w *WAL) Checkpoint() error
- func (w *WAL) Close() error
- func (w *WAL) Config() *WALConfig
- func (w *WAL) CreateSnapshot(engine Engine) (*Snapshot, error)
- func (w *WAL) IsDegraded() bool
- func (w *WAL) LastCorruptionDiagnostics() *CorruptionDiagnostics
- func (w *WAL) NewBatch() *BatchWriter
- func (w *WAL) NewBatchWithTxID(txID string) *BatchWriter
- func (w *WAL) Sequence() uint64
- func (w *WAL) Stats() WALStats
- func (w *WAL) Sync() error
- func (w *WAL) TruncateAfterSnapshot(snapshotSeq uint64) error
- type WALBulkDeleteEdgesData
- type WALBulkDeleteNodesData
- type WALBulkEdgesData
- type WALBulkNodesData
- type WALConfig
- type WALDeleteData
- type WALEdgeData
- type WALEngine
- func (w *WALEngine) AddToPendingEmbeddings(nodeID NodeID)
- func (w *WALEngine) AllEdges() ([]*Edge, error)
- func (w *WALEngine) AllNodes() ([]*Node, error)
- func (w *WALEngine) BatchGetNodes(ids []NodeID) (map[NodeID]*Node, error)
- func (w *WALEngine) BulkCreateEdges(edges []*Edge) error
- func (w *WALEngine) BulkCreateNodes(nodes []*Node) error
- func (w *WALEngine) BulkDeleteEdges(ids []EdgeID) error
- func (w *WALEngine) BulkDeleteNodes(ids []NodeID) error
- func (w *WALEngine) Close() error
- func (w *WALEngine) CreateEdge(edge *Edge) error
- func (w *WALEngine) CreateNode(node *Node) (NodeID, error)
- func (w *WALEngine) DeleteByPrefix(prefix string) (nodesDeleted int64, edgesDeleted int64, err error)
- func (w *WALEngine) DeleteEdge(id EdgeID) error
- func (w *WALEngine) DeleteNode(id NodeID) error
- func (w *WALEngine) DisableAutoCompaction()
- func (w *WALEngine) EdgeCount() (int64, error)
- func (w *WALEngine) EdgeCountByPrefix(prefix string) (int64, error)
- func (w *WALEngine) EnableAutoCompaction(snapshotDir string) error
- func (w *WALEngine) FindNodeNeedingEmbedding() *Node
- func (w *WALEngine) ForEachNodeIDByLabel(label string, visit func(NodeID) bool) error
- func (w *WALEngine) GetAllNodes() []*Node
- func (w *WALEngine) GetEdge(id EdgeID) (*Edge, error)
- func (w *WALEngine) GetEdgeBetween(startID, endID NodeID, edgeType string) *Edge
- func (w *WALEngine) GetEdgeCurrentHead(id EdgeID) (MVCCHead, error)
- func (w *WALEngine) GetEdgeLatestEffective(id EdgeID) (*Edge, error)
- func (w *WALEngine) GetEdgeLatestVisible(id EdgeID) (*Edge, error)
- func (w *WALEngine) GetEdgeVisibleAt(id EdgeID, version MVCCVersion) (*Edge, error)
- func (w *WALEngine) GetEdgesBetween(startID, endID NodeID) ([]*Edge, error)
- func (w *WALEngine) GetEdgesBetweenVisibleAt(startID, endID NodeID, version MVCCVersion) ([]*Edge, error)
- func (w *WALEngine) GetEdgesByType(edgeType string) ([]*Edge, error)
- func (w *WALEngine) GetEdgesByTypeVisibleAt(edgeType string, version MVCCVersion) ([]*Edge, error)
- func (w *WALEngine) GetEngine() Engine
- func (w *WALEngine) GetFirstNodeByLabel(label string) (*Node, error)
- func (w *WALEngine) GetInDegree(nodeID NodeID) int
- func (w *WALEngine) GetIncomingEdges(nodeID NodeID) ([]*Edge, error)
- func (w *WALEngine) GetInnerEngine() Engine
- func (w *WALEngine) GetNode(id NodeID) (*Node, error)
- func (w *WALEngine) GetNodeCurrentHead(id NodeID) (MVCCHead, error)
- func (w *WALEngine) GetNodeLatestEffective(id NodeID) (*Node, error)
- func (w *WALEngine) GetNodeLatestVisible(id NodeID) (*Node, error)
- func (w *WALEngine) GetNodeVisibleAt(id NodeID, version MVCCVersion) (*Node, error)
- func (w *WALEngine) GetNodesByLabel(label string) ([]*Node, error)
- func (w *WALEngine) GetNodesByLabelVisibleAt(label string, version MVCCVersion) ([]*Node, error)
- func (w *WALEngine) GetOutDegree(nodeID NodeID) int
- func (w *WALEngine) GetOutgoingEdges(nodeID NodeID) ([]*Edge, error)
- func (w *WALEngine) GetSchema() *SchemaManager
- func (w *WALEngine) GetSchemaForNamespace(namespace string) *SchemaManager
- func (w *WALEngine) GetSnapshotStats() (totalSnapshots int64, lastSnapshotTime time.Time)
- func (w *WALEngine) GetWAL() *WAL
- func (w *WALEngine) IsCurrentTemporalNode(node *Node, asOf time.Time) (bool, error)
- func (w *WALEngine) IterateNodes(fn func(*Node) bool) error
- func (w *WALEngine) LastWriteTime() time.Time
- func (w *WALEngine) LifecycleStatus() map[string]interface{}
- func (w *WALEngine) ListNamespaces() []string
- func (w *WALEngine) MarkNodeEmbedded(nodeID NodeID)
- func (w *WALEngine) NodeCount() (int64, error)
- func (w *WALEngine) NodeCountByPrefix(prefix string) (int64, error)
- func (w *WALEngine) PauseLifecycle()
- func (w *WALEngine) PendingEmbeddingsCount() int
- func (w *WALEngine) PruneMVCCVersions(ctx context.Context, opts MVCCPruneOptions) (int64, error)
- func (w *WALEngine) PruneTemporalHistory(ctx context.Context, opts TemporalPruneOptions) (int64, error)
- func (w *WALEngine) RebuildMVCCHeads(ctx context.Context) error
- func (w *WALEngine) RebuildTemporalIndexes(ctx context.Context) error
- func (w *WALEngine) RefreshPendingEmbeddingsIndex() int
- func (w *WALEngine) RegisterSnapshotReader(info SnapshotReaderInfo) func()
- func (w *WALEngine) ResumeLifecycle()
- func (w *WALEngine) SetLifecycleSchedule(interval time.Duration) error
- func (w *WALEngine) StreamEdges(ctx context.Context, fn func(edge *Edge) error) error
- func (w *WALEngine) StreamNodeChunks(ctx context.Context, chunkSize int, fn func(nodes []*Node) error) error
- func (w *WALEngine) StreamNodes(ctx context.Context, fn func(node *Node) error) error
- func (w *WALEngine) StreamNodesByPrefix(ctx context.Context, prefix string, fn func(node *Node) error) error
- func (w *WALEngine) TopLifecycleDebtKeys(limit int) []MVCCLifecycleDebtKey
- func (w *WALEngine) TriggerPruneNow(ctx context.Context) error
- func (w *WALEngine) UpdateEdge(edge *Edge) error
- func (w *WALEngine) UpdateNode(node *Node) error
- func (w *WALEngine) UpdateNodeEmbedding(node *Node) error
- type WALEntry
- func FindWALEntriesByTxID(walDir, txID string, maxEntries int) ([]WALEntry, error)
- func ReadWALEntries(walPath string) ([]WALEntry, error)
- func ReadWALEntriesAfter(walPath string, afterSeq uint64) ([]WALEntry, error)
- func ReadWALEntriesAfterFromDir(walDir string, afterSeq uint64) ([]WALEntry, error)
- func ReadWALEntriesFromDir(walDir string) ([]WALEntry, error)
- func ReadWALEntriesRangeFromDir(walDir string, fromSeq, toSeq uint64) ([]WALEntry, error)
- type WALIntegrityReport
- type WALLogger
- type WALManifest
- type WALNodeData
- type WALSegment
- type WALStats
- type WALTxData
Constants ¶
const ( ConstraintContractKindPrimitiveNode = "primitive-node" ConstraintContractKindPrimitiveRelationship = "primitive-relationship" ConstraintContractKindBooleanNode = "boolean-node" ConstraintContractKindBooleanRelationship = "boolean-relationship" )
const DefaultMaxRetries = 5
const DefaultRetentionPolicyMaxVersionsPerKey = 100
const DefaultUpdateRetryLimit = 5
Variables ¶
var ( ErrNoTransaction = errors.New("no active transaction") ErrTransactionActive = errors.New("transaction already active") ErrTransactionClosed = errors.New("transaction already closed") ErrTransactionRollback = errors.New("transaction rolled back") )
Transaction errors
var ( ErrNotFound = errors.New("not found") ErrAlreadyExists = errors.New("already exists") ErrConflict = errors.New("conflict") ErrInvalidID = errors.New("invalid id") ErrInvalidData = errors.New("invalid data") ErrNotImplemented = errors.New("not implemented") ErrInvalidEdge = errors.New("invalid edge: start or end node not found") ErrStorageClosed = errors.New("storage closed") ErrIterationStopped = errors.New("iteration stopped") // Sentinel to stop streaming early )
Common errors
var ( ErrMVCCSnapshotGracefulCancel = errors.New("mvcc: snapshot cancelled due to resource pressure") ErrMVCCSnapshotHardExpired = errors.New("mvcc: snapshot forcibly expired due to critical resource pressure") )
Snapshot expiration errors surface when an already-admitted reader is forced to stop.
var ( ErrWALClosed = errors.New("wal: closed") ErrWALCorrupted = errors.New("wal: corrupted entry") ErrWALPartialWrite = errors.New("wal: partial write detected") ErrWALChecksumFailed = errors.New("wal: checksum verification failed") ErrWALMissingTrailer = errors.New("wal: missing or invalid trailer (incomplete write)") ErrSnapshotFailed = errors.New("wal: snapshot creation failed") ErrRecoveryFailed = errors.New("wal: recovery failed") )
Common WAL errors
var ErrMVCCResourcePressure = errors.New("mvcc: resource pressure exceeded snapshot lifetime")
ErrMVCCResourcePressure is returned when MVCC resource pressure exceeds snapshot lifetime.
var ErrNoUndoData = errors.New("wal: entry has no undo data")
UndoWALEntry reverses a WAL entry using its stored "before image". This is used for transaction rollback on crash recovery. Returns ErrNoUndoData if the entry lacks undo information.
Functions ¶
func CollectEdgeTypes ¶
CollectEdgeTypes collects all unique edge types using streaming.
func CollectLabels ¶
CollectLabels collects all unique labels using streaming.
func CountNodesWithLabel ¶
CountNodesWithLabel counts nodes with a specific label using streaming.
func EnsureDatabasePrefix ¶
EnsureDatabasePrefix adds "<dbName>:" to id if id has no existing valid prefix.
If id already has a prefix (even a different database), id is returned unchanged to avoid accidentally rewriting cross-database IDs.
func FromNeo4jExport ¶
func FromNeo4jExport(export *Neo4jExport) ([]*Node, []*Edge)
FromNeo4jExport converts Neo4j JSON export format to NornicDB nodes and edges.
This function imports data exported from Neo4j, extracting NornicDB-specific properties (those with "_" prefix) back into their dedicated fields.
Supports both export formats:
- neo4j-admin database dump (flat format)
- apoc.export.json (nested format)
Example:
// Load Neo4j export file
data, _ := os.ReadFile("neo4j-export.json")
var export storage.Neo4jExport
json.Unmarshal(data, &export)
// Convert to NornicDB format
nodes, edges := storage.FromNeo4jExport(&export)
// Import into NornicDB
if err := engine.BulkCreateNodes(nodes); err != nil {
log.Fatal(err)
}
if err := engine.BulkCreateEdges(edges); err != nil {
log.Fatal(err)
}
fmt.Printf("Imported %d nodes, %d edges\n", len(nodes), len(edges))
Returns nodes and edges ready for storage engine insertion.
func GenericSaveToNeo4jExport ¶
func GenericSaveToNeo4jExport(engine ExportableEngine, path string) error
GenericSaveToNeo4jExport works with any ExportableEngine.
func GetEntryTxID ¶
GetEntryTxID extracts the transaction ID from a WAL entry, if present.
func LoadFromNeo4jExport ¶
LoadFromNeo4jExport loads data from a combined Neo4j export file.
This function loads data from a single JSON file containing both nodes and relationships in a combined format. This is the format produced by SaveToNeo4jExport() and provides a more compact representation.
Parameters:
- engine: Storage engine to load data into
- path: Path to the combined JSON export file
Returns:
- Error if file cannot be read or data is invalid
Example:
// Load from combined export file
engine := storage.NewMemoryEngine()
err := storage.LoadFromNeo4jExport(engine, "./data-export.json")
if err != nil {
log.Fatalf("Failed to load export: %v", err)
}
fmt.Println("Successfully loaded data from export file")
File Format:
{
"nodes": [
{"id":"0","labels":["Person"],"properties":{"name":"Alice"}},
{"id":"1","labels":["Person"],"properties":{"name":"Bob"}}
],
"relationships": [
{"id":"0","type":"KNOWS","startNode":"0","endNode":"1","properties":{}}
]
}
Performance:
- Loads entire file into memory for parsing
- Uses bulk operations for efficient storage
- Suitable for moderate-sized datasets
Use Cases:
- Restoring NornicDB backups
- Migrating data between environments
- Loading test datasets
- Data exchange with Neo4j systems
func LoadFromNeo4jJSON ¶
LoadFromNeo4jJSON loads nodes and edges from Neo4j APOC JSON export format.
This function reads the standard Neo4j APOC export format consisting of nodes.json and relationships.json files. This format is produced by Neo4j's APOC library using `apoc.export.json.all()` or similar procedures.
File Format:
- nodes.json: One JSON object per line (JSONL format)
- relationships.json: One JSON object per line (JSONL format)
Parameters:
- engine: Storage engine to load data into
- dir: Directory containing nodes.json and relationships.json files
Returns:
- Error if files cannot be read or data is invalid
Example:
// Load from Neo4j APOC export directory
engine := storage.NewMemoryEngine()
err := storage.LoadFromNeo4jJSON(engine, "./neo4j-export/")
if err != nil {
log.Fatalf("Failed to load Neo4j data: %v", err)
}
fmt.Println("Successfully loaded Neo4j data into NornicDB")
Expected Directory Structure:
neo4j-export/ ├── nodes.json └── relationships.json
Node Format (nodes.json):
{"id":"0","labels":["Person"],"properties":{"name":"Alice","age":30}}
{"id":"1","labels":["Company"],"properties":{"name":"Acme Corp"}}
Relationship Format (relationships.json):
{"id":"0","type":"WORKS_FOR","startNode":"0","endNode":"1","properties":{"since":2020}}
Performance:
- Processes files sequentially (nodes first, then relationships)
- Uses streaming JSON parsing for memory efficiency
- Bulk operations for optimal storage performance
func NodeNeedsEmbedding ¶
NodeNeedsEmbedding checks if a node needs an embedding to be generated. Returns true if the node should have an embedding generated, false if it should be skipped.
A node is skipped (returns false) if:
- It has an internal label (starts with '_')
- It already has an embedding
- It has the "embedding_skipped" property set
- It has "has_embedding" property explicitly set to false
Example:
for _, node := range nodes {
if storage.NodeNeedsEmbedding(node) {
generateEmbedding(node)
}
}
func ParseDatabasePrefix ¶
ParseDatabasePrefix splits an ID formatted as "<db>:<id>" into database and unprefixed ID.
Returns ok=false if there is no valid prefix (no ':', empty db, or empty id).
func PruneOldSnapshotFiles ¶
PruneOldSnapshotFiles removes old snapshot files in dir according to cfg retention. Keeps at most SnapshotRetentionMaxCount snapshots (newest by mtime) and deletes any older than SnapshotRetentionMaxAge. Idempotent; safe to call after each save.
func RecoverFromWALWithResult ¶
func RecoverFromWALWithResult(walDir, snapshotPath string) (*MemoryEngine, ReplayResult, error)
RecoverFromWALWithResult recovers database state and returns detailed results. Use this for programmatic access to replay statistics and errors.
func RecoverWithTransactions ¶
func RecoverWithTransactions(walDir, snapshotPath string) (*MemoryEngine, *TransactionRecoveryResult, error)
RecoverWithTransactions performs transaction-aware WAL recovery. Incomplete transactions (no commit/abort) are rolled back using undo data. Returns the engine state and recovery statistics.
func RefreshUniqueConstraintValuesForEngine ¶ added in v1.0.43
func RefreshUniqueConstraintValuesForEngine(engine Engine, schema *SchemaManager) error
RefreshUniqueConstraintValuesForEngine rebuilds single-property UNIQUE value caches from the engine after a schema mutation has been admitted.
func ReplayWALEntry ¶
ReplayWALEntry applies a single WAL entry to the engine. Uses the database name from the entry if present, otherwise wraps with default database.
func ResetGlobalEdgeMetaStore ¶
func ResetGlobalEdgeMetaStore()
ResetGlobalEdgeMetaStore resets the global edge meta store. Primarily for testing.
func ResetGlobalNodeConfigStore ¶
func ResetGlobalNodeConfigStore()
ResetGlobalNodeConfigStore resets the global node config store. Primarily for testing.
func SaveSnapshot ¶
SaveSnapshot writes a snapshot to disk with full durability guarantees. Uses write-to-temp + atomic-rename pattern for crash safety.
func SaveToNeo4jExport ¶
SaveToNeo4jExport exports all data from the storage engine to a Neo4j-compatible JSON file.
This function creates a complete export of all nodes and relationships in the storage engine, formatted for compatibility with Neo4j tools and for backup/restore operations.
Parameters:
- engine: Storage engine to export data from
- path: Output file path for the JSON export
Returns:
- Error if export fails or file cannot be written
Example:
// Export all data to JSON file
err := storage.SaveToNeo4jExport(engine, "./backup.json")
if err != nil {
log.Fatalf("Export failed: %v", err)
}
fmt.Println("Data exported successfully")
// The exported file can be loaded back with:
// storage.LoadFromNeo4jExport(newEngine, "./backup.json")
Output Format:
{
"nodes": [
{
"id": "node-123",
"labels": ["Person", "Employee"],
"properties": {
"name": "Alice Smith",
"age": 30,
"email": "alice@example.com"
}
}
],
"relationships": [
{
"id": "rel-456",
"type": "WORKS_FOR",
"startNode": "node-123",
"endNode": "node-789",
"properties": {
"since": "2020-01-15",
"role": "Developer"
}
}
]
}
Use Cases:
- Creating backups of NornicDB data
- Migrating data to Neo4j
- Data analysis with Neo4j tools
- Sharing datasets in a standard format
Performance:
- Reads all data into memory before export
- Uses pretty-printed JSON for readability
- Suitable for datasets that fit in memory
Note: Currently only supports MemoryEngine. Other storage engines will return an error indicating unsupported engine type.
func SetStorageSerializer ¶
func SetStorageSerializer(serializer StorageSerializer) error
SetStorageSerializer sets the active serializer for storage encoding.
func StreamEdgesWithFallback ¶
func StreamEdgesWithFallback(ctx context.Context, engine Engine, chunkSize int, fn EdgeVisitor) error
StreamEdgesWithFallback provides streaming iteration with fallback.
func StreamNodesWithFallback ¶
func StreamNodesWithFallback(ctx context.Context, engine Engine, chunkSize int, fn NodeVisitor) error
StreamNodesWithFallback provides streaming iteration with fallback. If the engine supports StreamingEngine, it uses that. Otherwise, it loads all nodes but processes them in chunks.
func StripDatabasePrefix ¶
StripDatabasePrefix removes "<db>:" from id only if it matches dbName. If dbName is empty, or id does not have the matching prefix, id is returned unchanged.
func UndoWALEntry ¶
func ValidateConstraintContractOnCreationForEngine ¶
func ValidateConstraintContractOnCreationForEngine(engine Engine, contract ConstraintContract) error
func ValidateConstraintOnCreationForEngine ¶
func ValidateConstraintOnCreationForEngine(engine Engine, c Constraint) error
ValidateConstraintOnCreationForEngine validates constraints using the Engine interface. This allows callers (like Cypher) to validate through wrapper engines (namespaced, WAL, etc.).
func ValidatePropertyType ¶
func ValidatePropertyType(value interface{}, expectedType PropertyType) error
ValidatePropertyType checks if a value matches the expected type. Handles JSON/MessagePack serialization quirks where integers become float64.
func ValidatePropertyTypeConstraintOnCreationForEngine ¶
func ValidatePropertyTypeConstraintOnCreationForEngine(engine Engine, ptc PropertyTypeConstraint) error
ValidatePropertyTypeConstraintOnCreationForEngine validates type constraints using Engine.
Types ¶
type AsyncEngine ¶
type AsyncEngine struct {
// contains filtered or unexported fields
}
AsyncEngine wraps a storage engine with write-behind caching. Writes return immediately after updating the cache, and are flushed to the underlying engine asynchronously.
func NewAsyncEngine ¶
func NewAsyncEngine(engine Engine, config *AsyncEngineConfig) *AsyncEngine
NewAsyncEngine wraps an engine with write-behind caching.
func (*AsyncEngine) AddToPendingEmbeddings ¶
func (ae *AsyncEngine) AddToPendingEmbeddings(nodeID NodeID)
AddToPendingEmbeddings delegates to the underlying engine, if supported. Call this to re-queue a node for embedding after a failed attempt (e.g. so another worker can retry).
func (*AsyncEngine) AllEdges ¶
func (ae *AsyncEngine) AllEdges() ([]*Edge, error)
AllEdges returns merged view of cache and engine. It snapshots async cache state quickly under lock, then releases the lock before engine I/O to avoid holding ae.mu across potentially slow scans.
func (*AsyncEngine) AllNodes ¶
func (ae *AsyncEngine) AllNodes() ([]*Node, error)
AllNodes returns merged view of cache, in-flight nodes, and engine. It snapshots async cache state quickly under lock, then releases the lock before engine I/O to avoid holding ae.mu across potentially slow scans.
func (*AsyncEngine) BatchGetNodes ¶
func (ae *AsyncEngine) BatchGetNodes(ids []NodeID) (map[NodeID]*Node, error)
BatchGetNodes fetches multiple nodes, checking cache first then engine. Returns a map for O(1) lookup. Missing nodes are not included.
func (*AsyncEngine) BulkCreateEdges ¶
func (ae *AsyncEngine) BulkCreateEdges(edges []*Edge) error
BulkCreateEdges creates edges in batch (async).
func (*AsyncEngine) BulkCreateNodes ¶
func (ae *AsyncEngine) BulkCreateNodes(nodes []*Node) error
BulkCreateNodes creates nodes in batch (async).
func (*AsyncEngine) BulkDeleteEdges ¶
func (ae *AsyncEngine) BulkDeleteEdges(ids []EdgeID) error
BulkDeleteEdges marks multiple edges for deletion (async).
func (*AsyncEngine) BulkDeleteNodes ¶
func (ae *AsyncEngine) BulkDeleteNodes(ids []NodeID) error
BulkDeleteNodes marks multiple nodes for deletion (async).
func (*AsyncEngine) Close ¶
func (ae *AsyncEngine) Close() error
Close stops the background flush goroutine and flushes all pending data. Returns an error if the final flush fails or if data remains unflushed.
func (*AsyncEngine) CreateEdge ¶
func (ae *AsyncEngine) CreateEdge(edge *Edge) error
CreateEdge adds to cache and returns immediately.
func (*AsyncEngine) CreateNode ¶
func (ae *AsyncEngine) CreateNode(node *Node) (NodeID, error)
CreateNode adds to cache and returns immediately.
func (*AsyncEngine) DeleteByPrefix ¶
func (ae *AsyncEngine) DeleteByPrefix(prefix string) (nodesDeleted int64, edgesDeleted int64, err error)
DeleteByPrefix delegates to the underlying engine.
func (*AsyncEngine) DeleteEdge ¶
func (ae *AsyncEngine) DeleteEdge(id EdgeID) error
DeleteEdge marks for deletion and returns immediately. Optimized: if edge was created in this transaction (still in cache), just remove it from cache - no need to delete from underlying engine. CRITICAL: If edge is in-flight (being flushed), we must also mark for deletion because the flush will write it to the underlying engine.
func (*AsyncEngine) DeleteNode ¶
func (ae *AsyncEngine) DeleteNode(id NodeID) error
DeleteNode marks for deletion and returns immediately. Optimized: if node was created in this transaction (still in cache), just remove it from cache - no need to delete from underlying engine. CRITICAL: If node is in-flight (being flushed), we must also mark for deletion because the flush will write it to the underlying engine.
func (*AsyncEngine) EdgeCount ¶
func (ae *AsyncEngine) EdgeCount() (int64, error)
func (*AsyncEngine) EdgeCountByPrefix ¶
func (ae *AsyncEngine) EdgeCountByPrefix(prefix string) (int64, error)
func (*AsyncEngine) FindNodeNeedingEmbedding ¶
func (ae *AsyncEngine) FindNodeNeedingEmbedding() *Node
FindNodeNeedingEmbedding returns a node that needs embedding. IMPORTANT: This checks the in-memory cache first to ensure we don't re-process nodes that have embeddings pending flush to the underlying engine.
The algorithm: 1. Build set of node IDs that have embeddings in cache (pending flush) 2. First check nodes in our cache that need embedding 3. Then check underlying engine, skipping nodes we have in cache with embeddings
func (*AsyncEngine) Flush ¶
func (ae *AsyncEngine) Flush() error
Flush writes all pending changes to the underlying engine. Uses batched operations for better performance - all deletes in one transaction.
CRITICAL FIX: Failed items are NOT removed from cache - they will be retried on the next flush. This prevents silent data loss.
Design: Snapshot caches, clear them, UNLOCK, then write to engine. Reads during write see engine data (consistent since cache is empty). This avoids blocking reads during I/O which kills Mac M-series performance.
Thread-safe: Uses flushMu to prevent concurrent flushes which can cause race conditions when cache limit is reached during concurrent writes.
func (*AsyncEngine) FlushWithResult ¶
func (ae *AsyncEngine) FlushWithResult() FlushResult
FlushWithResult writes pending changes and returns detailed results. Use this for programmatic access to flush statistics.
func (*AsyncEngine) ForEachNodeIDByLabel ¶
func (ae *AsyncEngine) ForEachNodeIDByLabel(label string, visit func(NodeID) bool) error
ForEachNodeIDByLabel streams node IDs for a label, combining cache + engine. Stops early when visit returns false.
func (*AsyncEngine) GetAllNodes ¶
func (ae *AsyncEngine) GetAllNodes() []*Node
func (*AsyncEngine) GetEdge ¶
func (ae *AsyncEngine) GetEdge(id EdgeID) (*Edge, error)
GetEdge checks cache first, then underlying engine.
func (*AsyncEngine) GetEdgeBetween ¶
func (ae *AsyncEngine) GetEdgeBetween(startID, endID NodeID, edgeType string) *Edge
func (*AsyncEngine) GetEdgeCurrentHead ¶
func (ae *AsyncEngine) GetEdgeCurrentHead(id EdgeID) (MVCCHead, error)
GetEdgeCurrentHead delegates edge head lookup to the wrapped engine when supported.
func (*AsyncEngine) GetEdgeLatestEffective ¶
func (ae *AsyncEngine) GetEdgeLatestEffective(id EdgeID) (*Edge, error)
GetEdgeLatestEffective returns the merged latest-visible edge across pending, in-flight, and persisted state.
func (*AsyncEngine) GetEdgeLatestVisible ¶
func (ae *AsyncEngine) GetEdgeLatestVisible(id EdgeID) (*Edge, error)
GetEdgeLatestVisible resolves the latest persisted-or-effective edge.
func (*AsyncEngine) GetEdgeVisibleAt ¶
func (ae *AsyncEngine) GetEdgeVisibleAt(id EdgeID, version MVCCVersion) (*Edge, error)
GetEdgeVisibleAt delegates snapshot-visible edge reads to the wrapped engine when supported.
func (*AsyncEngine) GetEdgesBetween ¶
func (ae *AsyncEngine) GetEdgesBetween(startID, endID NodeID) ([]*Edge, error)
func (*AsyncEngine) GetEdgesBetweenVisibleAt ¶
func (ae *AsyncEngine) GetEdgesBetweenVisibleAt(startID, endID NodeID, version MVCCVersion) ([]*Edge, error)
GetEdgesBetweenVisibleAt delegates snapshot-visible topology queries to the wrapped engine when supported.
func (*AsyncEngine) GetEdgesByType ¶
func (ae *AsyncEngine) GetEdgesByType(edgeType string) ([]*Edge, error)
GetEdgesByType returns all edges of a specific type, merging cache and engine.
func (*AsyncEngine) GetEdgesByTypeVisibleAt ¶
func (ae *AsyncEngine) GetEdgesByTypeVisibleAt(edgeType string, version MVCCVersion) ([]*Edge, error)
GetEdgesByTypeVisibleAt delegates snapshot-visible edge-type queries to the wrapped engine when supported.
func (*AsyncEngine) GetEngine ¶
func (ae *AsyncEngine) GetEngine() Engine
GetEngine returns the underlying storage engine. Used for transaction support which needs direct access.
func (*AsyncEngine) GetFirstNodeByLabel ¶
func (ae *AsyncEngine) GetFirstNodeByLabel(label string) (*Node, error)
GetNodesByLabel checks cache and merges with engine results. Uses case-insensitive label matching for Neo4j compatibility. Snapshots cache state quickly, then releases lock before engine I/O. GetFirstNodeByLabel returns the first node with the specified label. Optimized for MATCH...LIMIT 1 patterns - uses label index for O(1) lookup.
func (*AsyncEngine) GetInDegree ¶
func (ae *AsyncEngine) GetInDegree(nodeID NodeID) int
func (*AsyncEngine) GetIncomingEdges ¶
func (ae *AsyncEngine) GetIncomingEdges(nodeID NodeID) ([]*Edge, error)
func (*AsyncEngine) GetInnerEngine ¶
func (e *AsyncEngine) GetInnerEngine() Engine
GetInnerEngine returns the wrapped storage engine.
func (*AsyncEngine) GetNode ¶
func (ae *AsyncEngine) GetNode(id NodeID) (*Node, error)
GetNode checks cache first, then underlying engine.
func (*AsyncEngine) GetNodeCurrentHead ¶
func (ae *AsyncEngine) GetNodeCurrentHead(id NodeID) (MVCCHead, error)
GetNodeCurrentHead delegates node head lookup to the wrapped engine when supported.
func (*AsyncEngine) GetNodeLatestEffective ¶
func (ae *AsyncEngine) GetNodeLatestEffective(id NodeID) (*Node, error)
GetNodeLatestEffective returns the merged latest-visible node across pending, in-flight, and persisted state.
func (*AsyncEngine) GetNodeLatestVisible ¶
func (ae *AsyncEngine) GetNodeLatestVisible(id NodeID) (*Node, error)
GetNodeLatestVisible resolves the latest persisted-or-effective node.
func (*AsyncEngine) GetNodeVisibleAt ¶
func (ae *AsyncEngine) GetNodeVisibleAt(id NodeID, version MVCCVersion) (*Node, error)
GetNodeVisibleAt delegates snapshot-visible node reads to the wrapped engine when supported.
func (*AsyncEngine) GetNodesByLabel ¶
func (ae *AsyncEngine) GetNodesByLabel(label string) ([]*Node, error)
func (*AsyncEngine) GetNodesByLabelVisibleAt ¶
func (ae *AsyncEngine) GetNodesByLabelVisibleAt(label string, version MVCCVersion) ([]*Node, error)
GetNodesByLabelVisibleAt delegates snapshot-visible label queries to the wrapped engine when supported.
func (*AsyncEngine) GetOutDegree ¶
func (ae *AsyncEngine) GetOutDegree(nodeID NodeID) int
func (*AsyncEngine) GetOutgoingEdges ¶
func (ae *AsyncEngine) GetOutgoingEdges(nodeID NodeID) ([]*Edge, error)
func (*AsyncEngine) GetSchema ¶
func (ae *AsyncEngine) GetSchema() *SchemaManager
func (*AsyncEngine) GetSchemaForNamespace ¶
func (ae *AsyncEngine) GetSchemaForNamespace(namespace string) *SchemaManager
GetSchemaForNamespace implements NamespaceSchemaProvider when the underlying engine supports it.
func (*AsyncEngine) GetUnderlying ¶
func (ae *AsyncEngine) GetUnderlying() Engine
GetUnderlying returns the underlying storage engine. This is used for transaction support when the underlying engine supports ACID transactions (e.g., BadgerEngine).
func (*AsyncEngine) HasPendingWrites ¶
func (ae *AsyncEngine) HasPendingWrites() bool
HasPendingWrites returns true if there are unflushed writes. This is a cheap check that can be used to avoid unnecessary flush calls.
func (*AsyncEngine) HoldFlush ¶ added in v1.0.42
func (ae *AsyncEngine) HoldFlush() func()
HoldFlush acquires a shared flush guard and returns a release function.
While held, background or manual Flush calls block on flushMu.Lock(), which is useful when a higher-level transaction needs a stable committed view for its full lifetime. Regular async writes still queue into memory and will flush once the returned release function is called.
func (*AsyncEngine) IsCurrentTemporalNode ¶
IsCurrentTemporalNode delegates current-version checks to the wrapped engine when supported.
func (*AsyncEngine) IterateNodes ¶
func (ae *AsyncEngine) IterateNodes(fn func(*Node) bool) error
IterateNodes iterates through all nodes, checking cache first.
func (*AsyncEngine) LastWriteTime ¶
func (ae *AsyncEngine) LastWriteTime() time.Time
LastWriteTime returns the last known write time from the underlying engine, if available.
func (*AsyncEngine) LifecycleStatus ¶
func (ae *AsyncEngine) LifecycleStatus() map[string]interface{}
LifecycleStatus delegates lifecycle status when supported.
func (*AsyncEngine) ListNamespaces ¶
func (ae *AsyncEngine) ListNamespaces() []string
ListNamespaces returns known namespaces from the wrapped engine, if supported.
func (*AsyncEngine) MarkNodeEmbedded ¶
func (ae *AsyncEngine) MarkNodeEmbedded(nodeID NodeID)
MarkNodeEmbedded delegates to the underlying engine, if supported. This removes a node from the pending-embeddings secondary index once embedded.
func (*AsyncEngine) NodeCount ¶
func (ae *AsyncEngine) NodeCount() (int64, error)
func (*AsyncEngine) NodeCountByPrefix ¶
func (ae *AsyncEngine) NodeCountByPrefix(prefix string) (int64, error)
func (*AsyncEngine) OnEdgeCreated ¶
func (ae *AsyncEngine) OnEdgeCreated(callback EdgeEventCallback)
OnEdgeCreated sets a callback to be invoked when edges are created.
func (*AsyncEngine) OnEdgeDeleted ¶
func (ae *AsyncEngine) OnEdgeDeleted(callback EdgeDeleteCallback)
OnEdgeDeleted sets a callback to be invoked when edges are deleted.
func (*AsyncEngine) OnEdgeUpdated ¶
func (ae *AsyncEngine) OnEdgeUpdated(callback EdgeEventCallback)
OnEdgeUpdated sets a callback to be invoked when edges are updated.
func (*AsyncEngine) OnNodeCreated ¶
func (ae *AsyncEngine) OnNodeCreated(callback NodeEventCallback)
OnNodeCreated sets a callback to be invoked when nodes are created.
func (*AsyncEngine) OnNodeDeleted ¶
func (ae *AsyncEngine) OnNodeDeleted(callback NodeDeleteCallback)
OnNodeDeleted sets a callback to be invoked when nodes are deleted.
func (*AsyncEngine) OnNodeUpdated ¶
func (ae *AsyncEngine) OnNodeUpdated(callback NodeEventCallback)
OnNodeUpdated sets a callback to be invoked when nodes are updated.
func (*AsyncEngine) PauseLifecycle ¶
func (ae *AsyncEngine) PauseLifecycle()
PauseLifecycle delegates lifecycle pause when supported.
func (*AsyncEngine) PendingEmbeddingsCount ¶
func (ae *AsyncEngine) PendingEmbeddingsCount() int
PendingEmbeddingsCount delegates to the underlying engine, if supported.
func (*AsyncEngine) PruneMVCCVersions ¶
func (ae *AsyncEngine) PruneMVCCVersions(ctx context.Context, opts MVCCPruneOptions) (int64, error)
PruneMVCCVersions delegates MVCC pruning to the wrapped engine when supported.
func (*AsyncEngine) PruneTemporalHistory ¶
func (ae *AsyncEngine) PruneTemporalHistory(ctx context.Context, opts TemporalPruneOptions) (int64, error)
PruneTemporalHistory delegates temporal pruning to the wrapped engine when supported.
func (*AsyncEngine) RebuildMVCCHeads ¶
func (ae *AsyncEngine) RebuildMVCCHeads(ctx context.Context) error
RebuildMVCCHeads delegates MVCC head rebuild to the wrapped engine when supported.
func (*AsyncEngine) RebuildTemporalIndexes ¶
func (ae *AsyncEngine) RebuildTemporalIndexes(ctx context.Context) error
RebuildTemporalIndexes delegates temporal index rebuild to the wrapped engine when supported.
func (*AsyncEngine) RefreshPendingEmbeddingsIndex ¶
func (ae *AsyncEngine) RefreshPendingEmbeddingsIndex() int
RefreshPendingEmbeddingsIndex delegates to the underlying engine, if supported. This keeps the pending-embeddings secondary index consistent even when AsyncEngine is the outer-most storage layer.
func (*AsyncEngine) RegisterSnapshotReader ¶
func (ae *AsyncEngine) RegisterSnapshotReader(info SnapshotReaderInfo) func()
RegisterSnapshotReader delegates snapshot-reader registration when supported.
func (*AsyncEngine) ResumeLifecycle ¶
func (ae *AsyncEngine) ResumeLifecycle()
ResumeLifecycle delegates lifecycle resume when supported.
func (*AsyncEngine) SetLifecycleSchedule ¶
func (ae *AsyncEngine) SetLifecycleSchedule(interval time.Duration) error
SetLifecycleSchedule delegates lifecycle cadence updates when supported.
func (*AsyncEngine) Stats ¶
func (ae *AsyncEngine) Stats() (pendingWrites, totalFlushes int64)
Stats returns async engine statistics.
func (*AsyncEngine) StreamEdges ¶
StreamEdges implements StreamingEngine.StreamEdges by delegating to the underlying engine.
func (*AsyncEngine) StreamNodeChunks ¶
func (ae *AsyncEngine) StreamNodeChunks(ctx context.Context, chunkSize int, fn func(nodes []*Node) error) error
StreamNodeChunks implements StreamingEngine.StreamNodeChunks by using StreamNodes. We always use StreamNodes (not delegate) to properly merge cache + underlying engine.
func (*AsyncEngine) StreamNodes ¶
StreamNodes implements StreamingEngine.StreamNodes by delegating to the underlying engine. It merges cached nodes with the underlying stream for consistency.
func (*AsyncEngine) StreamNodesByPrefix ¶
func (ae *AsyncEngine) StreamNodesByPrefix(ctx context.Context, prefix string, fn func(node *Node) error) error
StreamNodesByPrefix implements PrefixStreamingEngine by merging pending cache entries with prefix-scoped streaming from the underlying engine.
func (*AsyncEngine) TopLifecycleDebtKeys ¶
func (ae *AsyncEngine) TopLifecycleDebtKeys(limit int) []MVCCLifecycleDebtKey
TopLifecycleDebtKeys delegates lifecycle debt inspection when supported.
func (*AsyncEngine) TriggerPruneNow ¶
func (ae *AsyncEngine) TriggerPruneNow(ctx context.Context) error
TriggerPruneNow delegates lifecycle prune-now when supported.
func (*AsyncEngine) UpdateEdge ¶
func (ae *AsyncEngine) UpdateEdge(edge *Edge) error
UpdateEdge adds to cache and returns immediately.
func (*AsyncEngine) UpdateNode ¶
func (ae *AsyncEngine) UpdateNode(node *Node) error
UpdateNode adds to cache and returns immediately.
func (*AsyncEngine) UpdateNodeEmbedding ¶
func (ae *AsyncEngine) UpdateNodeEmbedding(node *Node) error
UpdateNodeEmbedding updates an existing node with its embedding. Unlike UpdateNode, this MUST NOT create a new node; it returns ErrNotFound if the node does not exist (in cache, in-flight, or in the underlying engine).
type AsyncEngineConfig ¶
type AsyncEngineConfig struct {
// FlushInterval controls how often pending writes are flushed.
// Smaller = more consistent, larger = better throughput.
// Default: 50ms
FlushInterval time.Duration
// AdaptiveFlush enables volume-based flush timing.
// When enabled, the flush loop ticks at MinFlushInterval and only
// flushes when the adaptive interval has elapsed.
AdaptiveFlush bool
// MinFlushInterval is the shortest interval between flushes when adaptive flush is enabled.
// Default: 10ms
MinFlushInterval time.Duration
// MaxFlushInterval is the longest interval between flushes when adaptive flush is enabled.
// Default: 200ms
MaxFlushInterval time.Duration
// TargetFlushSize is the pending write count at which we reach MaxFlushInterval.
// Smaller batches flush more frequently; larger batches flush less frequently.
// Default: 1000 pending writes
TargetFlushSize int
// MaxNodeCacheSize is the maximum number of nodes to buffer before forcing a flush.
// When this limit is reached, CreateNode will block and flush synchronously.
// This prevents unbounded memory growth during bulk inserts.
// Set to 0 for unlimited (not recommended for bulk operations).
// Default: 50000 (50K nodes, ~35MB assuming 700 bytes/node)
MaxNodeCacheSize int
// MaxEdgeCacheSize is the maximum number of edges to buffer before forcing a flush.
// When this limit is reached, CreateEdge will block and flush synchronously.
// This prevents unbounded memory growth during bulk inserts.
// Set to 0 for unlimited (not recommended for bulk operations).
// Default: 100000 (100K edges, ~50MB assuming 500 bytes/edge)
MaxEdgeCacheSize int
}
AsyncEngineConfig configures the async engine behavior.
func DefaultAsyncEngineConfig ¶
func DefaultAsyncEngineConfig() *AsyncEngineConfig
DefaultAsyncEngineConfig returns sensible defaults.
type BadgerEngine ¶
type BadgerEngine struct {
// contains filtered or unexported fields
}
BadgerEngine provides persistent storage using BadgerDB.
Features:
- ACID transactions for all operations
- Persistent storage to disk
- Secondary indexes for efficient queries
- Thread-safe concurrent access
- Automatic crash recovery
Key Structure:
- Nodes: 0x01 + nodeID -> JSON(Node)
- Edges: 0x02 + edgeID -> JSON(Edge)
- Label Index: 0x03 + label + 0x00 + nodeID -> empty
- Outgoing Index: 0x04 + nodeID + 0x00 + edgeID -> empty
- Incoming Index: 0x05 + nodeID + 0x00 + edgeID -> empty
- Edge-Between Set: 0x11 + startID + 0x00 + endID + 0x00 + type + 0x00 + edgeID -> empty
- Edge-Between Head: 0x12 + startID + 0x00 + endID + 0x00 + type -> edgeID
Example:
engine, err := storage.NewBadgerEngine("/path/to/data")
if err != nil {
log.Fatal(err)
}
defer engine.Close()
node := &storage.Node{
ID: "user-123",
Labels: []string{"User"},
Properties: map[string]any{"name": "Alice"},
}
engine.CreateNode(node)
func NewBadgerEngine ¶
func NewBadgerEngine(dataDir string) (*BadgerEngine, error)
NewBadgerEngine creates a new persistent storage engine with default settings.
This is the simplest way to create a storage engine. The engine uses BadgerDB for persistent disk storage with ACID transaction guarantees. All data is stored in the specified directory and persists across restarts.
Parameters:
- dataDir: Directory path for storing data files. Created if it doesn't exist.
Returns:
- *BadgerEngine on success
- error if database cannot be opened (e.g., permissions, disk space)
Example 1 - Basic Usage:
engine, err := storage.NewBadgerEngine("./data/nornicdb")
if err != nil {
log.Fatal(err)
}
defer engine.Close()
// Engine is ready - create nodes
node := &storage.Node{
ID: "user-1",
Labels: []string{"User"},
Properties: map[string]any{"name": "Alice"},
}
engine.CreateNode(node)
Example 2 - Production Application:
// Use absolute path for production
dataDir := filepath.Join(os.Getenv("APP_HOME"), "data", "nornicdb")
engine, err := storage.NewBadgerEngine(dataDir)
if err != nil {
return fmt.Errorf("failed to open database: %w", err)
}
defer engine.Close()
Example 3 - Multiple Databases:
// Main application database
mainDB, _ := storage.NewBadgerEngine("./data/main")
defer mainDB.Close()
// Test database
testDB, _ := storage.NewBadgerEngine("./data/test")
defer testDB.Close()
// Cache database
cacheDB, _ := storage.NewBadgerEngine("./data/cache")
defer cacheDB.Close()
ELI12:
Think of NewBadgerEngine like setting up a filing cabinet in your room. You tell it "put the cabinet here" (the dataDir), and it creates folders and organizes everything. Even if you turn off your computer, the cabinet stays there with all your files inside. Next time you start up, all your data is still there!
Disk Usage:
- Approximately 2-3x the size of your actual data
- Includes write-ahead log and compaction overhead
Thread Safety:
Safe for concurrent use from multiple goroutines.
func NewBadgerEngineInMemory ¶
func NewBadgerEngineInMemory() (*BadgerEngine, error)
NewBadgerEngineInMemory creates an in-memory BadgerDB for testing.
Data is not persisted and is lost when the engine is closed. Useful for unit tests that need persistent storage semantics without actual disk I/O.
Example:
engine, err := storage.NewBadgerEngineInMemory()
if err != nil {
t.Fatal(err)
}
defer engine.Close()
// Use engine for testing...
func NewBadgerEngineWithOptions ¶
func NewBadgerEngineWithOptions(opts BadgerOptions) (*BadgerEngine, error)
NewBadgerEngineWithOptions creates a BadgerEngine with custom configuration.
Use this function when you need fine-grained control over the storage engine behavior, such as enabling in-memory mode for testing, forcing synchronous writes for maximum durability, or reducing memory usage.
Parameters:
- opts: BadgerOptions struct with configuration settings
Returns:
- *BadgerEngine on success
- error if database cannot be opened
Example 1 - In-Memory Database for Testing:
engine, err := storage.NewBadgerEngineWithOptions(storage.BadgerOptions{
DataDir: "./test", // Still needs a path but won't be used
InMemory: true, // All data in RAM, lost on shutdown
})
defer engine.Close()
// Perfect for unit tests - fast and clean
testCreateNodes(engine)
Example 2 - Maximum Durability for Financial Data:
engine, err := storage.NewBadgerEngineWithOptions(storage.BadgerOptions{
DataDir: "./data/transactions",
SyncWrites: true, // Force fsync after each write (slower but safer)
})
// Guaranteed data persistence even if power fails
Example 3 - Low Memory Mode for Embedded Devices:
engine, err := storage.NewBadgerEngineWithOptions(storage.BadgerOptions{
DataDir: "./data/nornicdb",
LowMemory: true, // Reduces RAM usage by 50-70%
})
// Uses ~50MB instead of ~150MB for typical workloads
Example 4 - Custom Logger Integration:
logger := zerolog.New(os.Stdout).With().Timestamp().Logger()
engine, err := storage.NewBadgerEngineWithOptions(storage.BadgerOptions{
DataDir: "./data/nornicdb",
Logger: &BadgerLogger{zlog: logger}, // Custom logging
})
ELI12:
NewBadgerEngine is like getting a basic backpack for school. NewBadgerEngineWithOptions is like customizing your backpack - you can:
- Make it waterproof (SyncWrites = true)
- Make it lighter but less storage (LowMemory = true)
- Use it as a temporary bag (InMemory = true)
- Add custom labels (Logger)
Configuration Trade-offs:
- SyncWrites=true: Slower writes (2-5x) but maximum safety
- LowMemory=true: Less RAM but slightly slower
- InMemory=true: Fastest but data lost on shutdown
Thread Safety:
Safe for concurrent use from multiple goroutines.
func (*BadgerEngine) AddToPendingEmbeddings ¶
func (b *BadgerEngine) AddToPendingEmbeddings(nodeID NodeID)
AddToPendingEmbeddings adds a node to the pending embeddings index. Call this when creating a node that needs embedding.
func (*BadgerEngine) AllEdges ¶
func (b *BadgerEngine) AllEdges() ([]*Edge, error)
AllEdges returns all edges (implements Engine interface).
func (*BadgerEngine) AllNodes ¶
func (b *BadgerEngine) AllNodes() ([]*Node, error)
AllNodes returns all nodes (implements Engine interface).
func (*BadgerEngine) AppendEdgeTombstone ¶
func (b *BadgerEngine) AppendEdgeTombstone(id EdgeID, version MVCCVersion) error
func (*BadgerEngine) AppendEdgeVersion ¶
func (b *BadgerEngine) AppendEdgeVersion(edge *Edge, version MVCCVersion) error
func (*BadgerEngine) AppendNodeTombstone ¶
func (b *BadgerEngine) AppendNodeTombstone(id NodeID, version MVCCVersion) error
func (*BadgerEngine) AppendNodeVersion ¶
func (b *BadgerEngine) AppendNodeVersion(node *Node, version MVCCVersion) error
func (*BadgerEngine) Backup ¶
func (b *BadgerEngine) Backup(path string) error
Backup creates a backup of the database to the specified file path. Uses BadgerDB's streaming backup which creates a consistent snapshot. The backup file is a self-contained, portable copy of the database.
func (*BadgerEngine) BatchGetNodes ¶
func (b *BadgerEngine) BatchGetNodes(ids []NodeID) (map[NodeID]*Node, error)
BatchGetNodes fetches multiple nodes in a single transaction. Returns a map for O(1) lookup by ID. Missing nodes are not included in the result. This is optimized for traversal operations that need to fetch many nodes.
func (*BadgerEngine) BatchGetNodesLatestVisible ¶
func (b *BadgerEngine) BatchGetNodesLatestVisible(ids []NodeID) (map[NodeID]*Node, error)
func (*BadgerEngine) BeginTransaction ¶
func (b *BadgerEngine) BeginTransaction() (*BadgerTransaction, error)
BeginTransaction starts a new Badger transaction with ACID guarantees.
func (*BadgerEngine) BulkCreateEdges ¶
func (b *BadgerEngine) BulkCreateEdges(edges []*Edge) error
BulkCreateEdges creates multiple edges in a single transaction.
func (*BadgerEngine) BulkCreateNodes ¶
func (b *BadgerEngine) BulkCreateNodes(nodes []*Node) error
BulkCreateNodes creates multiple nodes in a single transaction.
func (*BadgerEngine) BulkDeleteEdges ¶
func (b *BadgerEngine) BulkDeleteEdges(ids []EdgeID) error
BulkDeleteEdges removes multiple edges in a single transaction. This is much faster than calling DeleteEdge repeatedly.
func (*BadgerEngine) BulkDeleteNodes ¶
func (b *BadgerEngine) BulkDeleteNodes(ids []NodeID) error
BulkDeleteNodes removes multiple nodes in a single transaction. This is much faster than calling DeleteNode repeatedly. IMPORTANT: This also deletes all edges connected to the deleted nodes and updates edge counts.
func (*BadgerEngine) ClearAllEmbeddings ¶
func (b *BadgerEngine) ClearAllEmbeddings() (int, error)
ClearAllEmbeddings removes embeddings from all nodes, allowing them to be regenerated. Returns the number of nodes that had their embeddings cleared.
func (*BadgerEngine) ClearAllEmbeddingsForPrefix ¶
func (b *BadgerEngine) ClearAllEmbeddingsForPrefix(idPrefix string) (int, error)
ClearAllEmbeddingsForPrefix removes embeddings from nodes whose IDs start with the given prefix. This is used to clear embeddings for a single logical database namespace (e.g., "nornic:").
If idPrefix is empty, clears embeddings for all nodes.
func (*BadgerEngine) Close ¶
func (b *BadgerEngine) Close() error
Close closes the BadgerDB database.
func (*BadgerEngine) CreateEdge ¶
func (b *BadgerEngine) CreateEdge(edge *Edge) error
CreateEdge creates a new edge between two nodes.
func (*BadgerEngine) CreateNode ¶
func (b *BadgerEngine) CreateNode(node *Node) (NodeID, error)
CreateNode creates a new node in persistent storage. REQUIRES: node.ID must be prefixed with namespace (e.g., "nornic:node-123"). This enforces that all nodes are namespaced at the storage layer.
func (*BadgerEngine) DataDirFreeSpace ¶
func (b *BadgerEngine) DataDirFreeSpace() (int64, error)
DataDirFreeSpace returns free bytes for the underlying data directory.
func (*BadgerEngine) DeleteByPrefix ¶
func (b *BadgerEngine) DeleteByPrefix(prefix string) (nodesDeleted int64, edgesDeleted int64, err error)
DeleteByPrefix deletes all nodes and edges with IDs starting with the given prefix. Used for DROP DATABASE operations to delete all data in a namespace.
This uses Badger's native prefix drop for db-scoped keyspaces to avoid per-node decoding and DeleteNode/DeleteEdge loops. Secondary indexes that don't begin with the node/edge ID (label and edge-type indexes) are cleaned up by scanning those index keyspaces and deleting entries whose suffix IDs match the prefix.
func (*BadgerEngine) DeleteEdge ¶
func (b *BadgerEngine) DeleteEdge(id EdgeID) error
DeleteEdge removes an edge.
func (*BadgerEngine) DeleteMVCCVersion ¶
func (b *BadgerEngine) DeleteMVCCVersion(ctx context.Context, logicalKey []byte, version MVCCVersion) error
DeleteMVCCVersion deletes a single MVCC version for a logical key.
func (*BadgerEngine) DeleteNode ¶
func (b *BadgerEngine) DeleteNode(id NodeID) error
DeleteNode removes a node and all its edges.
func (*BadgerEngine) EdgeCount ¶
func (b *BadgerEngine) EdgeCount() (int64, error)
EdgeCount returns the total number of valid, decodable edges. This is consistent with AllEdges() - only counts edges that can be successfully decoded.
func (*BadgerEngine) EdgeCountByPrefix ¶
func (b *BadgerEngine) EdgeCountByPrefix(prefix string) (int64, error)
EdgeCountByPrefix counts edges whose EdgeID begins with the provided prefix. The prefix refers to the EdgeID string prefix (e.g., database namespace "nornic:").
func (*BadgerEngine) FindNodeNeedingEmbedding ¶
func (b *BadgerEngine) FindNodeNeedingEmbedding() *Node
FindNodeNeedingEmbedding returns a node that needs embedding. Uses Badger's secondary index (prefixPendingEmbed) for O(1) lookup.
This is highly optimized: - O(1) to find next node (just seek to prefix and get first key) - No in-memory index needed - Persistent across restarts - Atomic with node operations
CRITICAL: This method aggressively cleans up stale entries to prevent processing non-existent nodes. It will skip up to 100 stale entries before giving up to prevent infinite loops.
func (*BadgerEngine) ForEachNodeIDByLabel ¶
func (b *BadgerEngine) ForEachNodeIDByLabel(label string, visit func(NodeID) bool) error
ForEachNodeIDByLabel streams node IDs for a label without decoding nodes. Stops early when visit returns false.
func (*BadgerEngine) GetAllNodes ¶
func (b *BadgerEngine) GetAllNodes() []*Node
GetAllNodes returns all nodes in the storage.
func (*BadgerEngine) GetEdge ¶
func (b *BadgerEngine) GetEdge(id EdgeID) (*Edge, error)
GetEdge retrieves an edge by ID.
func (*BadgerEngine) GetEdgeBetween ¶
func (b *BadgerEngine) GetEdgeBetween(source, target NodeID, edgeType string) *Edge
GetEdgeBetween returns an edge between two nodes with the given type.
func (*BadgerEngine) GetEdgeCurrentHead ¶
func (b *BadgerEngine) GetEdgeCurrentHead(id EdgeID) (MVCCHead, error)
func (*BadgerEngine) GetEdgeLatestVisible ¶
func (b *BadgerEngine) GetEdgeLatestVisible(id EdgeID) (*Edge, error)
func (*BadgerEngine) GetEdgeVisibleAt ¶
func (b *BadgerEngine) GetEdgeVisibleAt(id EdgeID, version MVCCVersion) (*Edge, error)
func (*BadgerEngine) GetEdgesBetween ¶
func (b *BadgerEngine) GetEdgesBetween(startID, endID NodeID) ([]*Edge, error)
GetEdgesBetween returns all edges between two nodes.
func (*BadgerEngine) GetEdgesBetweenVisibleAt ¶
func (b *BadgerEngine) GetEdgesBetweenVisibleAt(startID, endID NodeID, version MVCCVersion) ([]*Edge, error)
func (*BadgerEngine) GetEdgesByType ¶
func (b *BadgerEngine) GetEdgesByType(edgeType string) ([]*Edge, error)
GetEdgesByType returns all edges of a specific type using the edge type index. This is MUCH faster than AllEdges() for queries like mutual follows. Edge types are matched case-insensitively (Neo4j compatible). Results are cached per type to speed up repeated queries.
func (*BadgerEngine) GetEdgesByTypeVisibleAt ¶
func (b *BadgerEngine) GetEdgesByTypeVisibleAt(edgeType string, version MVCCVersion) ([]*Edge, error)
func (*BadgerEngine) GetFirstNodeByLabel ¶
func (b *BadgerEngine) GetFirstNodeByLabel(label string) (*Node, error)
GetFirstNodeByLabel returns the first node with the specified label. This is optimized for MATCH...LIMIT 1 patterns - stops after first match.
func (*BadgerEngine) GetInDegree ¶
func (b *BadgerEngine) GetInDegree(nodeID NodeID) int
GetInDegree returns the number of incoming edges to a node.
func (*BadgerEngine) GetIncomingEdges ¶
func (b *BadgerEngine) GetIncomingEdges(nodeID NodeID) ([]*Edge, error)
GetIncomingEdges returns all edges where the given node is the target.
func (*BadgerEngine) GetNode ¶
func (b *BadgerEngine) GetNode(id NodeID) (*Node, error)
GetNode retrieves a node by ID.
func (*BadgerEngine) GetNodeCurrentHead ¶
func (b *BadgerEngine) GetNodeCurrentHead(id NodeID) (MVCCHead, error)
func (*BadgerEngine) GetNodeLatestVisible ¶
func (b *BadgerEngine) GetNodeLatestVisible(id NodeID) (*Node, error)
func (*BadgerEngine) GetNodeVisibleAt ¶
func (b *BadgerEngine) GetNodeVisibleAt(id NodeID, version MVCCVersion) (*Node, error)
func (*BadgerEngine) GetNodesByLabel ¶
func (b *BadgerEngine) GetNodesByLabel(label string) ([]*Node, error)
GetNodesByLabel returns all nodes with the specified label.
func (*BadgerEngine) GetNodesByLabelVisibleAt ¶
func (b *BadgerEngine) GetNodesByLabelVisibleAt(label string, version MVCCVersion) ([]*Node, error)
func (*BadgerEngine) GetOutDegree ¶
func (b *BadgerEngine) GetOutDegree(nodeID NodeID) int
GetOutDegree returns the number of outgoing edges from a node.
func (*BadgerEngine) GetOutgoingEdges ¶
func (b *BadgerEngine) GetOutgoingEdges(nodeID NodeID) ([]*Edge, error)
GetOutgoingEdges returns all edges where the given node is the source.
func (*BadgerEngine) GetSchema ¶
func (b *BadgerEngine) GetSchema() *SchemaManager
GetSchema returns the schema manager.
func (*BadgerEngine) GetSchemaForNamespace ¶
func (b *BadgerEngine) GetSchemaForNamespace(namespace string) *SchemaManager
GetSchemaForNamespace returns the schema for a specific database namespace. If no schema exists yet, an empty schema is created (and will be persisted once mutated).
func (*BadgerEngine) GetTemporalNodeAsOfInNamespace ¶
func (*BadgerEngine) HasLabelBatch ¶
HasLabelBatch checks label membership for a batch of node IDs using the label index. This avoids decoding node records and is significantly faster for large batches.
func (*BadgerEngine) InvalidateEdgeTypeCache ¶
func (b *BadgerEngine) InvalidateEdgeTypeCache()
InvalidateEdgeTypeCache clears the entire edge type cache. Called after bulk edge mutations to ensure cache consistency.
func (*BadgerEngine) InvalidateEdgeTypeCacheForType ¶
func (b *BadgerEngine) InvalidateEdgeTypeCacheForType(edgeType string)
InvalidateEdgeTypeCacheForType removes only the specified edge type from cache. Much faster than full invalidation for single-edge operations.
func (*BadgerEngine) InvalidatePendingEmbeddingsIndex ¶
func (b *BadgerEngine) InvalidatePendingEmbeddingsIndex()
InvalidatePendingEmbeddingsIndex is a no-op for Badger index. The index is persistent and doesn't need invalidation.
func (*BadgerEngine) IsCurrentTemporalNode ¶
IsCurrentTemporalNode reports whether the given temporal node is the live/current version.
func (*BadgerEngine) IsCurrentTemporalNodeInNamespace ¶
func (b *BadgerEngine) IsCurrentTemporalNodeInNamespace(namespace string, node *Node, asOf time.Time) (bool, error)
IsCurrentTemporalNodeInNamespace reports whether the given temporal node is the live/current version.
func (*BadgerEngine) IsInMemory ¶
func (b *BadgerEngine) IsInMemory() bool
IsInMemory returns true if the engine is running in memory-only mode. In-memory mode is used for testing - there's no disk to fsync to.
func (*BadgerEngine) IterateLatestVisibleEdges ¶
func (b *BadgerEngine) IterateLatestVisibleEdges(yield func(*Edge) error) error
func (*BadgerEngine) IterateLatestVisibleNodes ¶
func (b *BadgerEngine) IterateLatestVisibleNodes(yield func(*Node) error) error
func (*BadgerEngine) IterateMVCCHeads ¶
func (b *BadgerEngine) IterateMVCCHeads(ctx context.Context, yield func(logicalKey []byte, head MVCCHead) error) error
IterateMVCCHeads iterates all persisted MVCC heads.
func (*BadgerEngine) IterateMVCCVersions ¶
func (b *BadgerEngine) IterateMVCCVersions(ctx context.Context, logicalKey []byte, yield func(version MVCCVersion, tombstoned bool, sizeBytes int64) error) error
IterateMVCCVersions iterates all versions for a logical key.
func (*BadgerEngine) IterateNodes ¶
func (b *BadgerEngine) IterateNodes(fn func(*Node) bool) error
IterateNodes iterates through all nodes one at a time without loading all into memory. The callback returns true to continue, false to stop.
func (*BadgerEngine) LifecycleStatus ¶
func (b *BadgerEngine) LifecycleStatus() map[string]interface{}
LifecycleStatus reports lifecycle status when enabled.
func (*BadgerEngine) ListNamespaces ¶
func (b *BadgerEngine) ListNamespaces() []string
ListNamespaces returns the set of database namespaces currently present in this Badger engine, derived from the cached per-namespace node/edge counters.
Namespaces are returned without the trailing ':' (e.g., "nornic", "db2").
func (*BadgerEngine) MarkNodeEmbedded ¶
func (b *BadgerEngine) MarkNodeEmbedded(nodeID NodeID)
MarkNodeEmbedded removes a node from the pending embeddings index. Call this after successfully embedding a node.
func (*BadgerEngine) NodeCount ¶
func (b *BadgerEngine) NodeCount() (int64, error)
func (*BadgerEngine) NodeCountByPrefix ¶
func (b *BadgerEngine) NodeCountByPrefix(prefix string) (int64, error)
NodeCountByPrefix counts nodes whose NodeID begins with the provided prefix. The prefix refers to the NodeID string prefix (e.g., database namespace "nornic:").
This is an optional fast-path used by NamespacedEngine to provide accurate per-database counts without decoding values.
func (*BadgerEngine) OnEdgeCreated ¶
func (b *BadgerEngine) OnEdgeCreated(callback EdgeEventCallback)
OnEdgeCreated sets a callback to be invoked when edges are created. Implements StorageEventNotifier interface.
func (*BadgerEngine) OnEdgeDeleted ¶
func (b *BadgerEngine) OnEdgeDeleted(callback EdgeDeleteCallback)
OnEdgeDeleted sets a callback to be invoked when edges are deleted. Implements StorageEventNotifier interface.
func (*BadgerEngine) OnEdgeUpdated ¶
func (b *BadgerEngine) OnEdgeUpdated(callback EdgeEventCallback)
OnEdgeUpdated sets a callback to be invoked when edges are updated. Implements StorageEventNotifier interface.
func (*BadgerEngine) OnNodeCreated ¶
func (b *BadgerEngine) OnNodeCreated(callback NodeEventCallback)
OnNodeCreated sets a callback to be invoked when nodes are created. Implements StorageEventNotifier interface.
func (*BadgerEngine) OnNodeDeleted ¶
func (b *BadgerEngine) OnNodeDeleted(callback NodeDeleteCallback)
OnNodeDeleted sets a callback to be invoked when nodes are deleted. Implements StorageEventNotifier interface.
func (*BadgerEngine) OnNodeUpdated ¶
func (b *BadgerEngine) OnNodeUpdated(callback NodeEventCallback)
OnNodeUpdated sets a callback to be invoked when nodes are updated. Implements StorageEventNotifier interface.
func (*BadgerEngine) PauseLifecycle ¶
func (b *BadgerEngine) PauseLifecycle()
PauseLifecycle pauses lifecycle work.
func (*BadgerEngine) PendingEmbeddingsCount ¶
func (b *BadgerEngine) PendingEmbeddingsCount() int
PendingEmbeddingsCount returns the number of nodes waiting for embedding. Note: This requires a scan of the pending index, so use sparingly.
func (*BadgerEngine) PruneMVCCVersions ¶
func (b *BadgerEngine) PruneMVCCVersions(ctx context.Context, opts MVCCPruneOptions) (int64, error)
func (*BadgerEngine) PruneTemporalHistory ¶
func (b *BadgerEngine) PruneTemporalHistory(ctx context.Context, opts TemporalPruneOptions) (int64, error)
PruneTemporalHistory removes older closed temporal versions according to opts.
func (*BadgerEngine) ReadMVCCHead ¶
ReadMVCCHead loads the current MVCC head for a logical key.
func (*BadgerEngine) RebuildMVCCHeads ¶
func (b *BadgerEngine) RebuildMVCCHeads(ctx context.Context) error
func (*BadgerEngine) RebuildTemporalIndexes ¶
func (b *BadgerEngine) RebuildTemporalIndexes(ctx context.Context) error
RebuildTemporalIndexes recreates the temporal history and current-pointer indexes from stored nodes.
func (*BadgerEngine) RefreshPendingEmbeddingsIndex ¶
func (b *BadgerEngine) RefreshPendingEmbeddingsIndex() int
RefreshPendingEmbeddingsIndex rebuilds the pending embeddings index. This scans all nodes and adds any missing ones to the index. It also removes stale entries for nodes that no longer exist or already have embeddings. Use this on startup or after bulk imports.
func (*BadgerEngine) RegisterSnapshotReader ¶
func (b *BadgerEngine) RegisterSnapshotReader(info SnapshotReaderInfo) func()
RegisterSnapshotReader delegates reader registration when lifecycle is enabled.
func (*BadgerEngine) ResumeLifecycle ¶
func (b *BadgerEngine) ResumeLifecycle()
ResumeLifecycle resumes lifecycle work.
func (*BadgerEngine) RunGC ¶
func (b *BadgerEngine) RunGC() error
RunGC runs garbage collection on the BadgerDB value log. Should be called periodically for long-running applications.
func (*BadgerEngine) SetLifecycleController ¶
func (b *BadgerEngine) SetLifecycleController(controller MVCCLifecycleController)
SetLifecycleController injects the MVCC lifecycle controller.
func (*BadgerEngine) SetLifecycleSchedule ¶
func (b *BadgerEngine) SetLifecycleSchedule(interval time.Duration) error
SetLifecycleSchedule updates lifecycle cadence when supported by the controller.
func (*BadgerEngine) Size ¶
func (b *BadgerEngine) Size() (lsm, vlog int64)
Size returns the approximate size of the database in bytes.
func (*BadgerEngine) StartLifecycleManager ¶
func (b *BadgerEngine) StartLifecycleManager(ctx context.Context)
StartLifecycleManager starts the injected lifecycle manager.
func (*BadgerEngine) StreamEdges ¶
StreamEdges implements StreamingEngine.StreamEdges for memory-efficient iteration. Iterates through all edges one at a time without loading all into memory.
func (*BadgerEngine) StreamNodeChunks ¶
func (b *BadgerEngine) StreamNodeChunks(ctx context.Context, chunkSize int, fn func(nodes []*Node) error) error
StreamNodeChunks implements StreamingEngine.StreamNodeChunks for batch processing. Iterates through nodes in chunks, more efficient for batch operations.
func (*BadgerEngine) StreamNodes ¶
StreamNodes implements StreamingEngine.StreamNodes for memory-efficient iteration. Iterates through all nodes one at a time without loading all into memory.
func (*BadgerEngine) StreamNodesByPrefix ¶
func (b *BadgerEngine) StreamNodesByPrefix(ctx context.Context, prefix string, fn func(node *Node) error) error
StreamNodesByPrefix streams nodes whose IDs start with prefix. This is significantly faster than full StreamNodes + callback filtering when tenants/databases share a physical store.
func (*BadgerEngine) Sync ¶
func (b *BadgerEngine) Sync() error
Sync forces a sync of all data to disk. This is useful for ensuring durability before a crash.
func (*BadgerEngine) TopLifecycleDebtKeys ¶
func (b *BadgerEngine) TopLifecycleDebtKeys(limit int) []MVCCLifecycleDebtKey
TopLifecycleDebtKeys returns the highest-debt keys when supported by the controller.
func (*BadgerEngine) TriggerPruneNow ¶
func (b *BadgerEngine) TriggerPruneNow(ctx context.Context) error
TriggerPruneNow runs an immediate lifecycle prune.
func (*BadgerEngine) UpdateEdge ¶
func (b *BadgerEngine) UpdateEdge(edge *Edge) error
UpdateEdge updates an existing edge.
func (*BadgerEngine) UpdateEdgeCurrentHead ¶
func (b *BadgerEngine) UpdateEdgeCurrentHead(id EdgeID, version MVCCVersion, tombstoned bool) error
func (*BadgerEngine) UpdateNode ¶
func (b *BadgerEngine) UpdateNode(node *Node) error
UpdateNode updates an existing node or creates it if it doesn't exist (upsert).
func (*BadgerEngine) UpdateNodeCurrentHead ¶
func (b *BadgerEngine) UpdateNodeCurrentHead(id NodeID, version MVCCVersion, tombstoned bool) error
func (*BadgerEngine) UpdateNodeEmbedding ¶
func (b *BadgerEngine) UpdateNodeEmbedding(node *Node) error
UpdateNodeEmbedding updates only the embedding field of an existing node. Returns ErrNotFound if the node doesn't exist (does NOT create the node). This is used by the embedding queue to prevent creating orphaned nodes. REQUIRES: node.ID must be prefixed with namespace (e.g., "nornic:node-123").
func (*BadgerEngine) ValidateConstraintOnCreation ¶
func (b *BadgerEngine) ValidateConstraintOnCreation(c Constraint) error
ValidateConstraintOnCreation validates that all existing data satisfies the constraint. This is called when CREATE CONSTRAINT is executed, matching Neo4j behavior.
func (*BadgerEngine) ValidatePropertyTypeConstraintOnCreation ¶
func (b *BadgerEngine) ValidatePropertyTypeConstraintOnCreation(ptc PropertyTypeConstraint) error
ValidatePropertyTypeConstraintOnCreation validates existing data against type constraint.
func (*BadgerEngine) ValidateRelationshipConstraint ¶
func (b *BadgerEngine) ValidateRelationshipConstraint(rc RelationshipConstraint) error
ValidateRelationshipConstraint validates relationship property constraints.
func (*BadgerEngine) WriteMVCCHead ¶
WriteMVCCHead writes an updated MVCC head for a logical key.
type BadgerOptions ¶
type BadgerOptions struct {
// DataDir is the directory for storing data files.
// Required.
DataDir string
// InMemory runs BadgerDB in memory-only mode.
// Useful for testing. Data is not persisted.
InMemory bool
// SyncWrites forces fsync after each write.
// Slower but more durable.
SyncWrites bool
// Logger for BadgerDB internal logging.
// If nil, BadgerDB's default logger is used.
Logger badger.Logger
// LowMemory enables memory-constrained settings.
// Reduces MemTableSize and other buffers to use less RAM.
LowMemory bool
// HighPerformance enables aggressive caching and larger buffers.
// Uses more RAM but significantly faster writes/reads.
HighPerformance bool
// EncryptionKey is the 16, 24, or 32 byte key for AES encryption.
// If provided, all data will be encrypted at rest using AES-CTR.
// WARNING: If you lose this key, your data is irrecoverable!
// Leave empty to disable encryption.
EncryptionKey []byte
// Serializer selects the storage serialization format ("gob", "msgpack").
// Empty means default (gob).
Serializer StorageSerializer
// NodeCacheMaxEntries is the maximum number of nodes held in the in-process
// hot node cache (used by GetNode). When exceeded, the cache is cleared.
// Set to 0 to use the default.
NodeCacheMaxEntries int
// EdgeTypeCacheMaxTypes is the maximum number of distinct edge types cached
// for GetEdgesByType. When exceeded, the cache is cleared.
// Set to 0 to use the default.
EdgeTypeCacheMaxTypes int
// LabelFirstNodeCacheMaxEntries is the maximum number of labels cached for
// fast label-first lookups. When exceeded, the cache is cleared.
// Set to 0 to use the default.
LabelFirstNodeCacheMaxEntries int
// EngineOptions holds engine-wide MVCC retention defaults and similar policies.
EngineOptions EngineOptions
}
BadgerOptions configures the BadgerDB engine.
type BadgerTransaction ¶
type BadgerTransaction struct {
// Transaction identity
ID string
StartTime time.Time
Status TransactionStatus
// CommitVersion is assigned once for a successful commit that mutates storage.
CommitVersion MVCCVersion
// Transaction metadata (for logging/debugging)
Metadata map[string]interface{}
// contains filtered or unexported fields
}
BadgerTransaction wraps Badger's native transaction with constraint validation.
Provides ACID guarantees:
- Atomicity: All operations commit together or none do
- Consistency: Constraints are validated before commit
- Isolation: Changes invisible until commit
- Durability: Badger's WAL ensures persistence
func (*BadgerTransaction) AllNodes ¶ added in v1.0.42
func (tx *BadgerTransaction) AllNodes() ([]*Node, error)
AllNodes returns all visible nodes including pending transaction writes.
func (*BadgerTransaction) Commit ¶
func (tx *BadgerTransaction) Commit() error
Commit applies all changes atomically with full constraint validation. Explicit transactions get strict ACID durability with immediate fsync.
func (*BadgerTransaction) CreateEdge ¶
func (tx *BadgerTransaction) CreateEdge(edge *Edge) error
CreateEdge adds an edge to the transaction.
func (*BadgerTransaction) CreateNode ¶
func (tx *BadgerTransaction) CreateNode(node *Node) (NodeID, error)
CreateNode adds a node to the transaction with constraint validation. REQUIRES: node.ID must be prefixed with namespace (e.g., "nornic:node-123"). This enforces that all nodes are namespaced at the storage layer.
func (*BadgerTransaction) DeleteEdge ¶
func (tx *BadgerTransaction) DeleteEdge(edgeID EdgeID) error
DeleteEdge deletes an edge from the transaction.
func (*BadgerTransaction) DeleteNode ¶
func (tx *BadgerTransaction) DeleteNode(nodeID NodeID) error
DeleteNode deletes a node from the transaction.
func (*BadgerTransaction) GetAllNodes ¶ added in v1.0.42
func (tx *BadgerTransaction) GetAllNodes() []*Node
func (*BadgerTransaction) GetEdge ¶
func (tx *BadgerTransaction) GetEdge(edgeID EdgeID) (*Edge, error)
GetEdge retrieves an edge with read-your-writes semantics.
func (*BadgerTransaction) GetEdgeBetween ¶
func (tx *BadgerTransaction) GetEdgeBetween(startID, endID NodeID, edgeType string) *Edge
GetEdgeBetween returns a matching edge including pending transaction writes.
func (*BadgerTransaction) GetEdgesBetween ¶
func (tx *BadgerTransaction) GetEdgesBetween(startID, endID NodeID) ([]*Edge, error)
GetEdgesBetween returns edges between two nodes including pending transaction writes.
func (*BadgerTransaction) GetEdgesByType ¶
func (tx *BadgerTransaction) GetEdgesByType(edgeType string) ([]*Edge, error)
GetEdgesByType returns edges of a given type including pending transaction writes.
func (*BadgerTransaction) GetFirstNodeByLabel ¶ added in v1.0.42
func (tx *BadgerTransaction) GetFirstNodeByLabel(label string) (*Node, error)
GetFirstNodeByLabel returns the first visible node with the given label.
func (*BadgerTransaction) GetIncomingEdges ¶
func (tx *BadgerTransaction) GetIncomingEdges(nodeID NodeID) ([]*Edge, error)
GetIncomingEdges returns incoming edges including pending transaction writes.
func (*BadgerTransaction) GetMetadata ¶
func (tx *BadgerTransaction) GetMetadata() map[string]interface{}
GetMetadata returns transaction metadata copy.
func (*BadgerTransaction) GetNode ¶
func (tx *BadgerTransaction) GetNode(nodeID NodeID) (*Node, error)
GetNode retrieves a node (read-your-writes).
func (*BadgerTransaction) GetNodesByLabel ¶ added in v1.0.42
func (tx *BadgerTransaction) GetNodesByLabel(label string) ([]*Node, error)
GetNodesByLabel returns nodes with the given label including pending transaction writes.
func (*BadgerTransaction) GetOutgoingEdges ¶
func (tx *BadgerTransaction) GetOutgoingEdges(nodeID NodeID) ([]*Edge, error)
GetOutgoingEdges returns outgoing edges including pending transaction writes.
func (*BadgerTransaction) HasPendingNodeMutations ¶ added in v1.0.42
func (tx *BadgerTransaction) HasPendingNodeMutations() bool
func (*BadgerTransaction) IsActive ¶
func (tx *BadgerTransaction) IsActive() bool
IsActive returns true if the transaction is still active.
func (*BadgerTransaction) OperationCount ¶
func (tx *BadgerTransaction) OperationCount() int
OperationCount returns the number of buffered operations.
func (*BadgerTransaction) Rollback ¶
func (tx *BadgerTransaction) Rollback() error
Rollback discards all changes.
func (*BadgerTransaction) SetDeferredConstraintValidation ¶
func (tx *BadgerTransaction) SetDeferredConstraintValidation(deferValidation bool) error
SetDeferredConstraintValidation controls per-operation constraint checks. When enabled, constraints are enforced at commit time only.
func (*BadgerTransaction) SetMetadata ¶
func (tx *BadgerTransaction) SetMetadata(metadata map[string]interface{}) error
SetMetadata sets transaction metadata (same as Transaction).
func (*BadgerTransaction) SetSkipCreateExistenceCheck ¶
func (tx *BadgerTransaction) SetSkipCreateExistenceCheck(skip bool) error
SetSkipCreateExistenceCheck controls read-before-write checks for CREATE. When enabled, CREATE skips the storage existence read for UUID IDs.
func (*BadgerTransaction) UpdateEdge ¶
func (tx *BadgerTransaction) UpdateEdge(edge *Edge) error
UpdateEdge updates an existing edge within the transaction.
This is required so Cypher can do CREATE ... SET r.prop = ... in a single query while using implicit/explicit transactions (writes must remain isolated until commit).
func (*BadgerTransaction) UpdateNode ¶
func (tx *BadgerTransaction) UpdateNode(node *Node) error
UpdateNode updates a node in the transaction.
type BatchWriter ¶
type BatchWriter struct {
// contains filtered or unexported fields
}
BatchWriter provides explicit batch commit control for bulk operations. Instead of syncing after each write (even in batch mode), BatchWriter buffers all writes and only syncs when Commit() is called.
This dramatically improves bulk write throughput by reducing fsync calls. Use for imports, migrations, or any operation writing many records.
Example:
batch := wal.NewBatch()
for _, node := range nodes {
batch.AppendNode(OpCreateNode, node)
}
if err := batch.Commit(); err != nil {
batch.Rollback() // Discard uncommitted entries
}
Performance:
- Single fsync at end instead of per-write
- 10-100x faster for bulk operations
- Memory usage proportional to batch size
IMPORTANT: Sequence numbers are assigned at commit time, not append time. This ensures entries are written in sequence order, preventing replay issues when mixing batch and non-batch operations.
func (*BatchWriter) AppendDelete ¶
func (b *BatchWriter) AppendDelete(op OperationType, id string) error
AppendDelete adds a delete operation to the batch.
func (*BatchWriter) AppendEdge ¶
func (b *BatchWriter) AppendEdge(op OperationType, edge *Edge) error
AppendEdge adds an edge operation to the batch.
func (*BatchWriter) AppendNode ¶
func (b *BatchWriter) AppendNode(op OperationType, node *Node) error
AppendNode adds a node operation to the batch.
func (*BatchWriter) Commit ¶
func (b *BatchWriter) Commit() error
Commit writes all batched entries and syncs to disk. Sequence numbers are assigned here to ensure proper ordering. This is the only fsync in the batch - much faster than per-write sync.
func (*BatchWriter) CommitWithSeq ¶
func (b *BatchWriter) CommitWithSeq() (uint64, uint64, error)
CommitWithSeq writes all batched entries, syncs to disk, and returns the sequence range assigned to the batch. If the batch is empty or WAL is disabled, returns (0, 0, nil).
func (*BatchWriter) Len ¶
func (b *BatchWriter) Len() int
Len returns the number of pending entries.
func (*BatchWriter) Rollback ¶
func (b *BatchWriter) Rollback()
Rollback discards all uncommitted entries.
type CompositeEngine ¶
type CompositeEngine struct {
// contains filtered or unexported fields
}
CompositeEngine is a storage engine that spans multiple constituent databases. It implements the Engine interface by routing operations to constituents and merging results.
This enables composite databases (similar to Neo4j Fabric) where a single database view spans multiple physical databases.
func NewCompositeEngine ¶
func NewCompositeEngine( constituents map[string]Engine, constituentNames map[string]string, accessModes map[string]string, ) *CompositeEngine
NewCompositeEngine creates a new composite engine that spans multiple constituent databases.
Parameters:
- constituents: Map of alias -> storage engine for each constituent
- constituentNames: Map of alias -> actual database name
- accessModes: Map of alias -> access mode ("read", "write", "read_write")
func (*CompositeEngine) AllEdges ¶
func (c *CompositeEngine) AllEdges() ([]*Edge, error)
AllEdges returns all edges from all constituents. Duplicate edges (same ID) are deduplicated - only the first occurrence is kept.
func (*CompositeEngine) AllNodes ¶
func (c *CompositeEngine) AllNodes() ([]*Node, error)
AllNodes returns all nodes from all constituents. Duplicate nodes (same ID) are deduplicated - only the first occurrence is kept.
func (*CompositeEngine) BatchGetNodes ¶
func (c *CompositeEngine) BatchGetNodes(ids []NodeID) (map[NodeID]*Node, error)
BatchGetNodes retrieves multiple nodes from all constituents.
func (*CompositeEngine) BulkCreateEdges ¶
func (c *CompositeEngine) BulkCreateEdges(edges []*Edge) error
BulkCreateEdges creates edges in bulk. Routes edges to constituents containing their start nodes.
func (*CompositeEngine) BulkCreateNodes ¶
func (c *CompositeEngine) BulkCreateNodes(nodes []*Node) error
BulkCreateNodes creates nodes in bulk. Routes nodes to appropriate constituents based on routing rules.
func (*CompositeEngine) BulkDeleteEdges ¶
func (c *CompositeEngine) BulkDeleteEdges(ids []EdgeID) error
BulkDeleteEdges deletes edges in bulk from all constituents.
func (*CompositeEngine) BulkDeleteNodes ¶
func (c *CompositeEngine) BulkDeleteNodes(ids []NodeID) error
BulkDeleteNodes deletes nodes in bulk from all constituents.
func (*CompositeEngine) Close ¶
func (c *CompositeEngine) Close() error
Close closes all constituent engines.
func (*CompositeEngine) CreateEdge ¶
func (c *CompositeEngine) CreateEdge(edge *Edge) error
CreateEdge creates an edge. Routes to the constituent containing the start node. Following Neo4j TransactionState pattern: check if nodes were created in current transaction, and if so, try that constituent first. Otherwise try all constituents.
func (*CompositeEngine) CreateNode ¶
func (c *CompositeEngine) CreateNode(node *Node) (NodeID, error)
CreateNode creates a node. Routes to the appropriate constituent based on routing rules.
func (*CompositeEngine) DeleteByPrefix ¶
func (c *CompositeEngine) DeleteByPrefix(prefix string) (nodesDeleted int64, edgesDeleted int64, err error)
DeleteByPrefix is not supported for composite databases. Composite databases don't have their own data - they're virtual views.
func (*CompositeEngine) DeleteEdge ¶
func (c *CompositeEngine) DeleteEdge(id EdgeID) error
DeleteEdge deletes an edge from the constituent containing it.
func (*CompositeEngine) DeleteNode ¶
func (c *CompositeEngine) DeleteNode(id NodeID) error
DeleteNode deletes a node from the constituent that contains it.
func (*CompositeEngine) EdgeCount ¶
func (c *CompositeEngine) EdgeCount() (int64, error)
EdgeCount returns the total edge count across all constituents.
func (*CompositeEngine) GetAllNodes ¶
func (c *CompositeEngine) GetAllNodes() []*Node
GetAllNodes returns all nodes from all constituents (non-error version).
func (*CompositeEngine) GetConstituentByAlias ¶
func (c *CompositeEngine) GetConstituentByAlias(alias string) (Engine, error)
GetConstituentByAlias returns the storage engine for a specific constituent within this composite database. This is used by the Cypher executor to resolve USE composite.alias references.
func (*CompositeEngine) GetEdge ¶
func (c *CompositeEngine) GetEdge(id EdgeID) (*Edge, error)
GetEdge retrieves an edge. Searches all constituents.
func (*CompositeEngine) GetEdgeBetween ¶
func (c *CompositeEngine) GetEdgeBetween(startID, endID NodeID, edgeType string) *Edge
GetEdgeBetween returns an edge between two nodes from any constituent.
func (*CompositeEngine) GetEdgesBetween ¶
func (c *CompositeEngine) GetEdgesBetween(startID, endID NodeID) ([]*Edge, error)
GetEdgesBetween returns edges between two nodes from all constituents. Duplicate edges (same ID) are deduplicated - only the first occurrence is kept.
func (*CompositeEngine) GetEdgesByType ¶
func (c *CompositeEngine) GetEdgesByType(edgeType string) ([]*Edge, error)
GetEdgesByType returns edges of the given type from all constituents. Duplicate edges (same ID) are deduplicated - only the first occurrence is kept.
func (*CompositeEngine) GetFirstNodeByLabel ¶
func (c *CompositeEngine) GetFirstNodeByLabel(label string) (*Node, error)
GetFirstNodeByLabel returns the first node with the given label from any constituent.
func (*CompositeEngine) GetInDegree ¶
func (c *CompositeEngine) GetInDegree(nodeID NodeID) int
GetInDegree returns the in-degree of a node across all constituents.
func (*CompositeEngine) GetIncomingEdges ¶
func (c *CompositeEngine) GetIncomingEdges(nodeID NodeID) ([]*Edge, error)
GetIncomingEdges returns incoming edges from all constituents. Duplicate edges (same ID) are deduplicated - only the first occurrence is kept.
func (*CompositeEngine) GetNode ¶
func (c *CompositeEngine) GetNode(id NodeID) (*Node, error)
GetNode retrieves a node. Searches all readable constituents.
func (*CompositeEngine) GetNodesByLabel ¶
func (c *CompositeEngine) GetNodesByLabel(label string) ([]*Node, error)
GetNodesByLabel returns nodes with the given label from all constituents. Duplicate nodes (same ID) are deduplicated - only the first occurrence is kept. Returns empty slice if no readable constituents are available.
func (*CompositeEngine) GetOutDegree ¶
func (c *CompositeEngine) GetOutDegree(nodeID NodeID) int
GetOutDegree returns the out-degree of a node across all constituents.
func (*CompositeEngine) GetOutgoingEdges ¶
func (c *CompositeEngine) GetOutgoingEdges(nodeID NodeID) ([]*Edge, error)
GetOutgoingEdges returns outgoing edges from all constituents. Duplicate edges (same ID) are deduplicated - only the first occurrence is kept.
func (*CompositeEngine) GetSchema ¶
func (c *CompositeEngine) GetSchema() *SchemaManager
GetSchema returns a merged schema from all constituents. Merges constraints and indexes from all constituent databases.
func (*CompositeEngine) IsComposite ¶
func (c *CompositeEngine) IsComposite() bool
IsComposite returns true, identifying this engine as a composite database. This enables type-assertion-free composite detection via interface check:
type compositeChecker interface { IsComposite() bool }
if cc, ok := engine.(compositeChecker); ok && cc.IsComposite() { ... }
func (*CompositeEngine) NodeCount ¶
func (c *CompositeEngine) NodeCount() (int64, error)
NodeCount returns the total node count across all constituents.
func (*CompositeEngine) SetLabelRouting ¶
func (c *CompositeEngine) SetLabelRouting(label string, constituents []string)
SetLabelRouting configures label-based routing for a specific label. This allows explicit configuration of which constituents should handle nodes with a given label.
func (*CompositeEngine) SetPropertyDefault ¶
func (c *CompositeEngine) SetPropertyDefault(propertyName string, constituent string)
SetPropertyDefault sets the default constituent for a property when the value is not found in routing rules.
func (*CompositeEngine) SetPropertyRouting ¶
func (c *CompositeEngine) SetPropertyRouting(propertyName string, value interface{}, constituent string)
SetPropertyRouting configures property-based routing for a specific property value. This enables routing based on property values (e.g., database_id).
func (*CompositeEngine) StreamEdges ¶
StreamEdges streams edges from all constituents.
func (*CompositeEngine) StreamNodeChunks ¶
func (c *CompositeEngine) StreamNodeChunks(ctx context.Context, chunkSize int, fn func(nodes []*Node) error) error
StreamNodeChunks streams nodes in chunks from all constituents.
func (*CompositeEngine) StreamNodes ¶
StreamNodes streams nodes from all constituents.
func (*CompositeEngine) UpdateEdge ¶
func (c *CompositeEngine) UpdateEdge(edge *Edge) error
UpdateEdge updates an edge. Routes to the constituent containing it.
func (*CompositeEngine) UpdateNode ¶
func (c *CompositeEngine) UpdateNode(node *Node) error
UpdateNode updates a node. Routes to the constituent that contains it.
type CompositeIndex ¶
type CompositeIndex struct {
Name string
Label string
Properties []string // Ordered list of property names
// contains filtered or unexported fields
}
CompositeIndex represents an index on multiple properties for efficient multi-property queries. This is Neo4j's composite index equivalent.
Composite indexes support:
- Full key lookups (all properties specified)
- Prefix lookups (leading properties specified, for ordered access)
- Range queries on the last property in a prefix
func (*CompositeIndex) IndexNode ¶
func (idx *CompositeIndex) IndexNode(nodeID NodeID, properties map[string]interface{}) error
IndexNodeComposite indexes a node in a composite index. Call this when creating or updating a node with the indexed properties.
func (*CompositeIndex) LookupFull ¶
func (idx *CompositeIndex) LookupFull(values ...interface{}) []NodeID
LookupFull finds nodes matching all property values exactly. All properties in the composite index must be specified.
func (*CompositeIndex) LookupPrefix ¶
func (idx *CompositeIndex) LookupPrefix(values ...interface{}) []NodeID
LookupPrefix finds nodes matching a prefix of property values. Specify 1 to N-1 property values (where N is total properties in index). Returns all nodes that match the prefix.
Example: For index on (country, city, zipcode)
- LookupPrefix("US") returns all nodes in the US
- LookupPrefix("US", "NYC") returns all nodes in NYC, US
func (*CompositeIndex) LookupWithFilter ¶
func (idx *CompositeIndex) LookupWithFilter(filter func(NodeID) bool, values ...interface{}) []NodeID
LookupWithFilter finds nodes using a prefix and applies a filter function. This enables more complex queries like range queries on the last property.
Example: Find all users in "US", "NYC" with zipcode > "10000"
idx.LookupWithFilter(func(n NodeID, props map[string]interface{}) bool {
zip := props["zipcode"].(string)
return zip > "10000"
}, "US", "NYC")
func (*CompositeIndex) RemoveNode ¶
func (idx *CompositeIndex) RemoveNode(nodeID NodeID, properties map[string]interface{})
RemoveNode removes a node from the composite index. Call this when deleting a node or updating its indexed properties.
func (*CompositeIndex) Stats ¶
func (idx *CompositeIndex) Stats() map[string]interface{}
Stats returns statistics about the composite index.
type CompositeKey ¶
type CompositeKey struct {
Hash string // SHA256 hash of encoded values (for map lookup)
Values []interface{} // Original values (for debugging/display)
}
CompositeKey represents a key composed of multiple property values. The key is a hash of all property values in order for efficient lookup.
func NewCompositeKey ¶
func NewCompositeKey(values ...interface{}) CompositeKey
NewCompositeKey creates a composite key from multiple property values.
Composite keys enable uniqueness constraints and indexes on multiple properties together (e.g., unique combination of firstName + lastName). The key is hashed using SHA-256 for efficient map lookups while preserving the original values.
Parameters:
- values: Variable number of property values to combine
Returns:
- CompositeKey with hash for lookup and original values
Example 1 - Unique Person Name:
// Ensure no two people have the same first AND last name combination
key := storage.NewCompositeKey("Alice", "Johnson")
// key.Hash = "a1b2c3..." (SHA-256)
// key.Values = ["Alice", "Johnson"]
// Can store in map for O(1) lookup
uniqueKeys := make(map[string]bool)
uniqueKeys[key.Hash] = true
Example 2 - Multi-Column Unique Constraint:
// Email + domain must be unique together
key1 := storage.NewCompositeKey("user", "example.com")
key2 := storage.NewCompositeKey("user", "different.com")
// key1.Hash != key2.Hash (different combinations)
key3 := storage.NewCompositeKey("user", "example.com")
// key3.Hash == key1.Hash (same combination)
Example 3 - Geographic Uniqueness:
// Store locations - no duplicate (lat, lon) pairs
locations := make(map[string]storage.NodeID)
loc1 := storage.NewCompositeKey(40.7128, -74.0060) // NYC
locations[loc1.Hash] = storage.NodeID("loc-nyc")
loc2 := storage.NewCompositeKey(40.7128, -74.0060) // Same coords
if _, exists := locations[loc2.Hash]; exists {
fmt.Println("Location already exists!")
}
ELI12:
Imagine you're making sure no two people in your class have the SAME full name (first + last together):
- Alice Smith → Create a "fingerprint" (hash) from "Alice" + "Smith"
- Bob Johnson → Different fingerprint
- Alice Smith → SAME fingerprint as the first Alice Smith!
The hash is like a unique barcode for the combination. If two combinations have the same barcode, they're duplicates!
Why hash instead of just combining strings?
- Fast lookups (constant time)
- Handles any data types (numbers, strings, booleans)
- Consistent length (SHA-256 always 64 chars)
Use Cases:
- Composite unique constraints (email + database_id)
- Multi-column indexes
- Deduplication of complex records
func (CompositeKey) String ¶
func (ck CompositeKey) String() string
String returns a human-readable representation of the composite key.
type Constraint ¶
type Constraint struct {
Name string `json:"name"`
Type ConstraintType `json:"type"`
EntityType ConstraintEntityType `json:"entity_type,omitempty"` // defaults to NODE when empty
Label string `json:"label"` // label for nodes, relationship type for relationships
Properties []string `json:"properties,omitempty"`
OwnedIndex string `json:"owned_index,omitempty"` // name of the owned backing index (for uniqueness/key)
AllowedValues []interface{} `json:"allowed_values,omitempty"` // for DOMAIN constraints: list of allowed values
MaxCount int `json:"max_count,omitempty"` // for CARDINALITY constraints: maximum edge count per node
Direction string `json:"direction,omitempty"` // for CARDINALITY constraints: "OUTGOING" or "INCOMING"
SourceLabel string `json:"source_label,omitempty"` // for RELATIONSHIP_POLICY constraints: required source node label
TargetLabel string `json:"target_label,omitempty"` // for RELATIONSHIP_POLICY constraints: required target node label
PolicyMode string `json:"policy_mode,omitempty"` // for RELATIONSHIP_POLICY constraints: "ALLOWED" or "DISALLOWED"
}
Constraint represents a Neo4j-compatible schema constraint.
func (Constraint) EffectiveEntityType ¶
func (c Constraint) EffectiveEntityType() ConstraintEntityType
EffectiveEntityType returns the entity type, defaulting to NODE for backward compatibility.
type ConstraintContract ¶
type ConstraintContract struct {
Name string `json:"name"`
TargetEntityType string `json:"target_entity_type"`
TargetLabelOrType string `json:"target_label_or_type"`
Definition string `json:"definition"`
Entries []ConstraintContractEntry `json:"entries,omitempty"`
}
type ConstraintContractEntry ¶
type ConstraintContractEntry struct {
Kind string `json:"kind"`
PrimitiveType string `json:"primitive_type,omitempty"`
Properties []string `json:"properties,omitempty"`
Property string `json:"property,omitempty"`
ExpectedType string `json:"expected_type,omitempty"`
Expression string `json:"expression,omitempty"`
}
type ConstraintEntityType ¶
type ConstraintEntityType string
ConstraintEntityType distinguishes node constraints from relationship constraints.
const ( ConstraintEntityNode ConstraintEntityType = "NODE" ConstraintEntityRelationship ConstraintEntityType = "RELATIONSHIP" )
type ConstraintType ¶
type ConstraintType string
ConstraintType represents the type of constraint.
const ( ConstraintUnique ConstraintType = "UNIQUE" ConstraintNodeKey ConstraintType = "NODE_KEY" ConstraintExists ConstraintType = "EXISTS" ConstraintPropertyType ConstraintType = "PROPERTY_TYPE" ConstraintTemporal ConstraintType = "TEMPORAL_NO_OVERLAP" ConstraintRelationshipKey ConstraintType = "RELATIONSHIP_KEY" ConstraintDomain ConstraintType = "DOMAIN" ConstraintCardinality ConstraintType = "CARDINALITY" ConstraintPolicy ConstraintType = "RELATIONSHIP_POLICY" )
type ConstraintViolationError ¶
type ConstraintViolationError struct {
Type ConstraintType
Label string
Properties []string
Message string
}
ConstraintViolationError is returned when a constraint is violated.
func (*ConstraintViolationError) Error ¶
func (e *ConstraintViolationError) Error() string
type CorruptionDiagnostics ¶
type CorruptionDiagnostics struct {
Timestamp time.Time `json:"timestamp"`
WALPath string `json:"wal_path"`
CorruptedSeq uint64 `json:"corrupted_seq"`
Operation string `json:"operation"`
ExpectedCRC uint32 `json:"expected_crc"`
ActualCRC uint32 `json:"actual_crc"`
FileSize int64 `json:"file_size"`
LastGoodSeq uint64 `json:"last_good_seq"`
SuspectedCause string `json:"suspected_cause"`
BackupPath string `json:"backup_path,omitempty"`
RecoveryAction string `json:"recovery_action"`
}
CorruptionDiagnostics captures detailed information about WAL corruption to help diagnose root causes (disk failure, split-brain, bugs, etc.)
type DB ¶
type DB struct {
// contains filtered or unexported fields
}
DB provides closure-based transaction helpers over a transactional storage engine.
func NewDB ¶
func NewDB(engine transactionBeginner) *DB
NewDB wraps a transactional storage engine with closure-based transaction helpers.
func (*DB) Begin ¶
func (db *DB) Begin(readWrite bool) (*Transaction, error)
Begin opens a transaction-scoped snapshot for the closure helpers. The current storage transaction implementation always uses an explicit BadgerTransaction, so the readWrite flag is reserved for future differentiation.
func (*DB) SetMaxUpdateRetries ¶
SetMaxUpdateRetries overrides the default retry limit used by Update.
type Edge ¶
type Edge struct {
ID EdgeID `json:"id"`
StartNode NodeID `json:"startNode"`
EndNode NodeID `json:"endNode"`
Type string `json:"type"`
Properties map[string]any `json:"properties"`
// NornicDB extensions
CreatedAt time.Time `json:"-"`
UpdatedAt time.Time `json:"-"`
Confidence float64 `json:"-"`
AutoGenerated bool `json:"-"`
}
Edge represents a directed graph relationship (arc) between two nodes.
Edges are directed connections that link nodes together, representing relationships like "Alice KNOWS Bob" or "Document CITES Paper". They follow the Neo4j relationship model with NornicDB extensions for automatic relationship inference and confidence scoring.
Core Neo4j Fields:
- ID: Unique identifier for the relationship
- StartNode: Source node ID (where the arrow starts)
- EndNode: Target node ID (where the arrow points)
- Type: Relationship type (e.g., "KNOWS", "FOLLOWS", "CONTAINS")
- Properties: Key-value data about the relationship
NornicDB Extensions:
- CreatedAt: When the relationship was created
- Confidence: How certain we are this relationship exists (0.0-1.0)
- AutoGenerated: True if detected by ML/inference, false if manually created
Example 1 - Social Network Relationship:
edge := &storage.Edge{
ID: storage.EdgeID("friendship-123"),
StartNode: storage.NodeID("alice"),
EndNode: storage.NodeID("bob"),
Type: "KNOWS",
Properties: map[string]any{
"since": "2020-01-15",
"strength": "close_friend",
"mutuality": true,
},
CreatedAt: time.Now(),
Confidence: 1.0, // Manually created = 100% certain
AutoGenerated: false,
}
engine.CreateEdge(edge)
Example 2 - Document Citation:
citation := &storage.Edge{
ID: storage.EdgeID("cite-paper-5"),
StartNode: storage.NodeID("paper-123"),
EndNode: storage.NodeID("paper-456"),
Type: "CITES",
Properties: map[string]any{
"context": "Methods section",
"page": 12,
"importance": "high",
},
CreatedAt: time.Now(),
Confidence: 1.0,
}
Example 3 - Auto-Detected Semantic Relationship:
// NornicDB inference engine detected similarity
autoEdge := &storage.Edge{
ID: storage.EdgeID("similar-42"),
StartNode: storage.NodeID("note-1"),
EndNode: storage.NodeID("note-2"),
Type: "SIMILAR_TO",
Confidence: 0.87, // 87% confidence from embedding similarity
AutoGenerated: true, // Created automatically
Properties: map[string]any{
"similarity": 0.87,
"method": "cosine_similarity",
"detected_at": time.Now(),
"reason": "High semantic similarity in embeddings",
},
}
ELI12:
Think of an Edge like a string connecting two beads (nodes):
- StartNode: The first bead (where you start)
- EndNode: The second bead (where the string goes to)
- Type: What kind of string? ("FRIENDS_WITH", "PARENT_OF", "LIKES")
- Properties: Info about the connection ("since when?", "how strong?")
The arrow matters! "Alice KNOWS Bob" is different from "Bob KNOWS Alice" (they could both be true, but they're separate relationships).
NornicDB's cool additions:
- Confidence: "I'm 85% sure these two things are related"
- AutoGenerated: "I found this connection myself!" vs "A human told me"
Imagine your brain automatically connecting ideas: "Oh, these two notes seem related!" That's what AutoGenerated edges do - the system notices patterns and creates connections for you!
Neo4j Compatibility:
- Type maps to Neo4j relationship type (e.g., -[:KNOWS]->)
- StartNode/EndNode map to Neo4j node IDs
- Properties map to Neo4j relationship properties
- Direction is always preserved (Neo4j requirement)
Thread Safety:
Edge structs are NOT thread-safe. The storage engine handles concurrency.
type EdgeDeleteCallback ¶
type EdgeDeleteCallback func(edgeID EdgeID)
EdgeDeleteCallback is called when an edge is successfully deleted from storage.
type EdgeEventCallback ¶
type EdgeEventCallback func(edge *Edge)
EdgeEventCallback is called when edge storage operations complete successfully.
type EdgeID ¶
type EdgeID string
EdgeID is a strongly-typed unique identifier for graph edges (relationships).
Similar to NodeID, provides type safety and API clarity.
Example:
id := storage.EdgeID("follows-456")
edge, err := engine.GetEdge(id)
type EdgeMeta ¶
type EdgeMeta struct {
// Edge identification
EdgeID string `json:"edge_id"`
Src string `json:"src"`
Dst string `json:"dst"`
Label string `json:"label"`
// Confidence and scoring
Score float64 `json:"score"`
SignalType string `json:"signal_type"` // "coaccess", "similarity", "topology", "llm-infer", "manual"
EvidenceCount int `json:"evidence_count"`
DecayState float64 `json:"decay_state"`
// Temporal
Timestamp time.Time `json:"timestamp"`
SessionID string `json:"session_id,omitempty"`
// Lifecycle
Materialized bool `json:"materialized"`
Origin string `json:"origin"` // agent/commit ID that created this
// TLP-specific (topology link prediction)
TopologyAlgorithm string `json:"topology_algorithm,omitempty"`
TopologyScore float64 `json:"topology_score,omitempty"`
SemanticScore float64 `json:"semantic_score,omitempty"`
// Method that generated this edge (detailed)
Method string `json:"method,omitempty"`
Reason string `json:"reason,omitempty"`
// Additional metadata
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
EdgeMeta stores provenance for auto-generated edges. This is append-only for auditability.
type EdgeMetaKey ¶
EdgeMetaKey uniquely identifies an edge for provenance lookup.
func (EdgeMetaKey) String ¶
func (k EdgeMetaKey) String() string
String returns a string representation of the key.
type EdgeMetaStats ¶
type EdgeMetaStats struct {
TotalRecords int64
TotalMaterialized int64
UniqueEdges int64
BySignalType map[string]int64
}
EdgeMetaStats provides observability into provenance tracking.
type EdgeMetaStore ¶
type EdgeMetaStore struct {
// contains filtered or unexported fields
}
EdgeMetaStore manages edge provenance. Thread-safe and append-only for auditability.
func GlobalEdgeMetaStore ¶
func GlobalEdgeMetaStore() *EdgeMetaStore
GlobalEdgeMetaStore returns the global edge meta store singleton.
func NewEdgeMetaStore ¶
func NewEdgeMetaStore() *EdgeMetaStore
NewEdgeMetaStore creates a new edge metadata store.
func NewEdgeMetaStoreWithOptions ¶
func NewEdgeMetaStoreWithOptions(opts ...EdgeMetaStoreOption) *EdgeMetaStore
NewEdgeMetaStoreWithOptions creates a store with functional options.
func (*EdgeMetaStore) Append ¶
func (s *EdgeMetaStore) Append(ctx context.Context, meta EdgeMeta) error
Append adds a new evidence record (immutable). This is the primary method for recording edge provenance.
func (*EdgeMetaStore) AppendFromSuggestion ¶
func (s *EdgeMetaStore) AppendFromSuggestion( ctx context.Context, src, dst, label string, score float64, signalType, method, reason, sessionID, origin string, materialized bool, ) error
AppendFromSuggestion creates an EdgeMeta from inference suggestion data. Convenience method for inference engine integration.
func (*EdgeMetaStore) Cleanup ¶
func (s *EdgeMetaStore) Cleanup(maxAge time.Duration) int
Cleanup removes records older than maxAge. Returns the number of records removed.
func (*EdgeMetaStore) Clear ¶
func (s *EdgeMetaStore) Clear()
Clear removes all provenance records. Use with caution - audit trail will be lost.
func (*EdgeMetaStore) CountHistory ¶
func (s *EdgeMetaStore) CountHistory(src, dst, label string) int
CountHistory returns the number of provenance records for an edge.
func (*EdgeMetaStore) Export ¶
func (s *EdgeMetaStore) Export() []*EdgeMeta
Export returns all provenance records for backup/export.
func (*EdgeMetaStore) GetByOrigin ¶
func (s *EdgeMetaStore) GetByOrigin(ctx context.Context, origin string, limit int) ([]*EdgeMeta, error)
GetByOrigin returns provenance records by origin (agent/commit ID).
func (*EdgeMetaStore) GetBySession ¶
func (s *EdgeMetaStore) GetBySession(ctx context.Context, sessionID string, limit int) ([]*EdgeMeta, error)
GetBySession returns provenance records by session.
func (*EdgeMetaStore) GetBySignalType ¶
func (s *EdgeMetaStore) GetBySignalType(ctx context.Context, signalType string, limit int) ([]*EdgeMeta, error)
GetBySignalType filters by how edges were created.
func (*EdgeMetaStore) GetByTimeRange ¶
func (s *EdgeMetaStore) GetByTimeRange(ctx context.Context, start, end time.Time, limit int) ([]*EdgeMeta, error)
GetByTimeRange returns provenance records within a time range.
func (*EdgeMetaStore) GetHistory ¶
func (s *EdgeMetaStore) GetHistory(ctx context.Context, src, dst, label string) ([]*EdgeMeta, error)
GetHistory returns all evidence for an edge.
func (*EdgeMetaStore) GetMaterialized ¶
GetMaterialized returns all materialized edges.
func (*EdgeMetaStore) HasHistory ¶
func (s *EdgeMetaStore) HasHistory(src, dst, label string) bool
HasHistory returns true if any provenance records exist for this edge.
func (*EdgeMetaStore) Import ¶
func (s *EdgeMetaStore) Import(records []*EdgeMeta) int
Import loads provenance records from backup/import. Existing records are NOT cleared - use Clear() first if needed.
func (*EdgeMetaStore) MarkMaterialized ¶
func (s *EdgeMetaStore) MarkMaterialized(ctx context.Context, src, dst, label, origin string) error
MarkMaterialized marks an edge as materialized (actually created). Appends a new record with Materialized=true.
func (*EdgeMetaStore) Size ¶
func (s *EdgeMetaStore) Size() int
Size returns the total number of provenance records.
func (*EdgeMetaStore) Stats ¶
func (s *EdgeMetaStore) Stats() EdgeMetaStats
Stats returns current provenance store statistics.
func (*EdgeMetaStore) UniqueEdgeCount ¶
func (s *EdgeMetaStore) UniqueEdgeCount() int
UniqueEdgeCount returns the number of unique edges with provenance.
type EdgeMetaStoreOption ¶
type EdgeMetaStoreOption func(*EdgeMetaStore)
EdgeMetaStoreOption configures an EdgeMetaStore.
type EdgeVisitor ¶
EdgeVisitor is a function called for each edge during streaming.
type Engine ¶
type Engine interface {
// Node operations
CreateNode(node *Node) (NodeID, error) // Returns the actual stored ID (may be prefixed for namespaced engines)
GetNode(id NodeID) (*Node, error)
UpdateNode(node *Node) error
DeleteNode(id NodeID) error
// Edge operations
CreateEdge(edge *Edge) error
GetEdge(id EdgeID) (*Edge, error)
UpdateEdge(edge *Edge) error
DeleteEdge(id EdgeID) error
// Query operations
GetNodesByLabel(label string) ([]*Node, error)
GetFirstNodeByLabel(label string) (*Node, error) // Optimized for LIMIT 1
GetOutgoingEdges(nodeID NodeID) ([]*Edge, error)
GetIncomingEdges(nodeID NodeID) ([]*Edge, error)
GetEdgesBetween(startID, endID NodeID) ([]*Edge, error)
GetEdgeBetween(startID, endID NodeID, edgeType string) *Edge
GetEdgesByType(edgeType string) ([]*Edge, error) // Fast lookup by edge type
AllNodes() ([]*Node, error)
AllEdges() ([]*Edge, error)
GetAllNodes() []*Node
// Degree operations (for graph algorithms)
GetInDegree(nodeID NodeID) int
GetOutDegree(nodeID NodeID) int
// Schema operations
GetSchema() *SchemaManager
// Bulk operations (for import)
BulkCreateNodes(nodes []*Node) error
BulkCreateEdges(edges []*Edge) error
// Bulk delete operations (for async flush performance)
BulkDeleteNodes(ids []NodeID) error
BulkDeleteEdges(ids []EdgeID) error
// Batch read operations (for traversal performance)
// BatchGetNodes fetches multiple nodes in a single operation
// Returns a map for O(1) lookup by ID
BatchGetNodes(ids []NodeID) (map[NodeID]*Node, error)
// Lifecycle
Close() error
// Stats
NodeCount() (int64, error)
EdgeCount() (int64, error)
// DeleteByPrefix deletes all nodes and edges with IDs starting with the given prefix.
// Used for DROP DATABASE operations to delete all data in a namespace.
// Returns the number of nodes and edges deleted.
//
// This is an optional interface - engines that don't support it will return an error.
// For multi-database support, this must be implemented.
DeleteByPrefix(prefix string) (nodesDeleted int64, edgesDeleted int64, err error)
}
Engine defines the storage engine interface for graph database operations.
All Engine implementations MUST be:
- Thread-safe: Safe for concurrent access from multiple goroutines
- ACID-like: Operations are atomic within their scope
- Idempotent where appropriate: CreateNode fails if ID exists
The interface provides standard graph database operations:
- CRUD for nodes and edges
- Label-based queries
- Graph traversal (outgoing/incoming edges)
- Bulk operations for import/export
- Statistics
Implementations:
- MemoryEngine: In-memory storage for testing and small datasets
- BadgerEngine: Persistent disk storage (planned)
Example Usage:
var engine storage.Engine
engine = storage.NewMemoryEngine()
defer engine.Close()
// Create data
node := &storage.Node{
ID: "n1",
Labels: []string{"Person"},
Properties: map[string]any{"name": "Alice"},
}
if _, err := engine.CreateNode(node); err != nil {
log.Fatal(err)
}
// Query
people, _ := engine.GetNodesByLabel("Person")
fmt.Printf("Found %d people\n", len(people))
// Traversal
outgoing, _ := engine.GetOutgoingEdges("n1")
for _, edge := range outgoing {
fmt.Printf("%s -> %s [%s]\n", edge.StartNode, edge.EndNode, edge.Type)
}
type EngineOptions ¶
type EngineOptions struct {
RetentionPolicy RetentionPolicy
}
EngineOptions contains storage-engine-wide options shared across engine implementations.
type ExportableEngine ¶
ExportableEngine extends Engine with export capabilities.
type FlushResult ¶
type FlushResult struct {
NodesWritten int
NodesFailed int
EdgesWritten int
EdgesFailed int
NodesDeleted int
EdgesDeleted int
DeletesFailed int
FailedNodeIDs []NodeID // IDs that failed - still in cache for retry
FailedEdgeIDs []EdgeID // IDs that failed - still in cache for retry
FirstNodeError string
FirstEdgeError string
FirstDeleteError string
}
FlushResult tracks the outcome of a flush operation for observability.
func (FlushResult) HasErrors ¶
func (r FlushResult) HasErrors() bool
HasErrors returns true if any flush operations failed.
type FulltextIndex ¶
FulltextIndex represents a full-text search index.
type IndexStats ¶
type IndexStats struct {
Name string `json:"name"`
Type string `json:"type"`
Label string `json:"label"`
Property string `json:"property,omitempty"`
Properties []string `json:"properties,omitempty"`
TotalEntries int64 `json:"totalEntries"`
UniqueValues int64 `json:"uniqueValues"`
Selectivity float64 `json:"selectivity"` // uniqueValues / totalEntries
}
IndexStats represents statistics about an index.
type LabelConfig ¶
type LabelConfig struct {
Label string `json:"label"`
MaxEdges int `json:"max_edges"` // 0 = unlimited
MinConfidence float64 `json:"min_confidence"` // Override default threshold
Cooldown time.Duration `json:"cooldown"` // Override default cooldown
Disabled bool `json:"disabled"` // Completely disable this label
}
LabelConfig defines per-label edge limits.
type LabelIndexEngine ¶
type LabelIndexEngine interface {
// HasLabelBatch returns a map of node IDs that have the given label.
// Implementations should treat labels case-insensitively (Neo4j compatible).
// Missing nodes are treated as not having the label.
HasLabelBatch(ids []NodeID, label string) (map[NodeID]bool, error)
}
LabelIndexEngine is an optional interface implemented by engines that can answer label-membership queries via an index, without decoding full nodes.
This is used by performance-sensitive query executors that need to enforce `(n:Label)` semantics while avoiding per-node GetNode/BatchGetNodes overhead.
type LabelNodeIDLookupEngine ¶
type LabelNodeIDLookupEngine interface {
ForEachNodeIDByLabel(label string, visit func(NodeID) bool) error
}
LabelNodeIDLookupEngine is an optional interface for engines that can return node IDs for a label without decoding full nodes.
Implementations must treat labels case-insensitively (Neo4j compatible). The visit function should return true to continue iteration, false to stop.
type MVCCAppendEngine ¶
type MVCCAppendEngine interface {
AppendNodeVersion(node *Node, version MVCCVersion) error
AppendNodeTombstone(id NodeID, version MVCCVersion) error
AppendEdgeVersion(edge *Edge, version MVCCVersion) error
AppendEdgeTombstone(id EdgeID, version MVCCVersion) error
UpdateNodeCurrentHead(id NodeID, version MVCCVersion, tombstoned bool) error
UpdateEdgeCurrentHead(id EdgeID, version MVCCVersion, tombstoned bool) error
}
MVCCAppendEngine is an optional extension interface for immutable MVCC writes.
type MVCCEnumerationEngine ¶
type MVCCEnumerationEngine interface {
BatchGetNodesLatestVisible(ids []NodeID) (map[NodeID]*Node, error)
IterateLatestVisibleNodes(yield func(*Node) error) error
IterateLatestVisibleEdges(yield func(*Edge) error) error
}
MVCCEnumerationEngine is an optional extension interface for latest-visible iteration.
type MVCCHead ¶
type MVCCHead struct {
Version MVCCVersion
Tombstoned bool
FloorVersion MVCCVersion
}
MVCCHead stores the current persisted head for a logical record.
type MVCCHeadEngine ¶
type MVCCHeadEngine interface {
GetNodeCurrentHead(id NodeID) (MVCCHead, error)
GetEdgeCurrentHead(id EdgeID) (MVCCHead, error)
}
MVCCHeadEngine is an optional extension interface for persisted head lookups.
type MVCCIndexedVisibilityEngine ¶
type MVCCIndexedVisibilityEngine interface {
GetNodesByLabelVisibleAt(label string, version MVCCVersion) ([]*Node, error)
GetEdgesByTypeVisibleAt(edgeType string, version MVCCVersion) ([]*Edge, error)
GetEdgesBetweenVisibleAt(startID, endID NodeID, version MVCCVersion) ([]*Edge, error)
}
MVCCIndexedVisibilityEngine is an optional extension interface for snapshot-visible graph queries that resolve label, type, and topology against MVCC history instead of only the current materialized indexes.
type MVCCLatestEffectiveEngine ¶
type MVCCLatestEffectiveEngine interface {
GetNodeLatestEffective(id NodeID) (*Node, error)
GetEdgeLatestEffective(id EdgeID) (*Edge, error)
}
MVCCLatestEffectiveEngine is an optional extension interface for wrapper-level latest reads that merge pending, in-flight, and persisted state.
type MVCCLifecycleController ¶
type MVCCLifecycleController interface {
MVCCLifecycleEngine
AcquireSnapshotReader(info SnapshotReaderInfo) (func(), error)
EvaluateSnapshotReader(info SnapshotReaderInfo) (graceful bool, hard bool)
RunPruneNow(ctx context.Context, opts MVCCPruneOptions) (int64, error)
StartLifecycle(ctx context.Context)
StopLifecycle()
IsLifecycleEnabled() bool
IsLifecycleRunning() bool
ReaderRegistry() SnapshotReaderRegistry
}
MVCCLifecycleController is the storage-facing control interface used by engines. A concrete implementation can live outside the storage package and be injected.
type MVCCLifecycleDebtEngine ¶
type MVCCLifecycleDebtEngine interface {
TopLifecycleDebtKeys(limit int) []MVCCLifecycleDebtKey
}
MVCCLifecycleDebtEngine is an optional extension for inspecting the highest-debt logical keys.
type MVCCLifecycleDebtKey ¶
type MVCCLifecycleDebtKey struct {
LogicalKey string `json:"logical_key"`
Namespace string `json:"namespace,omitempty"`
DebtBytes int64 `json:"debt_bytes"`
TombstoneDepth int `json:"tombstone_depth"`
FloorLagVersions int `json:"floor_lag_versions"`
VersionsToDelete int `json:"versions_to_delete"`
}
MVCCLifecycleDebtKey describes one logical key contributing lifecycle debt.
type MVCCLifecycleEngine ¶
type MVCCLifecycleEngine interface {
RegisterSnapshotReader(info SnapshotReaderInfo) func()
LifecycleStatus() map[string]interface{}
TriggerPruneNow(ctx context.Context) error
PauseLifecycle()
ResumeLifecycle()
}
MVCCLifecycleEngine is an optional extension interface for lifecycle management.
type MVCCLifecycleScheduleEngine ¶
MVCCLifecycleScheduleEngine is an optional extension for runtime lifecycle cadence control.
type MVCCMaintenanceEngine ¶
type MVCCMaintenanceEngine interface {
RebuildMVCCHeads(ctx context.Context) error
PruneMVCCVersions(ctx context.Context, opts MVCCPruneOptions) (int64, error)
}
MVCCMaintenanceEngine is an optional extension interface for rebuild and prune operations.
type MVCCPruneOptions ¶
MVCCPruneOptions controls pruning of older MVCC versions. Zero values inherit the engine's configured RetentionPolicy.
type MVCCReadMode ¶
type MVCCReadMode string
MVCCReadMode selects latest-visible versus snapshot-visible reads.
const ( MVCCReadLatest MVCCReadMode = "latest" MVCCReadSnapshot MVCCReadMode = "snapshot" )
type MVCCReadSelector ¶
type MVCCReadSelector struct {
Mode MVCCReadMode
Version MVCCVersion
}
MVCCReadSelector describes which committed version a read should resolve.
type MVCCVersion ¶
MVCCVersion identifies one committed storage version.
Versions are ordered first by committed timestamp, then by a monotonic sequence allocated at commit time to break same-timestamp ties.
func (MVCCVersion) Compare ¶
func (v MVCCVersion) Compare(other MVCCVersion) int
Compare returns -1, 0, or 1 using MVCC ordering semantics.
func (MVCCVersion) IsZero ¶
func (v MVCCVersion) IsZero() bool
IsZero reports whether the version is uninitialized.
func (MVCCVersion) String ¶
func (v MVCCVersion) String() string
String renders a stable debug form for logs and diagnostics.
type MVCCVisibilityEngine ¶
type MVCCVisibilityEngine interface {
GetNodeLatestVisible(id NodeID) (*Node, error)
GetNodeVisibleAt(id NodeID, version MVCCVersion) (*Node, error)
GetEdgeLatestVisible(id EdgeID) (*Edge, error)
GetEdgeVisibleAt(id EdgeID, version MVCCVersion) (*Edge, error)
}
MVCCVisibilityEngine is an optional extension interface for latest and snapshot-visible node and edge reads.
type MemoryEngine ¶
type MemoryEngine struct {
*BadgerEngine
}
MemoryEngine is a thread-safe in-memory graph storage implementation. It wraps BadgerDB's in-memory mode for testing purposes.
Use Cases:
- Unit testing (no disk I/O, fast cleanup)
- Loading Neo4j exports into memory for analysis
- Small datasets that fit entirely in RAM
- Development and prototyping
Implementation Note:
MemoryEngine is a thin wrapper around BadgerEngine with InMemory=true. This ensures tests use the exact same code path as production.
func NewMemoryEngine ¶
func NewMemoryEngine() *MemoryEngine
NewMemoryEngine creates a new in-memory storage engine for testing. It uses BadgerDB's in-memory mode internally.
Example:
engine := storage.NewMemoryEngine() defer engine.Close()
Note: For tests, prefer storage.NewTestEngine(t) which handles cleanup.
func RecoverFromWAL ¶
func RecoverFromWAL(walDir, snapshotPath string) (*MemoryEngine, error)
RecoverFromWAL recovers database state from a snapshot and WAL. Returns a new MemoryEngine with the recovered state.
func (*MemoryEngine) BeginTransaction ¶
func (m *MemoryEngine) BeginTransaction() (*BadgerTransaction, error)
BeginTransaction starts a new transaction. Returns *BadgerTransaction for compatibility with the executor.
func (*MemoryEngine) DeleteByPrefix ¶
func (m *MemoryEngine) DeleteByPrefix(prefix string) (nodesDeleted int64, edgesDeleted int64, err error)
DeleteByPrefix delegates to the underlying BadgerEngine.
type NamespaceLister ¶
type NamespaceLister interface {
ListNamespaces() []string
}
NamespaceLister is an optional extension interface that reports the known database namespaces stored in an engine.
Returned values are unqualified namespace names (e.g., "nornic", "db2"), not ID prefixes (e.g., "nornic:").
type NamespaceSchemaProvider ¶
type NamespaceSchemaProvider interface {
GetSchemaForNamespace(namespace string) *SchemaManager
}
NamespaceSchemaProvider is an optional extension interface that provides per-namespace schema.
This enables multi-database deployments to maintain isolated constraints/indexes per database, matching Neo4j’s per-database schema model.
type NamespaceTemporalCurrentNodeProvider ¶
type NamespaceTemporalCurrentNodeProvider interface {
IsCurrentTemporalNodeInNamespace(namespace string, node *Node, asOf time.Time) (bool, error)
}
NamespaceTemporalCurrentNodeProvider is an optional extension interface that evaluates current/live temporal versions within a namespace.
type NamespaceTemporalLookupProvider ¶
type NamespaceTemporalLookupProvider interface {
GetTemporalNodeAsOfInNamespace(namespace, label, keyProp string, keyValue interface{}, validFromProp, validToProp string, asOf time.Time) (*Node, error)
}
NamespaceTemporalLookupProvider is an optional extension interface that provides efficient temporal lookups scoped to a storage namespace.
type NamespacedEngine ¶
type NamespacedEngine struct {
// contains filtered or unexported fields
}
NamespacedEngine wraps a storage engine with database namespace isolation. All node and edge IDs are automatically prefixed with the namespace.
This provides logical database separation within a single physical storage:
- Keys are prefixed: "tenant_a:node:123" instead of "node:123"
- Queries only see data in the current namespace
- DROP DATABASE = delete all keys with prefix
Thread-safe: delegates to underlying engine's thread safety.
func NewNamespacedEngine ¶
func NewNamespacedEngine(inner Engine, namespace string) *NamespacedEngine
NewNamespacedEngine creates a namespaced view of the storage engine.
Parameters:
- inner: The underlying storage engine (shared across all namespaces)
- namespace: The database name (e.g., "tenant_a", "nornic")
The namespace is used as a key prefix for all operations.
func (*NamespacedEngine) AddToPendingEmbeddings ¶
func (n *NamespacedEngine) AddToPendingEmbeddings(nodeID NodeID)
AddToPendingEmbeddings adds a node back to the pending embeddings index (e.g. after a failed embed so it can be retried).
func (*NamespacedEngine) AllEdges ¶
func (n *NamespacedEngine) AllEdges() ([]*Edge, error)
func (*NamespacedEngine) AllNodes ¶
func (n *NamespacedEngine) AllNodes() ([]*Node, error)
func (*NamespacedEngine) BatchGetNodes ¶
func (n *NamespacedEngine) BatchGetNodes(ids []NodeID) (map[NodeID]*Node, error)
func (*NamespacedEngine) BulkCreateEdges ¶
func (n *NamespacedEngine) BulkCreateEdges(edges []*Edge) error
func (*NamespacedEngine) BulkCreateNodes ¶
func (n *NamespacedEngine) BulkCreateNodes(nodes []*Node) error
func (*NamespacedEngine) BulkDeleteEdges ¶
func (n *NamespacedEngine) BulkDeleteEdges(ids []EdgeID) error
func (*NamespacedEngine) BulkDeleteNodes ¶
func (n *NamespacedEngine) BulkDeleteNodes(ids []NodeID) error
func (*NamespacedEngine) Close ¶
func (n *NamespacedEngine) Close() error
func (*NamespacedEngine) CreateEdge ¶
func (n *NamespacedEngine) CreateEdge(edge *Edge) error
func (*NamespacedEngine) CreateNode ¶
func (n *NamespacedEngine) CreateNode(node *Node) (NodeID, error)
func (*NamespacedEngine) DeleteByPrefix ¶
func (n *NamespacedEngine) DeleteByPrefix(prefix string) (nodesDeleted int64, edgesDeleted int64, err error)
DeleteByPrefix is not supported for NamespacedEngine. Use the underlying engine's DeleteByPrefix with the namespace prefix instead.
func (*NamespacedEngine) DeleteEdge ¶
func (n *NamespacedEngine) DeleteEdge(id EdgeID) error
func (*NamespacedEngine) DeleteNode ¶
func (n *NamespacedEngine) DeleteNode(id NodeID) error
func (*NamespacedEngine) EdgeCount ¶
func (n *NamespacedEngine) EdgeCount() (int64, error)
func (*NamespacedEngine) FindNodeNeedingEmbedding ¶
func (n *NamespacedEngine) FindNodeNeedingEmbedding() *Node
FindNodeNeedingEmbedding finds a node that needs embedding, but only from this namespace. It only looks for nodes with the current namespace prefix - all IDs must be prefixed.
func (*NamespacedEngine) ForEachNodeIDByLabel ¶
func (n *NamespacedEngine) ForEachNodeIDByLabel(label string, visit func(NodeID) bool) error
ForEachNodeIDByLabel streams node IDs for a label, filtered to the namespace. Stops early when visit returns false.
func (*NamespacedEngine) GetAllNodes ¶
func (n *NamespacedEngine) GetAllNodes() []*Node
func (*NamespacedEngine) GetEdgeBetween ¶
func (n *NamespacedEngine) GetEdgeBetween(startID, endID NodeID, edgeType string) *Edge
func (*NamespacedEngine) GetEdgeCurrentHead ¶
func (n *NamespacedEngine) GetEdgeCurrentHead(id EdgeID) (MVCCHead, error)
GetEdgeCurrentHead resolves edge head metadata within the namespace.
func (*NamespacedEngine) GetEdgeLatestVisible ¶
func (n *NamespacedEngine) GetEdgeLatestVisible(id EdgeID) (*Edge, error)
GetEdgeLatestVisible resolves the latest visible edge within the namespace.
func (*NamespacedEngine) GetEdgeVisibleAt ¶
func (n *NamespacedEngine) GetEdgeVisibleAt(id EdgeID, version MVCCVersion) (*Edge, error)
GetEdgeVisibleAt resolves a snapshot-visible edge within the namespace.
func (*NamespacedEngine) GetEdgesBetween ¶
func (n *NamespacedEngine) GetEdgesBetween(startID, endID NodeID) ([]*Edge, error)
func (*NamespacedEngine) GetEdgesBetweenVisibleAt ¶
func (n *NamespacedEngine) GetEdgesBetweenVisibleAt(startID, endID NodeID, version MVCCVersion) ([]*Edge, error)
GetEdgesBetweenVisibleAt resolves snapshot-visible topology queries within the namespace.
func (*NamespacedEngine) GetEdgesByType ¶
func (n *NamespacedEngine) GetEdgesByType(edgeType string) ([]*Edge, error)
func (*NamespacedEngine) GetEdgesByTypeVisibleAt ¶
func (n *NamespacedEngine) GetEdgesByTypeVisibleAt(edgeType string, version MVCCVersion) ([]*Edge, error)
GetEdgesByTypeVisibleAt resolves snapshot-visible edge-type queries within the namespace.
func (*NamespacedEngine) GetFirstNodeByLabel ¶
func (n *NamespacedEngine) GetFirstNodeByLabel(label string) (*Node, error)
func (*NamespacedEngine) GetInDegree ¶
func (n *NamespacedEngine) GetInDegree(nodeID NodeID) int
func (*NamespacedEngine) GetIncomingEdges ¶
func (n *NamespacedEngine) GetIncomingEdges(nodeID NodeID) ([]*Edge, error)
func (*NamespacedEngine) GetInnerEngine ¶
func (n *NamespacedEngine) GetInnerEngine() Engine
GetInnerEngine returns the underlying storage engine (unwraps the namespace). This is used by DatabaseManager to create NamespacedEngines for other databases.
func (*NamespacedEngine) GetNodeCurrentHead ¶
func (n *NamespacedEngine) GetNodeCurrentHead(id NodeID) (MVCCHead, error)
GetNodeCurrentHead resolves node head metadata within the namespace.
func (*NamespacedEngine) GetNodeLatestVisible ¶
func (n *NamespacedEngine) GetNodeLatestVisible(id NodeID) (*Node, error)
GetNodeLatestVisible resolves the latest visible node within the namespace.
func (*NamespacedEngine) GetNodeVisibleAt ¶
func (n *NamespacedEngine) GetNodeVisibleAt(id NodeID, version MVCCVersion) (*Node, error)
GetNodeVisibleAt resolves a snapshot-visible node within the namespace.
func (*NamespacedEngine) GetNodesByLabel ¶
func (n *NamespacedEngine) GetNodesByLabel(label string) ([]*Node, error)
func (*NamespacedEngine) GetNodesByLabelVisibleAt ¶
func (n *NamespacedEngine) GetNodesByLabelVisibleAt(label string, version MVCCVersion) ([]*Node, error)
GetNodesByLabelVisibleAt resolves snapshot-visible label queries within the namespace.
func (*NamespacedEngine) GetOutDegree ¶
func (n *NamespacedEngine) GetOutDegree(nodeID NodeID) int
func (*NamespacedEngine) GetOutgoingEdges ¶
func (n *NamespacedEngine) GetOutgoingEdges(nodeID NodeID) ([]*Edge, error)
func (*NamespacedEngine) GetSchema ¶
func (n *NamespacedEngine) GetSchema() *SchemaManager
func (*NamespacedEngine) GetTemporalNodeAsOf ¶
func (n *NamespacedEngine) GetTemporalNodeAsOf(label, keyProp string, keyValue interface{}, validFromProp, validToProp string, asOf time.Time) (*Node, error)
GetTemporalNodeAsOf performs an efficient temporal lookup when the inner engine supports it.
func (*NamespacedEngine) IsCurrentTemporalNode ¶
IsCurrentTemporalNode reports whether node is the current/live temporal version.
func (*NamespacedEngine) LastWriteTime ¶
func (n *NamespacedEngine) LastWriteTime() time.Time
LastWriteTime returns the last known write time from the underlying engine, if available.
func (*NamespacedEngine) LifecycleStatus ¶
func (n *NamespacedEngine) LifecycleStatus() map[string]interface{}
LifecycleStatus delegates lifecycle status when supported.
func (*NamespacedEngine) MarkNodeEmbedded ¶
func (n *NamespacedEngine) MarkNodeEmbedded(nodeID NodeID)
MarkNodeEmbedded marks a node as embedded (removes from pending index). The node ID should be unprefixed (without namespace).
func (*NamespacedEngine) Namespace ¶
func (n *NamespacedEngine) Namespace() string
Namespace returns the current database namespace.
func (*NamespacedEngine) NodeCount ¶
func (n *NamespacedEngine) NodeCount() (int64, error)
func (*NamespacedEngine) PauseLifecycle ¶
func (n *NamespacedEngine) PauseLifecycle()
PauseLifecycle delegates lifecycle pause when supported.
func (*NamespacedEngine) RefreshPendingEmbeddingsIndex ¶
func (n *NamespacedEngine) RefreshPendingEmbeddingsIndex() int
RefreshPendingEmbeddingsIndex refreshes the pending embeddings index, but only for nodes in this namespace. Also cleans up stale entries from other namespaces in the underlying index.
func (*NamespacedEngine) RegisterSnapshotReader ¶
func (n *NamespacedEngine) RegisterSnapshotReader(info SnapshotReaderInfo) func()
RegisterSnapshotReader registers a reader scoped to the namespace when supported.
func (*NamespacedEngine) ResumeLifecycle ¶
func (n *NamespacedEngine) ResumeLifecycle()
ResumeLifecycle delegates lifecycle resume when supported.
func (*NamespacedEngine) SetLifecycleSchedule ¶
func (n *NamespacedEngine) SetLifecycleSchedule(interval time.Duration) error
SetLifecycleSchedule delegates lifecycle cadence updates when supported.
func (*NamespacedEngine) StreamEdges ¶
StreamEdges streams edges in the namespace.
func (*NamespacedEngine) StreamNodeChunks ¶
func (n *NamespacedEngine) StreamNodeChunks(ctx context.Context, chunkSize int, fn func(nodes []*Node) error) error
StreamNodeChunks streams nodes in chunks.
func (*NamespacedEngine) StreamNodes ¶
StreamNodes streams nodes in the namespace.
func (*NamespacedEngine) TopLifecycleDebtKeys ¶
func (n *NamespacedEngine) TopLifecycleDebtKeys(limit int) []MVCCLifecycleDebtKey
TopLifecycleDebtKeys delegates lifecycle debt inspection when supported.
func (*NamespacedEngine) TriggerPruneNow ¶
func (n *NamespacedEngine) TriggerPruneNow(ctx context.Context) error
TriggerPruneNow delegates lifecycle prune-now when supported.
func (*NamespacedEngine) UpdateEdge ¶
func (n *NamespacedEngine) UpdateEdge(edge *Edge) error
func (*NamespacedEngine) UpdateNode ¶
func (n *NamespacedEngine) UpdateNode(node *Node) error
type Neo4jExport ¶
type Neo4jExport struct {
Nodes []Neo4jNode `json:"nodes"`
Relationships []Neo4jRelationship `json:"relationships"`
}
Neo4jExport represents the Neo4j JSON export format. This is compatible with `neo4j-admin database dump` JSON output.
func ToNeo4jExport ¶
func ToNeo4jExport(nodes []*Node, edges []*Edge) *Neo4jExport
ToNeo4jExport converts NornicDB nodes and edges to Neo4j JSON export format.
This function prepares data for export that can be imported into Neo4j using neo4j-admin or APOC procedures. NornicDB-specific fields (decay score, embeddings, access counts) are stored with "_" prefix to mark them as system properties.
The output is compatible with:
- `neo4j-admin database import`
- `CALL apoc.import.json()`
- Standard Neo4j JSON format
Example:
// Get all data
nodes, _ := engine.GetNodesByLabel("") // All nodes
edges, _ := engine.AllEdges()
// Convert to Neo4j format
export := storage.ToNeo4jExport(nodes, edges)
// Save as JSON
data, _ := json.MarshalIndent(export, "", " ")
err := os.WriteFile("neo4j-export.json", data, 0644)
// Import into Neo4j
// $ neo4j-admin database import --nodes=neo4j-export.json full
// Or in Cypher:
// CALL apoc.import.json("file:///neo4j-export.json")
NornicDB extensions are preserved as properties:
_decayScore, _lastAccessed, _accessCount, _confidence, _autoGenerated
type Neo4jNode ¶
type Neo4jNode struct {
ID string `json:"id"`
Labels []string `json:"labels"`
Properties map[string]any `json:"properties"`
}
Neo4jNode is the Neo4j JSON export format for nodes.
type Neo4jNodeRef ¶
Neo4jNodeRef is a reference to a node in Neo4j relationship format.
type Neo4jRelationship ¶
type Neo4jRelationship struct {
ID string `json:"id"`
Type string `json:"type"`
Properties map[string]any `json:"properties"`
// Flat format (neo4j-admin dump)
StartNode string `json:"startNode,omitempty"`
EndNode string `json:"endNode,omitempty"`
// APOC format (apoc.export.json)
Start Neo4jNodeRef `json:"start,omitempty"`
End Neo4jNodeRef `json:"end,omitempty"`
}
Neo4jRelationship is the Neo4j JSON export format for relationships. Supports both flat format (startNode/endNode strings) and APOC format (start/end objects).
func (*Neo4jRelationship) GetEndID ¶
func (r *Neo4jRelationship) GetEndID() string
GetEndID returns the end node ID regardless of format.
func (*Neo4jRelationship) GetStartID ¶
func (r *Neo4jRelationship) GetStartID() string
GetStartID returns the start node ID supporting both Neo4j export formats.
Neo4j exports can use two formats:
- Flat format: startNode/endNode as strings (neo4j-admin dump)
- APOC format: start/end as objects (apoc.export.json)
This method abstracts the difference, always returning the start node ID.
Example:
// Flat format
rel := &Neo4jRelationship{
StartNode: "user-123",
}
fmt.Println(rel.GetStartID()) // "user-123"
// APOC format
rel = &Neo4jRelationship{
Start: Neo4jNodeRef{ID: "user-456"},
}
fmt.Println(rel.GetStartID()) // "user-456"
type Node ¶
type Node struct {
ID NodeID `json:"id"`
Labels []string `json:"labels"`
Properties map[string]any `json:"properties"`
// NornicDB extensions
CreatedAt time.Time `json:"-"`
UpdatedAt time.Time `json:"-"`
DecayScore float64 `json:"-"`
LastAccessed time.Time `json:"-"`
AccessCount int64 `json:"-"`
NamedEmbeddings map[string][]float32 `json:"-"` // Named vector embeddings (e.g., "title", "content", "default")
ChunkEmbeddings [][]float32 `json:"-"` // Chunked embeddings for long documents (legacy, migration support)
// Embedding metadata (separate from user Properties to avoid namespace pollution)
// Keys: embedding_model, embedding_dimensions, has_embedding, embedded_at, has_chunks, chunk_count
EmbedMeta map[string]any `json:"-"`
// Internal storage flags (not exposed to users, used during encode/decode)
EmbeddingsStoredSeparately bool `json:"-"` // True when embeddings are stored in separate keys (large node optimization)
}
Node represents a graph node (vertex) in the labeled property graph.
Nodes follow the Neo4j data model with NornicDB-specific extensions for memory decay, semantic search, and access tracking. Nodes are the fundamental entities in the graph and can represent people, documents, concepts, or any other entity in your domain.
Core Neo4j Fields:
- ID: Unique identifier (must be unique across all nodes)
- Labels: Type tags like ["Person", "User"] (Neo4j :Person:User)
- Properties: Key-value data (any JSON-serializable types) See docs/user-guides/property-data-types.md for complete type reference
NornicDB Extensions (not exported to Neo4j):
- CreatedAt: When the node was first created
- UpdatedAt: Last modification timestamp
- DecayScore: Memory importance (1.0=fresh, 0.0=decayed)
- LastAccessed: Last time node was queried/updated
- AccessCount: Total access frequency
- NamedEmbeddings: Named vector embeddings (e.g., "title", "content", "default")
- ChunkEmbeddings: Chunked embeddings for long documents (legacy, migration support)
Example 1 - Basic User Node:
node := &storage.Node{
ID: storage.NodeID("user-alice"),
Labels: []string{"Person", "User"},
Properties: map[string]any{
"name": "Alice Johnson",
"age": 30,
"email": "alice@example.com",
"verified": true,
},
CreatedAt: time.Now(),
DecayScore: 1.0, // Fresh memory
AccessCount: 0,
}
engine.CreateNode(node)
Example 2 - Document Node with Metadata:
doc := &storage.Node{
ID: storage.NodeID("doc-readme"),
Labels: []string{"Document", "Markdown"},
Properties: map[string]any{
"title": "README.md",
"content": "# Welcome to...",
"path": "./README.md",
"size": 4096,
"language": "markdown",
},
CreatedAt: time.Now(),
Embedding: generateEmbedding("# Welcome to..."), // For semantic search
}
Example 3 - Concept Node for Knowledge Graph:
concept := &storage.Node{
ID: storage.NodeID("concept-database"),
Labels: []string{"Concept", "Technology"},
Properties: map[string]any{
"name": "Database Systems",
"definition": "Systems for storing and retrieving data",
"category": "Software",
"importance": "high",
},
DecayScore: 0.95, // Slightly aged but still relevant
AccessCount: 42, // Accessed 42 times
LastAccessed: time.Now().Add(-24 * time.Hour),
}
ELI12:
Think of a Node like a character card in a trading card game:
- ID: The card's unique number (no two cards have the same)
- Labels: The types on the card (["Hero", "Warrior"])
- Properties: Stats on the card (name: "Alice", strength: 10, health: 100)
NornicDB adds extra info:
- DecayScore: How "fresh" the card is (new cards = 1.0, old forgotten cards = 0.2)
- AccessCount: How many times you've played this card
- Embedding: A secret code that helps find similar cards
Just like trading cards can be rare or common, frequently used or forgotten, Nodes track their usage and importance in the graph!
Neo4j Compatibility:
- Labels map to Neo4j labels (e.g., :Person:User)
- Properties map to Neo4j properties
- ID must be unique across all nodes
- Extensions stored with "_" prefix in Neo4j exports
Thread Safety:
Node structs are NOT thread-safe. The storage engine handles concurrency.
func FindNodeNeedingEmbedding ¶
FindNodeNeedingEmbedding finds a single node that needs embedding. This is more efficient than AllNodes() as it stops after finding one.
func (*Node) ExtractInternalProperties ¶
func (n *Node) ExtractInternalProperties()
ExtractInternalProperties extracts NornicDB-specific fields from properties.
func (*Node) GetDefaultEmbedding ¶
GetDefaultEmbedding returns the default embedding for a node, implementing migration behavior from ChunkEmbeddings to NamedEmbeddings.
Migration behavior (temporary):
- If NamedEmbeddings["default"] exists, return it
- Otherwise, if ChunkEmbeddings has at least one vector, treat ChunkEmbeddings[0] as "default"
- Otherwise, return nil
This allows backward compatibility with existing nodes that only have ChunkEmbeddings while transitioning to the new NamedEmbeddings model.
Example:
node := &storage.Node{
ID: storage.NodeID("doc-1"),
NamedEmbeddings: map[string][]float32{
"default": []float32{0.1, 0.2, 0.3},
},
}
emb := node.GetDefaultEmbedding() // Returns []float32{0.1, 0.2, 0.3}
// Legacy node with ChunkEmbeddings
legacyNode := &storage.Node{
ID: storage.NodeID("doc-2"),
ChunkEmbeddings: [][]float32{{0.4, 0.5, 0.6}},
}
emb = legacyNode.GetDefaultEmbedding() // Returns []float32{0.4, 0.5, 0.6}
func (*Node) MarshalNeo4jJSON ¶
MarshalNeo4jJSON serializes to Neo4j-compatible JSON.
type NodeConfig ¶
type NodeConfig struct {
// Node identification
NodeID string `json:"node_id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
// Pin/Deny lists
PinList []string `json:"pin_list"` // Target node IDs that never decay
DenyList []string `json:"deny_list"` // Target node IDs to never connect to
// Edge caps
MaxOutEdges int `json:"max_out_edges"` // Maximum outgoing edges (0 = unlimited)
MaxInEdges int `json:"max_in_edges"` // Maximum incoming edges (0 = unlimited)
MaxTotalEdges int `json:"max_total_edges"` // Maximum total edges (0 = unlimited)
// Current edge counts (for cap enforcement)
CurrentOutEdges int `json:"current_out_edges"`
CurrentInEdges int `json:"current_in_edges"`
CurrentTotalEdges int `json:"current_total_edges"`
// Per-label configuration
LabelConfigs map[string]LabelConfig `json:"label_configs"`
// Trust level
TrustLevel TrustLevel `json:"trust_level"`
// Global overrides
MinConfidence float64 `json:"min_confidence"` // Override default threshold (0 = use default)
Cooldown time.Duration `json:"cooldown"` // Override default cooldown (0 = use default)
Disabled bool `json:"disabled"` // Completely disable edge creation to/from this node
// Metadata
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
NodeConfig stores per-node edge materialization settings.
func NewNodeConfig ¶
func NewNodeConfig(nodeID string) *NodeConfig
NewNodeConfig creates a new node config with defaults.
func (*NodeConfig) AddToDeny ¶
func (c *NodeConfig) AddToDeny(targetID string)
AddToDeny adds a target to the deny list.
func (*NodeConfig) AddToPin ¶
func (c *NodeConfig) AddToPin(targetID string)
AddToPin adds a target to the pin list.
func (*NodeConfig) CanAddEdge ¶
func (c *NodeConfig) CanAddEdge(isOutgoing bool) bool
CanAddEdge returns true if another edge can be added (checks all caps).
func (*NodeConfig) CanAddInEdge ¶
func (c *NodeConfig) CanAddInEdge() bool
CanAddInEdge returns true if another incoming edge can be added.
func (*NodeConfig) CanAddOutEdge ¶
func (c *NodeConfig) CanAddOutEdge() bool
CanAddOutEdge returns true if another outgoing edge can be added.
func (*NodeConfig) DecrementEdgeCount ¶
func (c *NodeConfig) DecrementEdgeCount(isOutgoing bool)
DecrementEdgeCount decrements the edge count.
func (*NodeConfig) GetEffectiveConfidence ¶
func (c *NodeConfig) GetEffectiveConfidence(label string, baseThreshold float64) float64
GetEffectiveConfidence returns the effective minimum confidence threshold. Considers trust level adjustment and per-label overrides.
func (*NodeConfig) GetLabelConfig ¶
func (c *NodeConfig) GetLabelConfig(label string) (LabelConfig, bool)
GetLabelConfig returns the config for a specific label.
func (*NodeConfig) IncrementEdgeCount ¶
func (c *NodeConfig) IncrementEdgeCount(isOutgoing bool)
IncrementEdgeCount increments the edge count.
func (*NodeConfig) IsDenied ¶
func (c *NodeConfig) IsDenied(targetID string) bool
IsDenied returns true if the target is in the deny list.
func (*NodeConfig) IsPinned ¶
func (c *NodeConfig) IsPinned(targetID string) bool
IsPinned returns true if the target is in the pin list.
func (*NodeConfig) RemoveFromDeny ¶
func (c *NodeConfig) RemoveFromDeny(targetID string) bool
RemoveFromDeny removes a target from the deny list.
func (*NodeConfig) RemoveFromPin ¶
func (c *NodeConfig) RemoveFromPin(targetID string) bool
RemoveFromPin removes a target from the pin list.
func (*NodeConfig) SetLabelConfig ¶
func (c *NodeConfig) SetLabelConfig(label string, cfg LabelConfig)
SetLabelConfig sets the config for a specific label.
type NodeConfigStats ¶
type NodeConfigStats struct {
TotalConfigs int64
TotalChecks int64
TotalBlocked int64
BlockRate float64
}
NodeConfigStats provides observability into per-node config state.
type NodeConfigStore ¶
type NodeConfigStore struct {
// contains filtered or unexported fields
}
NodeConfigStore manages per-node configurations. Thread-safe for concurrent access.
func GlobalNodeConfigStore ¶
func GlobalNodeConfigStore() *NodeConfigStore
GlobalNodeConfigStore returns the global node config store singleton.
func NewNodeConfigStore ¶
func NewNodeConfigStore() *NodeConfigStore
NewNodeConfigStore creates a new per-node config store.
func NewNodeConfigStoreWithOptions ¶
func NewNodeConfigStoreWithOptions(opts ...NodeConfigStoreOption) *NodeConfigStore
NewNodeConfigStoreWithOptions creates a store with functional options.
func (*NodeConfigStore) AddToNodeDenyList ¶
func (s *NodeConfigStore) AddToNodeDenyList(nodeID, targetID string)
AddToNodeDenyList adds a target to a node's deny list.
func (*NodeConfigStore) AddToNodePinList ¶
func (s *NodeConfigStore) AddToNodePinList(nodeID, targetID string)
AddToNodePinList adds a target to a node's pin list.
func (*NodeConfigStore) Delete ¶
func (s *NodeConfigStore) Delete(nodeID string) bool
Delete removes a node config.
func (*NodeConfigStore) DisableNode ¶
func (s *NodeConfigStore) DisableNode(nodeID string)
DisableNode disables all edge creation to/from a node.
func (*NodeConfigStore) EnableNode ¶
func (s *NodeConfigStore) EnableNode(nodeID string)
EnableNode enables edge creation to/from a node.
func (*NodeConfigStore) Export ¶
func (s *NodeConfigStore) Export() []*NodeConfig
Export returns all configs for backup/export.
func (*NodeConfigStore) Get ¶
func (s *NodeConfigStore) Get(nodeID string) *NodeConfig
Get returns the config for a node, or nil if none exists.
func (*NodeConfigStore) GetAllNodeIDs ¶
func (s *NodeConfigStore) GetAllNodeIDs() []string
GetAllNodeIDs returns all configured node IDs.
func (*NodeConfigStore) GetDeniedTargets ¶
func (s *NodeConfigStore) GetDeniedTargets(nodeID string) []string
GetDeniedTargets returns all denied targets for a node.
func (*NodeConfigStore) GetEffectiveConfidence ¶
func (s *NodeConfigStore) GetEffectiveConfidence(sourceID, targetID, label string, baseThreshold float64) float64
GetEffectiveConfidence returns the effective confidence threshold for an edge.
func (*NodeConfigStore) GetOrCreate ¶
func (s *NodeConfigStore) GetOrCreate(nodeID string) *NodeConfig
GetOrCreate returns the config for a node, creating one if it doesn't exist.
func (*NodeConfigStore) GetPinnedTargets ¶
func (s *NodeConfigStore) GetPinnedTargets(nodeID string) []string
GetPinnedTargets returns all pinned targets for a node.
func (*NodeConfigStore) Import ¶
func (s *NodeConfigStore) Import(configs []*NodeConfig) int
Import loads configs from backup/import. Existing configs are NOT cleared - use Clear() first if needed.
func (*NodeConfigStore) IsEdgeAllowed ¶
func (s *NodeConfigStore) IsEdgeAllowed(sourceID, targetID, label string) bool
IsEdgeAllowed checks if an edge from source to target is allowed. Considers: feature flag, disabled state, deny list, and edge caps.
func (*NodeConfigStore) IsEdgeAllowedWithReason ¶
func (s *NodeConfigStore) IsEdgeAllowedWithReason(sourceID, targetID, label string) (bool, string)
IsEdgeAllowedWithReason checks if an edge is allowed and returns the reason.
func (*NodeConfigStore) IsPinned ¶
func (s *NodeConfigStore) IsPinned(sourceID, targetID string) bool
IsPinned checks if an edge should never decay.
func (*NodeConfigStore) RecordEdgeCreation ¶
func (s *NodeConfigStore) RecordEdgeCreation(sourceID, targetID string)
RecordEdgeCreation updates edge counts after an edge is created.
func (*NodeConfigStore) RecordEdgeDeletion ¶
func (s *NodeConfigStore) RecordEdgeDeletion(sourceID, targetID string)
RecordEdgeDeletion updates edge counts after an edge is deleted.
func (*NodeConfigStore) Set ¶
func (s *NodeConfigStore) Set(cfg NodeConfig)
Set stores a node config.
func (*NodeConfigStore) SetNodeEdgeCaps ¶
func (s *NodeConfigStore) SetNodeEdgeCaps(nodeID string, maxOut, maxIn, maxTotal int)
SetNodeEdgeCaps sets edge caps for a node.
func (*NodeConfigStore) SetNodeTrustLevel ¶
func (s *NodeConfigStore) SetNodeTrustLevel(nodeID string, level TrustLevel)
SetNodeTrustLevel sets the trust level for a node.
func (*NodeConfigStore) Size ¶
func (s *NodeConfigStore) Size() int
Size returns the number of configured nodes.
func (*NodeConfigStore) Stats ¶
func (s *NodeConfigStore) Stats() NodeConfigStats
Stats returns current store statistics.
type NodeConfigStoreOption ¶
type NodeConfigStoreOption func(*NodeConfigStore)
NodeConfigStoreOption configures a NodeConfigStore.
type NodeDeleteCallback ¶
type NodeDeleteCallback func(nodeID NodeID)
NodeDeleteCallback is called when a node is successfully deleted from storage.
type NodeEventCallback ¶
type NodeEventCallback func(node *Node)
NodeEventCallback is called when storage operations complete successfully. This allows external services (like search indexes) to stay synchronized with storage.
type NodeID ¶
type NodeID string
NodeID is a strongly-typed unique identifier for graph nodes.
Using a custom type provides:
- Type safety (can't accidentally use EdgeID where NodeID is expected)
- Clear API semantics
- Future extensibility (could add methods)
Example:
id := storage.NodeID("user-123")
node, err := engine.GetNode(id)
func FirstNodeIDByLabel ¶
FirstNodeIDByLabel returns the first node ID for a label without decoding nodes when possible. Returns ErrNotFound if no node matches.
type NodeVisitor ¶
NodeVisitor is a function called for each node during streaming.
type Operation ¶
type Operation struct {
Type OperationType
Timestamp time.Time
// For node operations
NodeID NodeID
Node *Node // New state (for create/update) or nil
OldNode *Node // Old state (for update/delete rollback)
// For delete operations that cascade (e.g., DeleteNode deletes edges).
EdgesDeleted int64
DeletedEdgeIDs []EdgeID
// For edge operations
EdgeID EdgeID
Edge *Edge // New state (for create/update) or nil
OldEdge *Edge // Old state (for update/delete rollback)
}
Operation represents a single operation within a transaction. Used by BadgerTransaction to track operations for constraint validation.
type OperationType ¶
type OperationType string
OperationType represents the type of operation in a transaction.
const ( OpCreateNode OperationType = "create_node" OpUpdateNode OperationType = "update_node" OpDeleteNode OperationType = "delete_node" OpCreateEdge OperationType = "create_edge" OpUpdateEdge OperationType = "update_edge" OpDeleteEdge OperationType = "delete_edge" OpUpdateEmbedding OperationType = "update_embedding" // Safe to skip on corruption - regenerable )
const ( OpBulkNodes OperationType = "bulk_create_nodes" OpBulkEdges OperationType = "bulk_create_edges" OpBulkDeleteNodes OperationType = "bulk_delete_nodes" OpBulkDeleteEdges OperationType = "bulk_delete_edges" OpCheckpoint OperationType = "checkpoint" // Marks snapshot boundaries // Transaction boundary markers for ACID compliance OpTxBegin OperationType = "tx_begin" // Marks transaction start OpTxCommit OperationType = "tx_commit" // Marks successful transaction completion OpTxAbort OperationType = "tx_abort" // Marks explicit transaction rollback )
Additional WAL operation types (extends OperationType from transaction.go)
type PrefixStatsEngine ¶
type PrefixStatsEngine interface {
NodeCountByPrefix(prefix string) (int64, error)
EdgeCountByPrefix(prefix string) (int64, error)
}
PrefixStatsEngine is an optional extension interface that provides fast per-prefix statistics without scanning and decoding all records.
The prefix refers to the *ID prefix* (e.g., a database namespace prefix like "nornic:") and is applied to stored NodeID/EdgeID values (not the internal key prefix bytes).
This is primarily used by NamespacedEngine so that NodeCount/EdgeCount can remain fast in multi-database deployments while still returning namespace-scoped results.
type PrefixStreamingEngine ¶
type PrefixStreamingEngine interface {
StreamingEngine
// StreamNodesByPrefix streams only nodes whose IDs start with the given prefix.
StreamNodesByPrefix(ctx context.Context, prefix string, fn func(node *Node) error) error
}
PrefixStreamingEngine extends StreamingEngine with namespace/key-prefix-aware streaming for efficient bounded scans on engines where IDs embed tenant/db prefixes. This avoids full-store scans followed by callback filtering.
type PressureBand ¶
type PressureBand string
PressureBand represents the MVCC storage pressure level.
const ( PressureNormal PressureBand = "normal" PressureHigh PressureBand = "high" PressureCritical PressureBand = "critical" )
type PropertyIndex ¶
type PropertyIndex struct {
Name string
Label string
Properties []string
// contains filtered or unexported fields
}
PropertyIndex represents a property index for faster lookups.
type PropertyType ¶
type PropertyType string
PropertyType represents the expected type of a property.
const ( PropertyTypeString PropertyType = "STRING" PropertyTypeInteger PropertyType = "INTEGER" PropertyTypeFloat PropertyType = "FLOAT" PropertyTypeBoolean PropertyType = "BOOLEAN" PropertyTypeDate PropertyType = "DATE" PropertyTypeDateTime PropertyType = "DATETIME" // Legacy alias for zoned datetime // Neo4j temporal property type constraints. PropertyTypeZonedDateTime PropertyType = "ZONED DATETIME" PropertyTypeLocalDateTime PropertyType = "LOCAL DATETIME" )
type PropertyTypeConstraint ¶
type PropertyTypeConstraint struct {
Name string `json:"name"`
EntityType ConstraintEntityType `json:"entity_type,omitempty"` // defaults to NODE when empty
Label string `json:"label"` // label for nodes, relationship type for relationships
Property string `json:"property"`
ExpectedType PropertyType `json:"expected_type"`
}
PropertyTypeConstraint represents a type constraint on properties.
func (PropertyTypeConstraint) EffectiveEntityType ¶
func (c PropertyTypeConstraint) EffectiveEntityType() ConstraintEntityType
EffectiveEntityType returns the entity type, defaulting to NODE for backward compatibility.
type PropertyTypeConstraintOptions ¶
type PropertyTypeConstraintOptions struct {
EntityType ConstraintEntityType
IfNotExists bool
}
AddPropertyTypeConstraint adds a property type constraint to the schema. This enforces a specific type for a property on a label (NULL values allowed). An optional entityType can be passed to specify RELATIONSHIP constraints. PropertyTypeConstraintOptions holds optional parameters for AddPropertyTypeConstraint.
type QueryAnalyzer ¶
type QueryAnalyzer struct {
// contains filtered or unexported fields
}
QueryAnalyzer analyzes queries to extract routing information.
func NewQueryAnalyzer ¶
func NewQueryAnalyzer() *QueryAnalyzer
NewQueryAnalyzer creates a new query analyzer for composite routing.
func (*QueryAnalyzer) AnalyzeQuery ¶
func (a *QueryAnalyzer) AnalyzeQuery(cypher string) *QueryInfo
AnalyzeQuery extracts routing information from a Cypher query string. This is a simplified analyzer - a full implementation would parse the AST.
func (*QueryAnalyzer) RouteQuery ¶
func (a *QueryAnalyzer) RouteQuery(queryInfo *QueryInfo, allConstituents []string) []string
RouteQuery determines which constituents to query based on query info.
func (*QueryAnalyzer) SetLabelRouting ¶
func (a *QueryAnalyzer) SetLabelRouting(label string, constituents []string)
SetLabelRouting configures label-based routing.
func (*QueryAnalyzer) SetPropertyDefault ¶
func (p *QueryAnalyzer) SetPropertyDefault(propertyName string, constituent string)
SetPropertyDefault sets the default constituent for a property when value not found.
func (*QueryAnalyzer) SetPropertyRouting ¶
func (p *QueryAnalyzer) SetPropertyRouting(propertyName string, value interface{}, constituent string)
SetPropertyRouting configures property-based routing.
type QueryInfo ¶
type QueryInfo struct {
Labels []string
Properties map[string]interface{}
IsWrite bool
IsFullScan bool
}
QueryInfo contains information extracted from a query for routing.
type RangeIndex ¶
type RangeIndex struct {
Name string
Label string
Property string
Properties []string // composite properties (for multi-property constraint indexes)
EntityType ConstraintEntityType // NODE or RELATIONSHIP
OwningConstraint string // name of the constraint that owns this index (empty if standalone)
// contains filtered or unexported fields
}
RangeIndex represents an index for range queries on a single property. It maintains a sorted list of entries for efficient O(log n) range queries.
type Receipt ¶
type Receipt struct {
TxID string `json:"tx_id"`
WALSeqStart uint64 `json:"wal_seq_start"`
WALSeqEnd uint64 `json:"wal_seq_end"`
Timestamp time.Time `json:"timestamp"`
Database string `json:"database,omitempty"`
Hash string `json:"hash"`
}
Receipt represents a mutation receipt tied to WAL sequencing. WALSeqEnd should refer to the commit marker sequence for the transaction.
func NewReceipt ¶
func NewReceipt(txID string, walSeqStart, walSeqEnd uint64, database string, timestamp time.Time) (*Receipt, error)
NewReceipt creates a receipt and computes its hash.
func (*Receipt) UpdateHash ¶
UpdateHash recomputes the receipt hash from canonical fields.
type RelationshipConstraint ¶
type RelationshipConstraint struct {
Name string
Type ConstraintType
RelType string // Relationship type (e.g., "KNOWS", "FOLLOWS")
Properties []string
}
RelationshipConstraint represents a constraint on relationship properties.
type RemoteCypherTx ¶
type RemoteCypherTx interface {
QueryCypher(ctx context.Context, statement string, params map[string]interface{}) ([]string, [][]interface{}, error)
Commit(ctx context.Context) error
Rollback(ctx context.Context) error
}
RemoteCypherTx represents an explicit remote Cypher transaction handle.
type RemoteEngine ¶
type RemoteEngine struct {
// contains filtered or unexported fields
}
RemoteEngine implements Engine by forwarding operations to a remote NornicDB instance via Bolt protocol (preferred) or HTTP tx API (fallback), auto-detected from the URI scheme.
func NewRemoteEngine ¶
func NewRemoteEngine(cfg RemoteEngineConfig) (*RemoteEngine, error)
NewRemoteEngine creates a remote engine. Transport is auto-detected from the URI scheme.
func (*RemoteEngine) AllEdges ¶
func (r *RemoteEngine) AllEdges() ([]*Edge, error)
func (*RemoteEngine) AllNodes ¶
func (r *RemoteEngine) AllNodes() ([]*Node, error)
func (*RemoteEngine) BatchGetNodes ¶
func (r *RemoteEngine) BatchGetNodes(ids []NodeID) (map[NodeID]*Node, error)
func (*RemoteEngine) BeginCypherTx ¶
func (r *RemoteEngine) BeginCypherTx(ctx context.Context) (RemoteCypherTx, error)
BeginCypherTx opens an explicit remote transaction handle.
func (*RemoteEngine) BulkCreateEdges ¶
func (r *RemoteEngine) BulkCreateEdges(edges []*Edge) error
func (*RemoteEngine) BulkCreateNodes ¶
func (r *RemoteEngine) BulkCreateNodes(nodes []*Node) error
func (*RemoteEngine) BulkDeleteEdges ¶
func (r *RemoteEngine) BulkDeleteEdges(ids []EdgeID) error
func (*RemoteEngine) BulkDeleteNodes ¶
func (r *RemoteEngine) BulkDeleteNodes(ids []NodeID) error
func (*RemoteEngine) Close ¶
func (r *RemoteEngine) Close() error
func (*RemoteEngine) CreateEdge ¶
func (r *RemoteEngine) CreateEdge(edge *Edge) error
func (*RemoteEngine) CreateNode ¶
func (r *RemoteEngine) CreateNode(node *Node) (NodeID, error)
func (*RemoteEngine) DeleteByPrefix ¶
func (r *RemoteEngine) DeleteByPrefix(prefix string) (nodesDeleted int64, edgesDeleted int64, err error)
func (*RemoteEngine) DeleteEdge ¶
func (r *RemoteEngine) DeleteEdge(id EdgeID) error
func (*RemoteEngine) DeleteNode ¶
func (r *RemoteEngine) DeleteNode(id NodeID) error
func (*RemoteEngine) EdgeCount ¶
func (r *RemoteEngine) EdgeCount() (int64, error)
func (*RemoteEngine) GetAllNodes ¶
func (r *RemoteEngine) GetAllNodes() []*Node
func (*RemoteEngine) GetEdgeBetween ¶
func (r *RemoteEngine) GetEdgeBetween(startID, endID NodeID, edgeType string) *Edge
func (*RemoteEngine) GetEdgesBetween ¶
func (r *RemoteEngine) GetEdgesBetween(startID, endID NodeID) ([]*Edge, error)
func (*RemoteEngine) GetEdgesByType ¶
func (r *RemoteEngine) GetEdgesByType(edgeType string) ([]*Edge, error)
func (*RemoteEngine) GetFirstNodeByLabel ¶
func (r *RemoteEngine) GetFirstNodeByLabel(label string) (*Node, error)
func (*RemoteEngine) GetInDegree ¶
func (r *RemoteEngine) GetInDegree(nodeID NodeID) int
func (*RemoteEngine) GetIncomingEdges ¶
func (r *RemoteEngine) GetIncomingEdges(nodeID NodeID) ([]*Edge, error)
func (*RemoteEngine) GetNodesByLabel ¶
func (r *RemoteEngine) GetNodesByLabel(label string) ([]*Node, error)
func (*RemoteEngine) GetOutDegree ¶
func (r *RemoteEngine) GetOutDegree(nodeID NodeID) int
func (*RemoteEngine) GetOutgoingEdges ¶
func (r *RemoteEngine) GetOutgoingEdges(nodeID NodeID) ([]*Edge, error)
func (*RemoteEngine) GetSchema ¶
func (r *RemoteEngine) GetSchema() *SchemaManager
func (*RemoteEngine) NodeCount ¶
func (r *RemoteEngine) NodeCount() (int64, error)
func (*RemoteEngine) QueryCypher ¶
func (r *RemoteEngine) QueryCypher(ctx context.Context, statement string, params map[string]interface{}) ([]string, [][]interface{}, error)
QueryCypher executes an arbitrary Cypher query against the remote instance and returns column names and raw rows. This is used by the fabric layer to dispatch fragment queries to remote constituents without going through the node/edge Engine abstraction.
The Bolt transport returns columns from the result record keys. The HTTP transport returns columns from the tx API response.
func (*RemoteEngine) UpdateEdge ¶
func (r *RemoteEngine) UpdateEdge(edge *Edge) error
func (*RemoteEngine) UpdateNode ¶
func (r *RemoteEngine) UpdateNode(node *Node) error
type RemoteEngineConfig ¶
type RemoteEngineConfig struct {
// URI is the remote NornicDB endpoint (bolt:// or http:// scheme).
URI string
// Database is the target database name on the remote instance.
Database string
// AuthToken is the caller's authorization header value (e.g. "Bearer <token>"),
// used for OIDC credential forwarding.
AuthToken string
// User and Password are used for explicit basic auth (user_password auth mode).
User string
Password string
// HTTPClient is an optional custom HTTP client, used only when transport is HTTP.
HTTPClient *http.Client
}
RemoteEngineConfig configures a remote storage engine.
The URI field determines the transport protocol:
- bolt://, bolt+s://, bolt+ssc://, neo4j://, neo4j+s://, neo4j+ssc:// → Bolt transport (preferred)
- http://, https:// → HTTP tx API transport (fallback)
type ReplayError ¶
type ReplayError struct {
Sequence uint64
Operation OperationType
Error error
}
ReplayError captures details about a failed replay entry.
type ReplayResult ¶
type ReplayResult struct {
Applied int // Successfully applied entries
Skipped int // Expected skips (duplicates, checkpoints)
Failed int // Unexpected failures
Errors []ReplayError // Detailed error information
}
ReplayResult tracks the outcome of WAL replay for observability.
func ReplayWALEntries ¶
func ReplayWALEntries(engine Engine, entries []WALEntry) ReplayResult
ReplayWALEntries replays multiple entries and tracks results. Expected errors (duplicates, checkpoints) are counted as skipped. Unexpected errors (corruption, constraint violations) are counted as failed.
func (ReplayResult) HasCriticalErrors ¶
func (r ReplayResult) HasCriticalErrors() bool
HasCriticalErrors returns true if there were unexpected failures.
func (ReplayResult) Summary ¶
func (r ReplayResult) Summary() string
Summary returns a human-readable summary of replay results.
type RetentionPolicy ¶
RetentionPolicy controls default MVCC historical retention for a storage engine. MaxVersionsPerKey applies to closed historical versions; the current head is always preserved. TTL optionally protects versions newer than now-TTL from pruning.
type SchemaCompositeIndexDef ¶
type SchemaDefinition ¶
type SchemaDefinition struct {
Version int `json:"version"`
Constraints []Constraint `json:"constraints,omitempty"`
ConstraintContracts []ConstraintContract `json:"constraint_contracts,omitempty"`
PropertyTypeConstraints []PropertyTypeConstraint `json:"property_type_constraints,omitempty"`
PropertyIndexes []SchemaPropertyIndexDef `json:"property_indexes,omitempty"`
CompositeIndexes []SchemaCompositeIndexDef `json:"composite_indexes,omitempty"`
FulltextIndexes []FulltextIndex `json:"fulltext_indexes,omitempty"`
VectorIndexes []VectorIndex `json:"vector_indexes,omitempty"`
RangeIndexes []SchemaRangeIndexDef `json:"range_indexes,omitempty"`
}
SchemaDefinition is the persisted representation of NornicDB schema rules.
It stores schema *definitions only* (constraints and index definitions), not derived/indexed data structures (like unique value maps), which are rebuilt from stored nodes/edges on startup.
This mirrors Neo4j’s model:
- schema rules are durable metadata
- index contents can be rebuilt if needed
type SchemaManager ¶
type SchemaManager struct {
// contains filtered or unexported fields
}
SchemaManager manages database schema including constraints and indexes.
func NewSchemaManager ¶
func NewSchemaManager() *SchemaManager
NewSchemaManager creates a new schema manager with empty constraint and index collections.
The schema manager provides thread-safe management of database schema including:
- Unique constraints (enforce uniqueness on properties)
- Node key constraints (composite unique keys)
- Existence constraints (require properties to exist)
- Property indexes (speed up lookups)
- Vector indexes (semantic similarity search)
- Full-text indexes (text search with scoring)
Returns:
- *SchemaManager ready for use
Example 1 - Basic Usage:
schema := storage.NewSchemaManager()
// Add unique constraint
constraint := &storage.UniqueConstraint{
Name: "unique_user_email",
Label: "User",
Property: "email",
}
schema.AddUniqueConstraint(constraint)
// Validate before creating node
err := schema.ValidateUnique("User", "email", "alice@example.com", "")
if err != nil {
log.Fatal("Email already exists!")
}
Example 2 - Multiple Constraints:
schema := storage.NewSchemaManager()
// Email must be unique
schema.AddUniqueConstraint(&storage.UniqueConstraint{
Name: "unique_email", Label: "User", Property: "email",
})
// Username must be unique
schema.AddUniqueConstraint(&storage.UniqueConstraint{
Name: "unique_username", Label: "User", Property: "username",
})
// All users must have email property
schema.AddConstraint(storage.Constraint{
Name: "user_must_have_email",
Type: storage.ConstraintExists,
Label: "User",
Properties: []string{"email"},
})
Example 3 - With Indexes for Performance:
schema := storage.NewSchemaManager()
// Index for fast lookups
schema.AddPropertyIndex(&storage.PropertyIndex{
Name: "idx_user_email",
Label: "User",
Properties: []string{"email"},
})
// Vector index for semantic search
schema.AddVectorIndex(&storage.VectorIndex{
Name: "doc_embeddings",
Label: "Document",
Property: "embedding",
Dimensions: 1024,
})
ELI12:
Think of a SchemaManager like a rule book for your database:
- "Every person must have a unique name" (unique constraint)
- "You can't create a person without an age" (existence constraint)
- "Make a quick-lookup list for emails" (index)
Before you add data, the SchemaManager checks: "Does this follow the rules?" If yes, data goes in. If no, you get an error. It keeps your database clean!
Thread Safety:
All methods are thread-safe for concurrent access.
func (*SchemaManager) AddCompositeIndex ¶
func (sm *SchemaManager) AddCompositeIndex(name, label string, properties []string) error
AddCompositeIndex creates a composite index on multiple properties. Composite indexes enable efficient queries that filter on multiple properties.
Example usage:
sm.AddCompositeIndex("user_location_idx", "User", []string{"country", "city", "zipcode"})
This enables efficient queries like:
- WHERE country = 'US' AND city = 'NYC' AND zipcode = '10001' (full match)
- WHERE country = 'US' AND city = 'NYC' (prefix match)
- WHERE country = 'US' (prefix match, uses first property only)
func (*SchemaManager) AddConstraint ¶
func (sm *SchemaManager) AddConstraint(c Constraint, ifNotExists ...bool) error
AddConstraint adds a constraint to the schema. Stores constraint in both the constraints map and uniqueConstraints (for backward compatibility).
Conflict rules (matching Neo4j behavior):
- Same name, already exists with identical schema+type: error, unless ifNotExists (then no-op)
- Same name, different schema or type: error
- Different name, same schema + same type: error (duplicate schema), unless ifNotExists
- Uniqueness vs relationship key on same schema: error (conflicting)
Pass ifNotExists=true when the DDL includes IF NOT EXISTS; duplicate-schema is then a no-op.
func (*SchemaManager) AddConstraintContractBundle ¶
func (sm *SchemaManager) AddConstraintContractBundle(contract ConstraintContract, compiledConstraints []Constraint, compiledTypes []PropertyTypeConstraint, ifNotExists bool) error
func (*SchemaManager) AddFulltextIndex ¶
func (sm *SchemaManager) AddFulltextIndex(name string, labels, properties []string) error
AddFulltextIndex adds a full-text index.
func (*SchemaManager) AddPropertyIndex ¶
func (sm *SchemaManager) AddPropertyIndex(name, label string, properties []string) error
AddPropertyIndex adds a property index.
func (*SchemaManager) AddPropertyTypeConstraint ¶
func (sm *SchemaManager) AddPropertyTypeConstraint(name, label, property string, expectedType PropertyType, entityType ...ConstraintEntityType) error
AddPropertyTypeConstraint adds a property type constraint to the schema. The entityType parameter controls NODE vs RELATIONSHIP scoping.
func (*SchemaManager) AddPropertyTypeConstraintWithOptions ¶
func (sm *SchemaManager) AddPropertyTypeConstraintWithOptions(name, label, property string, expectedType PropertyType, opts PropertyTypeConstraintOptions) error
AddPropertyTypeConstraintWithOptions adds a property type constraint with full options.
func (*SchemaManager) AddRangeIndex ¶
func (sm *SchemaManager) AddRangeIndex(name, label, property string) error
AddRangeIndex adds a range index for a single property.
func (*SchemaManager) AddUniqueConstraint ¶
func (sm *SchemaManager) AddUniqueConstraint(name, label, property string, ifNotExists ...bool) error
AddUniqueConstraint adds a unique constraint. Stores in both uniqueConstraints (for value tracking) and constraints (for lookup by label). Pass ifNotExists=true for IF NOT EXISTS semantics (duplicate is no-op).
func (*SchemaManager) AddVectorIndex ¶
func (sm *SchemaManager) AddVectorIndex(name, label, property string, dimensions int, similarityFunc string) error
AddVectorIndex adds a vector index.
func (*SchemaManager) CheckUniqueConstraint ¶
func (sm *SchemaManager) CheckUniqueConstraint(label, property string, value interface{}, excludeNode NodeID) error
CheckUniqueConstraint checks if a value violates a unique constraint. Returns error if constraint is violated.
func (*SchemaManager) DropConstraint ¶
func (sm *SchemaManager) DropConstraint(name string) error
DropConstraint removes a constraint (by name) from the schema. This supports both standard constraints and property type constraints.
func (*SchemaManager) DropIndex ¶
func (sm *SchemaManager) DropIndex(name string) error
DropIndex removes an index (by name) from the schema. It searches across all index types: property, composite, fulltext, vector, and range.
func (*SchemaManager) ExportDefinition ¶
func (sm *SchemaManager) ExportDefinition() *SchemaDefinition
ExportDefinition returns a stable, persisted representation of the schema. The returned object is safe to serialize and does not include runtime caches.
func (*SchemaManager) GetAllConstraintContracts ¶
func (sm *SchemaManager) GetAllConstraintContracts() []ConstraintContract
func (*SchemaManager) GetAllConstraints ¶
func (sm *SchemaManager) GetAllConstraints() []Constraint
GetAllConstraints returns all constraints in the schema, regardless of label. This is used by db.constraints() procedure to list all constraints.
func (*SchemaManager) GetAllPropertyTypeConstraints ¶
func (sm *SchemaManager) GetAllPropertyTypeConstraints() []PropertyTypeConstraint
GetAllPropertyTypeConstraints returns all property type constraints.
func (*SchemaManager) GetCompositeIndex ¶
func (sm *SchemaManager) GetCompositeIndex(name string) (*CompositeIndex, bool)
GetCompositeIndex returns a composite index by name.
func (*SchemaManager) GetCompositeIndexesForLabel ¶
func (sm *SchemaManager) GetCompositeIndexesForLabel(label string) []*CompositeIndex
GetCompositeIndexForLabel returns all composite indexes for a label.
func (*SchemaManager) GetConstraintContractsForTarget ¶
func (sm *SchemaManager) GetConstraintContractsForTarget(entityType ConstraintEntityType, labelOrType string) []ConstraintContract
func (*SchemaManager) GetConstraints ¶
func (sm *SchemaManager) GetConstraints() []UniqueConstraint
GetConstraints returns all unique constraints.
func (*SchemaManager) GetConstraintsForLabels ¶
func (sm *SchemaManager) GetConstraintsForLabels(labels []string) []Constraint
GetConstraintsForLabels returns all constraints for given labels. Returns constraints from the constraints map, preserving their original types.
func (*SchemaManager) GetFulltextIndex ¶
func (sm *SchemaManager) GetFulltextIndex(name string) (*FulltextIndex, bool)
GetFulltextIndex returns a fulltext index by name.
func (*SchemaManager) GetIndexStats ¶
func (sm *SchemaManager) GetIndexStats() []IndexStats
GetIndexStats returns statistics for all indexes.
func (*SchemaManager) GetIndexes ¶
func (sm *SchemaManager) GetIndexes() []interface{}
GetIndexes returns all indexes.
func (*SchemaManager) GetPropertyIndex ¶
func (sm *SchemaManager) GetPropertyIndex(label, property string) (*PropertyIndex, bool)
GetPropertyIndex returns a property index by label and property.
func (*SchemaManager) GetPropertyTypeConstraintsForLabels ¶
func (sm *SchemaManager) GetPropertyTypeConstraintsForLabels(labels []string) []PropertyTypeConstraint
GetPropertyTypeConstraintsForLabels returns type constraints for the given labels.
func (*SchemaManager) GetRangeIndex ¶
func (sm *SchemaManager) GetRangeIndex(name string) (*RangeIndex, bool)
GetRangeIndex returns a range index by name.
func (*SchemaManager) GetVectorIndex ¶
func (sm *SchemaManager) GetVectorIndex(name string) (*VectorIndex, bool)
GetVectorIndex returns a vector index by name.
func (*SchemaManager) LookupUniqueConstraintValue ¶ added in v1.0.43
func (sm *SchemaManager) LookupUniqueConstraintValue(label, property string, value interface{}) (NodeID, bool, bool)
LookupUniqueConstraintValue returns the node currently registered for a single-property uniqueness constraint value. The second return value reports whether the value is present, and the third reports whether the unique constraint exists.
func (*SchemaManager) PropertyIndexAllNonNil ¶
func (sm *SchemaManager) PropertyIndexAllNonNil(label, property string, descending bool) []NodeID
PropertyIndexAllNonNil returns all node IDs from the property index in key order, excluding nil keys.
func (*SchemaManager) PropertyIndexDelete ¶
func (sm *SchemaManager) PropertyIndexDelete(label, property string, nodeID NodeID, value interface{}) error
PropertyIndexDelete removes a node from a property index.
func (*SchemaManager) PropertyIndexInsert ¶
func (sm *SchemaManager) PropertyIndexInsert(label, property string, nodeID NodeID, value interface{}) error
PropertyIndexInsert adds a node to a property index.
func (*SchemaManager) PropertyIndexLookup ¶
func (sm *SchemaManager) PropertyIndexLookup(label, property string, value interface{}) []NodeID
PropertyIndexLookup looks up node IDs by property value using an index. Returns nil if no index exists for the label/property.
func (*SchemaManager) PropertyIndexTopK ¶
func (sm *SchemaManager) PropertyIndexTopK(label, property string, limit int, descending bool) []NodeID
PropertyIndexTopK returns up to limit node IDs from a property index ordered by indexed property value. Nil keys are skipped.
func (*SchemaManager) RangeIndexDelete ¶
func (sm *SchemaManager) RangeIndexDelete(name string, nodeID NodeID) error
RangeIndexDelete removes a value from a range index.
func (*SchemaManager) RangeIndexInsert ¶
func (sm *SchemaManager) RangeIndexInsert(name string, nodeID NodeID, value interface{}) error
RangeIndexInsert adds a value to a range index.
func (*SchemaManager) RangeQuery ¶
func (sm *SchemaManager) RangeQuery(name string, minVal, maxVal interface{}, includeMin, includeMax bool) ([]NodeID, error)
RangeQuery performs a range query on a range index. Returns node IDs where value is in range [minVal, maxVal]. Pass nil for minVal or maxVal to indicate unbounded.
func (*SchemaManager) RegisterUniqueValue ¶
func (sm *SchemaManager) RegisterUniqueValue(label, property string, value interface{}, nodeID NodeID)
RegisterUniqueValue registers a value for a unique constraint.
func (*SchemaManager) ReplaceFromDefinition ¶
func (sm *SchemaManager) ReplaceFromDefinition(def *SchemaDefinition) error
ReplaceFromDefinition replaces the in-memory schema contents with the given definition.
This does NOT persist anything, and it intentionally discards runtime caches (unique value maps, index maps, etc.). Those must be rebuilt from data.
func (*SchemaManager) SetPersister ¶
func (sm *SchemaManager) SetPersister(persist func(def *SchemaDefinition) error)
SetPersister sets an optional persistence hook for schema changes. When set, schema mutations will attempt to persist the updated schema definition and will roll back the in-memory change if persistence fails.
func (*SchemaManager) UnregisterUniqueValue ¶
func (sm *SchemaManager) UnregisterUniqueValue(label, property string, value interface{})
UnregisterUniqueValue removes a value from a unique constraint.
type SchemaPropertyIndexDef ¶
type SchemaRangeIndexDef ¶
type SerializerMigrationOptions ¶
SerializerMigrationOptions controls migration behavior.
type SerializerMigrationStats ¶
type SerializerMigrationStats struct {
DataDir string
Source StorageSerializer
Target StorageSerializer
HasData bool
NodesConverted int
EdgesConverted int
EmbeddingsConverted int
SkippedExisting int
TotalScanned int
}
SerializerMigrationStats reports conversion results.
func MigrateBadgerSerializer ¶
func MigrateBadgerSerializer(dataDir string, target StorageSerializer, opts SerializerMigrationOptions) (SerializerMigrationStats, error)
MigrateBadgerSerializer converts stored data to the target serializer in place. This expects the database to be offline (no running server).
func MigrateBadgerSerializerWithDB ¶
func MigrateBadgerSerializerWithDB(db *badger.DB, dataDir string, target StorageSerializer, opts SerializerMigrationOptions) (SerializerMigrationStats, error)
MigrateBadgerSerializerWithDB converts stored data to the target serializer using an existing DB handle. This is primarily used for tests and offline tooling.
type SignalType ¶
type SignalType string
SignalType describes how an edge was detected/created.
const ( SignalSimilarity SignalType = "similarity" // Semantic similarity SignalCoAccess SignalType = "coaccess" // Co-access pattern SignalTopology SignalType = "topology" // Topological link prediction SignalLLMInference SignalType = "llm-infer" // LLM-based inference SignalManual SignalType = "manual" // User-created SignalTransitive SignalType = "transitive" // Transitive inference SignalTemporal SignalType = "temporal" // Temporal proximity )
type Snapshot ¶
type Snapshot struct {
Sequence uint64 `json:"sequence"`
Timestamp time.Time `json:"timestamp"`
Nodes []*Node `json:"nodes"`
Edges []*Edge `json:"edges"`
Version string `json:"version"`
}
Snapshot represents a point-in-time snapshot of the database.
func LoadSnapshot ¶
LoadSnapshot reads a snapshot from disk.
type SnapshotReaderInfo ¶
type SnapshotReaderInfo struct {
ReaderID string
SnapshotVersion MVCCVersion
StartTime time.Time
Namespace string
}
SnapshotReaderInfo describes an active MVCC snapshot reader.
type SnapshotReaderRegistry ¶
type SnapshotReaderRegistry interface {
Register(info SnapshotReaderInfo) (string, func())
ActiveCount() int64
Snapshot() []SnapshotReaderInfo
}
SnapshotReaderRegistry exposes active snapshot-reader tracking.
type StorageEventNotifier ¶
type StorageEventNotifier interface {
// Node events
OnNodeCreated(callback NodeEventCallback)
OnNodeUpdated(callback NodeEventCallback)
OnNodeDeleted(callback NodeDeleteCallback)
// Edge events
OnEdgeCreated(callback EdgeEventCallback)
OnEdgeUpdated(callback EdgeEventCallback)
OnEdgeDeleted(callback EdgeDeleteCallback)
}
StorageEventNotifier is an optional interface that storage engines can implement to notify listeners of storage changes. This enables automatic synchronization between storage and external services (search indexes, embeddings, caches, etc.).
Events are fired AFTER the storage operation succeeds, ensuring consistency.
Example:
if notifier, ok := engine.(storage.StorageEventNotifier); ok {
notifier.OnNodeCreated(func(node *storage.Node) {
searchService.IndexNode(node)
})
notifier.OnNodeDeleted(func(nodeID storage.NodeID) {
searchService.RemoveNode(nodeID)
})
notifier.OnEdgeCreated(func(edge *storage.Edge) {
graphAnalyzer.UpdateMetrics(edge)
})
}
type StorageSerializer ¶
type StorageSerializer string
StorageSerializer selects the serialization format used for nodes/edges/embeddings.
const ( StorageSerializerGob StorageSerializer = "gob" StorageSerializerMsgpack StorageSerializer = "msgpack" )
func ParseStorageSerializer ¶
func ParseStorageSerializer(value string) (StorageSerializer, error)
ParseStorageSerializer normalizes and validates serializer input.
type StreamingEngine ¶
type StreamingEngine interface {
Engine
// StreamNodes iterates over all nodes without loading all into memory.
// The callback is called for each node. Return an error to stop iteration.
// Returns nil on successful completion, context.Canceled on cancellation.
StreamNodes(ctx context.Context, fn func(node *Node) error) error
// StreamEdges iterates over all edges without loading all into memory.
StreamEdges(ctx context.Context, fn func(edge *Edge) error) error
// StreamNodeChunks iterates over nodes in chunks for batch processing.
// More efficient than StreamNodes when processing in batches.
StreamNodeChunks(ctx context.Context, chunkSize int, fn func(nodes []*Node) error) error
}
StreamingEngine extends Engine with streaming iteration support. This is optional - engines that don't support streaming will use the default AllNodes/AllEdges with chunked processing.
type TemporalCurrentNodeEngine ¶
type TemporalCurrentNodeEngine interface {
IsCurrentTemporalNode(node *Node, asOf time.Time) (bool, error)
}
TemporalCurrentNodeEngine is an optional extension interface for deciding whether a temporal node represents the current/live version for indexing and query routing.
type TemporalLookupEngine ¶
type TemporalLookupEngine interface {
GetTemporalNodeAsOf(label, keyProp string, keyValue interface{}, validFromProp, validToProp string, asOf time.Time) (*Node, error)
}
TemporalLookupEngine is an optional extension interface for efficient temporal lookups on a namespaced engine view.
type TemporalMaintenanceEngine ¶
type TemporalMaintenanceEngine interface {
RebuildTemporalIndexes(ctx context.Context) error
PruneTemporalHistory(ctx context.Context, opts TemporalPruneOptions) (int64, error)
}
TemporalMaintenanceEngine is an optional extension interface for rebuilding and pruning temporal index state after upgrades, restores, or operator maintenance.
type TemporalPruneOptions ¶
type TemporalPruneOptions struct {
// MaxVersionsPerKey keeps at most this many closed historical versions per temporal key.
// Zero means unlimited.
MaxVersionsPerKey int
// MinRetentionAge protects versions newer than now-MinRetentionAge from pruning.
// Zero means no age-based protection.
MinRetentionAge time.Duration
}
TemporalPruneOptions controls pruning of older temporal versions.
type Transaction ¶
type Transaction = BadgerTransaction
Transaction is the public closure-facing transaction type used by DB.Update and DB.View.
type TransactionRecoveryResult ¶
type TransactionRecoveryResult struct {
SnapshotSeq uint64
Transactions map[string]*TransactionState
CommittedTransactions int
RolledBackTransactions int
AbortedTransactions int
FailedTransactions []string
UndoErrors []string
NonTxApplied int
NonTxErrors []string
}
TransactionRecoveryResult contains detailed statistics from transaction-aware recovery.
func (*TransactionRecoveryResult) HasErrors ¶
func (r *TransactionRecoveryResult) HasErrors() bool
HasErrors returns true if there were any errors during recovery.
func (*TransactionRecoveryResult) Summary ¶
func (r *TransactionRecoveryResult) Summary() string
Summary returns a human-readable summary of the recovery.
type TransactionState ¶
type TransactionState struct {
TxID string
Entries []WALEntry // All entries in this transaction (in order)
Started bool // True if we saw TxBegin
Done bool // True if we saw TxCommit or TxAbort
Aborted bool // True if explicitly aborted
}
TransactionState tracks the state of an in-progress transaction during recovery.
type TransactionStatus ¶
type TransactionStatus string
TransactionStatus represents the current state of a transaction.
const ( TxStatusActive TransactionStatus = "active" TxStatusCommitted TransactionStatus = "committed" TxStatusRolledBack TransactionStatus = "rolled_back" )
type TrustLevel ¶
type TrustLevel int
TrustLevel defines how trustworthy a node is for edge materialization.
const ( // TrustLevelDefault is the standard trust level TrustLevelDefault TrustLevel = 0 // TrustLevelLow requires higher confidence for edges TrustLevelLow TrustLevel = -1 // TrustLevelHigh allows lower confidence edges TrustLevelHigh TrustLevel = 1 // TrustLevelPinned edges never decay TrustLevelPinned TrustLevel = 2 )
func (TrustLevel) ConfidenceAdjustment ¶
func (t TrustLevel) ConfidenceAdjustment() float64
ConfidenceAdjustment returns the confidence threshold adjustment for this trust level. Positive values increase required confidence, negative values decrease it.
func (TrustLevel) String ¶
func (t TrustLevel) String() string
String returns the string representation of TrustLevel.
type UniqueConstraint ¶
type UniqueConstraint struct {
Name string
Label string
Property string
// contains filtered or unexported fields
}
UniqueConstraint represents a unique constraint on a label and property.
type VectorIndex ¶
type VectorIndex struct {
Name string
Label string
Property string
Dimensions int
SimilarityFunc string // "cosine", "euclidean", "dot"
}
VectorIndex represents a vector similarity index.
type WAL ¶
type WAL struct {
// contains filtered or unexported fields
}
WAL provides write-ahead logging for durability. Thread-safe for concurrent writes.
func (*WAL) Append ¶
func (w *WAL) Append(op OperationType, data interface{}) error
Append writes a new entry to the WAL using atomic write format.
The atomic format ensures partial writes are detectable:
[4 bytes: magic "WALE"] [1 byte: format version] [4 bytes: payload length] [N bytes: JSON-encoded entry] [4 bytes: CRC32 of payload]
If crash occurs mid-write:
- Missing magic: entry doesn't exist
- Missing/truncated payload: length mismatch detected
- Missing checksum: CRC verification fails
func (*WAL) AppendReturningSeq ¶
func (w *WAL) AppendReturningSeq(op OperationType, data interface{}) (uint64, error)
AppendReturningSeq writes a new entry to the WAL and returns its sequence number.
func (*WAL) AppendTxAbort ¶
AppendTxAbort writes a transaction-abort marker to the WAL.
func (*WAL) AppendTxBegin ¶
AppendTxBegin writes a transaction-begin marker to the WAL.
func (*WAL) AppendTxCommit ¶
AppendTxCommit writes a transaction-commit marker to the WAL.
func (*WAL) AppendWithDatabase ¶
func (w *WAL) AppendWithDatabase(op OperationType, data interface{}, database string) error
AppendWithDatabase writes a new entry to the WAL with database/namespace information.
func (*WAL) AppendWithDatabaseReturningSeq ¶
func (w *WAL) AppendWithDatabaseReturningSeq(op OperationType, data interface{}, database string) (uint64, error)
AppendWithDatabaseReturningSeq writes a new entry to the WAL with database/namespace information and returns the assigned sequence number.
func (*WAL) ApplyRetention ¶
ApplyRetention deletes sealed segments that are safe to drop after a snapshot. Segments are only deleted if their last sequence is <= snapshotSeq.
func (*WAL) Checkpoint ¶
Checkpoint creates a checkpoint marker for snapshot boundaries.
func (*WAL) CreateSnapshot ¶
CreateSnapshot creates a point-in-time snapshot from the engine.
func (*WAL) IsDegraded ¶
IsDegraded reports whether this WAL has detected corruption and performed best-effort recovery actions. When true, callers should consider the durability state degraded and surface it in health endpoints.
func (*WAL) LastCorruptionDiagnostics ¶
func (w *WAL) LastCorruptionDiagnostics() *CorruptionDiagnostics
LastCorruptionDiagnostics returns the last corruption diagnostics captured by this WAL. Returns nil if no corruption has been observed.
func (*WAL) NewBatchWithTxID ¶
func (w *WAL) NewBatchWithTxID(txID string) *BatchWriter
NewBatchWithTxID creates a new batch writer that stamps each entry with a TxID. The TxID will be embedded in WAL payloads (e.g., WALNodeData.TxID).
func (*WAL) TruncateAfterSnapshot ¶
TruncateAfterSnapshot truncates the WAL after a successful snapshot. This removes all entries up to and including the snapshot sequence number, preventing unbounded WAL growth. Call this after SaveSnapshot succeeds.
The process is crash-safe:
- Close current WAL file
- Read entries after snapshot sequence
- Write new WAL with only post-snapshot entries
- Atomically rename new WAL over old
- Reopen WAL for appends
If the system crashes during truncation:
- Old WAL remains intact (rename is atomic)
- Recovery will replay full WAL (safe, just slower)
- Retry truncation on next snapshot
Example:
snapshot, _ := wal.CreateSnapshot(engine) SaveSnapshot(snapshot, "data/snapshot.json") wal.TruncateAfterSnapshot(snapshot.Sequence) // Reclaim disk space
type WALBulkDeleteEdgesData ¶
type WALBulkDeleteEdgesData struct {
IDs []string `json:"ids"`
OldEdges []*Edge `json:"old_edges,omitempty"` // Complete edges being deleted (undo)
TxID string `json:"tx_id,omitempty"` // Transaction ID for grouping
}
WALBulkDeleteEdgesData holds bulk edge deletion data with undo support.
type WALBulkDeleteNodesData ¶
type WALBulkDeleteNodesData struct {
IDs []string `json:"ids"`
OldNodes []*Node `json:"old_nodes,omitempty"` // Complete nodes being deleted (undo)
TxID string `json:"tx_id,omitempty"` // Transaction ID for grouping
}
WALBulkDeleteNodesData holds bulk node deletion data with undo support.
type WALBulkEdgesData ¶
type WALBulkEdgesData struct {
Edges []*Edge `json:"edges"`
TxID string `json:"tx_id,omitempty"` // Transaction ID for grouping
}
WALBulkEdgesData holds bulk edge creation data.
type WALBulkNodesData ¶
type WALBulkNodesData struct {
Nodes []*Node `json:"nodes"`
TxID string `json:"tx_id,omitempty"` // Transaction ID for grouping
}
WALBulkNodesData holds bulk node creation data.
type WALConfig ¶
type WALConfig struct {
// Directory for WAL files
Dir string
// SyncMode controls when writes are synced to disk
// "immediate": fsync after each write (safest, slowest)
// "batch": fsync periodically (faster, some risk)
// "none": no fsync (fastest, data loss on crash)
SyncMode string
// BatchSyncInterval for "batch" sync mode
BatchSyncInterval time.Duration
// MaxFileSize triggers rotation when exceeded
MaxFileSize int64
// MaxEntries triggers rotation when exceeded
MaxEntries int64
// SnapshotInterval for automatic snapshots
SnapshotInterval time.Duration
// RetentionMaxSegments keeps at most N sealed segments (0 = unlimited).
RetentionMaxSegments int
// RetentionMaxAge keeps segments newer than this duration (0 = unlimited).
RetentionMaxAge time.Duration
// SnapshotRetentionMaxCount is the maximum number of snapshot files to keep in the
// snapshot directory (0 = keep all). Oldest snapshots are deleted after each new one.
// Recommended 3–5 so disk space stays bounded while keeping recovery options.
SnapshotRetentionMaxCount int
// SnapshotRetentionMaxAge is the maximum age of snapshot files to keep (0 = unlimited).
// Snapshots older than this are deleted even if under MaxCount.
SnapshotRetentionMaxAge time.Duration
// Logger receives WAL diagnostics events (optional).
// If nil, a default stdlib-backed logger is used.
Logger WALLogger
// OnCorruption is called when WAL corruption diagnostics are produced (optional).
// This allows the server layer to surface "WAL degraded" health state without
// parsing logs. The callback MUST be fast and non-blocking.
OnCorruption func(diag *CorruptionDiagnostics, cause error)
}
WALConfig configures WAL behavior.
func DefaultWALConfig ¶
func DefaultWALConfig() *WALConfig
DefaultWALConfig returns sensible defaults.
type WALDeleteData ¶
type WALDeleteData struct {
ID string `json:"id"`
OldNode *Node `json:"old_node,omitempty"` // Complete node being deleted (undo)
OldEdge *Edge `json:"old_edge,omitempty"` // Complete edge being deleted (undo)
TxID string `json:"tx_id,omitempty"` // Transaction ID for grouping
}
WALDeleteData holds delete operation data with undo support. For proper undo, we store the complete entity being deleted.
type WALEdgeData ¶
type WALEdgeData struct {
Edge *Edge `json:"edge"` // New state (redo)
OldEdge *Edge `json:"old_edge,omitempty"` // Previous state (undo) - for updates
TxID string `json:"tx_id,omitempty"` // Transaction ID for grouping
}
WALEdgeData holds edge data for WAL entries with optional undo support. For update/delete operations, OldEdge contains the "before image" for rollback.
type WALEngine ¶
type WALEngine struct {
// contains filtered or unexported fields
}
WALEngine wraps a storage engine with write-ahead logging.
All mutating operations are appended to the WAL before they are applied to the wrapped engine. This provides crash recovery via snapshot + replay while keeping the underlying Engine implementations simple and fast.
Design notes:
- Database routing: WALEngine supports multi-database usage by recording the database/namespace in each WAL entry and by normalizing IDs when needed.
- Embedding updates: embedding-only updates are logged using OpUpdateEmbedding which is safe to skip during recovery because embeddings are regenerable.
- Auto-compaction: optional periodic snapshots + WAL truncation to prevent unbounded WAL growth.
func NewWALEngine ¶
NewWALEngine creates a WAL-backed storage engine.
func (*WALEngine) AddToPendingEmbeddings ¶
AddToPendingEmbeddings delegates to underlying engine if it supports it.
func (*WALEngine) BatchGetNodes ¶
BatchGetNodes delegates to underlying engine.
func (*WALEngine) BulkCreateEdges ¶
BulkCreateEdges logs then executes bulk edge creation.
func (*WALEngine) BulkCreateNodes ¶
BulkCreateNodes logs then executes bulk node creation.
func (*WALEngine) BulkDeleteEdges ¶
BulkDeleteEdges logs then executes bulk edge deletion.
func (*WALEngine) BulkDeleteNodes ¶
BulkDeleteNodes logs then executes bulk node deletion.
func (*WALEngine) CreateEdge ¶
CreateEdge logs then executes edge creation.
func (*WALEngine) CreateNode ¶
CreateNode logs then executes node creation.
func (*WALEngine) DeleteByPrefix ¶
func (w *WALEngine) DeleteByPrefix(prefix string) (nodesDeleted int64, edgesDeleted int64, err error)
DeleteByPrefix delegates to the underlying engine.
func (*WALEngine) DeleteEdge ¶
DeleteEdge logs then executes edge deletion.
func (*WALEngine) DeleteNode ¶
DeleteNode logs then executes node deletion.
func (*WALEngine) DisableAutoCompaction ¶
func (w *WALEngine) DisableAutoCompaction()
DisableAutoCompaction stops automatic snapshot creation and WAL truncation. Waits for the auto-compaction goroutine to finish before returning to prevent race conditions when the engine is closed.
func (*WALEngine) EdgeCountByPrefix ¶
func (*WALEngine) EnableAutoCompaction ¶
EnableAutoCompaction starts automatic snapshot creation and WAL truncation. Snapshots are created at the configured SnapshotInterval, and the WAL is truncated after each successful snapshot to prevent unbounded growth.
Snapshots are saved to snapshotDir/snapshot-<timestamp>.json
This solves the "WAL grows forever" problem by automatically removing old entries that are already captured in snapshots.
Example:
walEngine.EnableAutoCompaction("data/snapshots")
// WAL will now be automatically truncated every SnapshotInterval
func (*WALEngine) FindNodeNeedingEmbedding ¶
FindNodeNeedingEmbedding delegates to underlying engine if it supports it.
func (*WALEngine) ForEachNodeIDByLabel ¶
ForEachNodeIDByLabel delegates label-to-nodeID iteration to the underlying engine when available. This keeps LIMIT + label paths fast without forcing full node materialization.
func (*WALEngine) GetAllNodes ¶
GetAllNodes delegates to underlying engine.
func (*WALEngine) GetEdgeBetween ¶
GetEdgeBetween delegates to underlying engine.
func (*WALEngine) GetEdgeCurrentHead ¶
GetEdgeCurrentHead delegates edge head lookup when supported.
func (*WALEngine) GetEdgeLatestEffective ¶
GetEdgeLatestEffective delegates MVCC latest-effective edge reads to the wrapped engine when supported.
func (*WALEngine) GetEdgeLatestVisible ¶
GetEdgeLatestVisible delegates latest-visible edge reads when supported.
func (*WALEngine) GetEdgeVisibleAt ¶
func (w *WALEngine) GetEdgeVisibleAt(id EdgeID, version MVCCVersion) (*Edge, error)
GetEdgeVisibleAt delegates snapshot-visible edge reads when supported.
func (*WALEngine) GetEdgesBetween ¶
GetEdgesBetween delegates to underlying engine.
func (*WALEngine) GetEdgesBetweenVisibleAt ¶
func (w *WALEngine) GetEdgesBetweenVisibleAt(startID, endID NodeID, version MVCCVersion) ([]*Edge, error)
GetEdgesBetweenVisibleAt delegates snapshot-visible topology queries when supported.
func (*WALEngine) GetEdgesByType ¶
GetEdgesByType delegates to underlying engine.
func (*WALEngine) GetEdgesByTypeVisibleAt ¶
func (w *WALEngine) GetEdgesByTypeVisibleAt(edgeType string, version MVCCVersion) ([]*Edge, error)
GetEdgesByTypeVisibleAt delegates snapshot-visible edge-type queries when supported.
func (*WALEngine) GetFirstNodeByLabel ¶
GetFirstNodeByLabel delegates to underlying engine.
func (*WALEngine) GetInDegree ¶
GetInDegree delegates to underlying engine.
func (*WALEngine) GetIncomingEdges ¶
GetIncomingEdges delegates to underlying engine.
func (*WALEngine) GetInnerEngine ¶
GetInnerEngine returns the wrapped storage engine.
func (*WALEngine) GetNodeCurrentHead ¶
GetNodeCurrentHead delegates node head lookup when supported.
func (*WALEngine) GetNodeLatestEffective ¶
GetNodeLatestEffective delegates MVCC latest-effective reads to the wrapped engine when supported.
func (*WALEngine) GetNodeLatestVisible ¶
GetNodeLatestVisible delegates latest-visible node reads when supported.
func (*WALEngine) GetNodeVisibleAt ¶
func (w *WALEngine) GetNodeVisibleAt(id NodeID, version MVCCVersion) (*Node, error)
GetNodeVisibleAt delegates snapshot-visible node reads when supported.
func (*WALEngine) GetNodesByLabel ¶
GetNodesByLabel delegates to underlying engine.
func (*WALEngine) GetNodesByLabelVisibleAt ¶
func (w *WALEngine) GetNodesByLabelVisibleAt(label string, version MVCCVersion) ([]*Node, error)
GetNodesByLabelVisibleAt delegates snapshot-visible label queries when supported.
func (*WALEngine) GetOutDegree ¶
GetOutDegree delegates to underlying engine.
func (*WALEngine) GetOutgoingEdges ¶
GetOutgoingEdges delegates to underlying engine.
func (*WALEngine) GetSchema ¶
func (w *WALEngine) GetSchema() *SchemaManager
GetSchema delegates to underlying engine.
func (*WALEngine) GetSchemaForNamespace ¶
func (w *WALEngine) GetSchemaForNamespace(namespace string) *SchemaManager
GetSchemaForNamespace implements NamespaceSchemaProvider when the underlying engine supports it.
func (*WALEngine) GetSnapshotStats ¶
GetSnapshotStats returns statistics about automatic snapshots.
func (*WALEngine) IsCurrentTemporalNode ¶
IsCurrentTemporalNode delegates current-version checks to the wrapped engine when supported.
func (*WALEngine) IterateNodes ¶
IterateNodes delegates to underlying engine if it supports streaming iteration.
func (*WALEngine) LastWriteTime ¶
LastWriteTime returns the last WAL entry timestamp (best-effort).
func (*WALEngine) LifecycleStatus ¶
LifecycleStatus delegates lifecycle status when supported.
func (*WALEngine) ListNamespaces ¶
ListNamespaces returns known namespaces from the wrapped engine, if supported.
func (*WALEngine) MarkNodeEmbedded ¶
MarkNodeEmbedded delegates to underlying engine if it supports it.
func (*WALEngine) NodeCountByPrefix ¶
func (*WALEngine) PauseLifecycle ¶
func (w *WALEngine) PauseLifecycle()
PauseLifecycle delegates lifecycle pause when supported.
func (*WALEngine) PendingEmbeddingsCount ¶
PendingEmbeddingsCount delegates to underlying engine if it supports it.
func (*WALEngine) PruneMVCCVersions ¶
PruneMVCCVersions delegates MVCC pruning to the wrapped engine when supported.
func (*WALEngine) PruneTemporalHistory ¶
func (w *WALEngine) PruneTemporalHistory(ctx context.Context, opts TemporalPruneOptions) (int64, error)
PruneTemporalHistory delegates temporal pruning to the wrapped engine when supported.
func (*WALEngine) RebuildMVCCHeads ¶
RebuildMVCCHeads delegates MVCC head rebuild to the wrapped engine when supported.
func (*WALEngine) RebuildTemporalIndexes ¶
RebuildTemporalIndexes delegates temporal index rebuild to the wrapped engine when supported.
func (*WALEngine) RefreshPendingEmbeddingsIndex ¶
RefreshPendingEmbeddingsIndex delegates to underlying engine if it supports it.
func (*WALEngine) RegisterSnapshotReader ¶
func (w *WALEngine) RegisterSnapshotReader(info SnapshotReaderInfo) func()
RegisterSnapshotReader delegates snapshot-reader registration when supported.
func (*WALEngine) ResumeLifecycle ¶
func (w *WALEngine) ResumeLifecycle()
ResumeLifecycle delegates lifecycle resume when supported.
func (*WALEngine) SetLifecycleSchedule ¶
SetLifecycleSchedule delegates lifecycle cadence updates when supported.
func (*WALEngine) StreamEdges ¶
StreamEdges implements StreamingEngine.StreamEdges by delegating to the underlying engine.
func (*WALEngine) StreamNodeChunks ¶
func (w *WALEngine) StreamNodeChunks(ctx context.Context, chunkSize int, fn func(nodes []*Node) error) error
StreamNodeChunks implements StreamingEngine.StreamNodeChunks by delegating to the underlying engine.
func (*WALEngine) StreamNodes ¶
StreamNodes implements StreamingEngine.StreamNodes by delegating to the underlying engine.
func (*WALEngine) StreamNodesByPrefix ¶
func (w *WALEngine) StreamNodesByPrefix(ctx context.Context, prefix string, fn func(node *Node) error) error
StreamNodesByPrefix implements PrefixStreamingEngine by delegating prefix-scoped iteration to the wrapped engine when available. This preserves namespace-aware early termination behavior for MATCH ... LIMIT hot paths.
func (*WALEngine) TopLifecycleDebtKeys ¶
func (w *WALEngine) TopLifecycleDebtKeys(limit int) []MVCCLifecycleDebtKey
TopLifecycleDebtKeys delegates lifecycle debt inspection when supported.
func (*WALEngine) TriggerPruneNow ¶
TriggerPruneNow delegates lifecycle prune-now when supported.
func (*WALEngine) UpdateEdge ¶
UpdateEdge logs then executes edge update.
func (*WALEngine) UpdateNode ¶
UpdateNode logs then executes node update.
func (*WALEngine) UpdateNodeEmbedding ¶
UpdateNodeEmbedding logs then executes embedding-only node update. Uses OpUpdateEmbedding which is safe to skip during WAL recovery since embeddings can be regenerated automatically.
type WALEntry ¶
type WALEntry struct {
Sequence uint64 `json:"seq"` // Monotonically increasing sequence number
Timestamp time.Time `json:"ts"` // When the operation occurred
Operation OperationType `json:"op"` // Operation type (create_node, update_node, etc.)
Data []byte `json:"data"` // JSON-serialized operation data
Checksum uint32 `json:"checksum"` // CRC32 checksum for integrity
Database string `json:"database,omitempty"` // Database/namespace name (for multi-database support)
}
WALEntry represents a single write-ahead log entry. Each mutating operation is recorded as an entry before execution.
func FindWALEntriesByTxID ¶
FindWALEntriesByTxID scans entries and returns those with a matching tx_id. Use maxEntries <= 0 to return all matches.
func ReadWALEntries ¶
ReadWALEntries reads all entries from a WAL file. Supports both legacy JSON format and new atomic format with automatic detection. Returns error on corruption of critical entries (nodes, edges). Embedding updates are safe to skip as they can be regenerated.
func ReadWALEntriesAfter ¶
ReadWALEntriesAfter reads entries after a given sequence number.
func ReadWALEntriesAfterFromDir ¶
ReadWALEntriesAfterFromDir reads WAL entries after a given sequence across all segments.
func ReadWALEntriesFromDir ¶
ReadWALEntriesFromDir reads WAL entries across all segments and the active WAL file.
type WALIntegrityReport ¶
type WALIntegrityReport struct {
Healthy bool `json:"healthy"`
TotalEntries int `json:"total_entries"`
ValidEntries int `json:"valid_entries"`
CorruptedEntries int `json:"corrupted_entries"`
SkippedEmbeddings int `json:"skipped_embeddings"`
FirstSeq uint64 `json:"first_seq"`
LastSeq uint64 `json:"last_seq"`
FileSize int64 `json:"file_size"`
Format string `json:"format"` // "atomic" or "legacy"
Errors []string `json:"errors,omitempty"`
CorruptionDetails []CorruptionDiagnostics `json:"corruption_details,omitempty"`
}
WALIntegrityReport provides detailed integrity check results
func CheckWALIntegrity ¶
func CheckWALIntegrity(walPath string) (*WALIntegrityReport, error)
CheckWALIntegrity performs a comprehensive integrity check on a WAL file. This can be used for health checks, startup validation, or manual diagnostics. It does NOT modify the WAL - read-only operation.
type WALLogger ¶
WALLogger receives structured diagnostics emitted by WAL recovery / corruption handlers.
This is intentionally minimal to avoid coupling storage to a specific logging library. Implementations should treat fields as a stable machine-readable contract.
type WALManifest ¶
type WALManifest struct {
Version int `json:"version"`
Segments []WALSegment `json:"segments"`
}
WALManifest indexes all sealed WAL segments.
type WALNodeData ¶
type WALNodeData struct {
Node *Node `json:"node"` // New state (redo)
OldNode *Node `json:"old_node,omitempty"` // Previous state (undo) - for updates
TxID string `json:"tx_id,omitempty"` // Transaction ID for grouping
}
WALNodeData holds node data for WAL entries with optional undo support. For update/delete operations, OldNode contains the "before image" for rollback.
type WALSegment ¶
type WALSegment struct {
FirstSeq uint64 `json:"first_seq"`
LastSeq uint64 `json:"last_seq"`
SizeBytes int64 `json:"size_bytes"`
CreatedAt time.Time `json:"created_at"`
Path string `json:"path"`
}
WALSegment describes a sealed WAL segment stored on disk.
type WALStats ¶
type WALStats struct {
Sequence uint64
EntryCount int64
BytesWritten int64
TotalWrites int64
TotalSyncs int64
LastSyncTime time.Time
LastEntryTime time.Time
Closed bool
}
WALStats provides observability into WAL state.
type WALTxData ¶
type WALTxData struct {
TxID string `json:"tx_id"` // Transaction identifier
Metadata map[string]string `json:"metadata,omitempty"` // Optional transaction metadata
Reason string `json:"reason,omitempty"` // For abort: why was it aborted
OpCount int `json:"op_count,omitempty"` // For commit: number of operations
}
WALTxData holds transaction boundary data.
Source Files
¶
- async_engine.go
- async_engine_events.go
- badger.go
- badger_backup.go
- badger_bulk.go
- badger_cache.go
- badger_constraint_validation.go
- badger_edge_between_index.go
- badger_edges.go
- badger_helpers.go
- badger_iter_helpers.go
- badger_lifecycle.go
- badger_mvcc.go
- badger_namespaces.go
- badger_nodes.go
- badger_queries.go
- badger_schema.go
- badger_serialization.go
- badger_serializer_detection.go
- badger_stats.go
- badger_temporal_index.go
- badger_transaction.go
- badger_txn_helpers.go
- composite_engine.go
- composite_routing.go
- constraint_contracts.go
- constraint_validation.go
- db.go
- edge_meta.go
- label_index_lookup.go
- label_nodeid_lookup.go
- loader.go
- memory.go
- namespace_prefix.go
- namespaced.go
- node_config.go
- property_validation.go
- receipt.go
- remote_engine.go
- schema.go
- schema_persistence.go
- serializer_migration.go
- temporal_constraint.go
- transaction.go
- types.go
- wal.go
- wal_atomic_record.go
- wal_batch.go
- wal_degraded.go
- wal_diagnostics.go
- wal_engine.go
- wal_ids.go
- wal_jsonbuf.go
- wal_logger.go
- wal_repair.go
- wal_segments.go
- wal_sync_unix.go