Skip to content

Commit 152d111

Browse files
committed
feat: Implement Native Edge SQLite Graph Persistence (#9678)
1 parent 92d5c3e commit 152d111

5 files changed

Lines changed: 484 additions & 83 deletions

File tree

ai/graph/Database.mjs

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import ClassSystemUtil from '../../src/util/ClassSystem.mjs';
33
import Store from './Store.mjs';
44
import EdgeModel from './EdgeModel.mjs';
55
import NodeModel from './NodeModel.mjs';
6+
import StorageBase from './storage/Base.mjs';
67

78
/**
89
* The Database class serves as the core coordinator for the Native Edge Graph Database engine.
@@ -20,6 +21,10 @@ class Database extends Base {
2021
* @protected
2122
*/
2223
className: 'Neo.ai.graph.Database',
24+
/**
25+
* @member {Boolean} autoSave=true
26+
*/
27+
autoSave: true,
2328
/**
2429
* @member {Object|Neo.data.Store|null} edges_=null
2530
* @reactive
@@ -29,7 +34,13 @@ class Database extends Base {
2934
* @member {Object|Neo.data.Store|null} nodes_=null
3035
* @reactive
3136
*/
32-
nodes_: null
37+
nodes_: null,
38+
/**
39+
* Database persistence wrapper.
40+
* @member {Object|Neo.ai.graph.storage.Base|null} storage_=null
41+
* @reactive
42+
*/
43+
storage_: null
3344
}
3445

3546
/**
@@ -50,6 +61,18 @@ class Database extends Base {
5061
this.nodes.add(node);
5162
}
5263

64+
/**
65+
* Triggered after the storage config gets changed.
66+
* @param {Neo.ai.graph.storage.Base} value
67+
* @param {Neo.ai.graph.storage.Base} oldValue
68+
* @protected
69+
*/
70+
afterSetStorage(value, oldValue) {
71+
if (value) {
72+
value.load();
73+
}
74+
}
75+
5376
/**
5477
* Triggered before the edges config gets changed.
5578
* @param {Object|Neo.data.Store} value
@@ -59,11 +82,15 @@ class Database extends Base {
5982
*/
6083
beforeSetEdges(value, oldValue) {
6184
oldValue?.destroy();
62-
return ClassSystemUtil.beforeSetInstance(value, Store, {
85+
let store = ClassSystemUtil.beforeSetInstance(value, Store, {
6386
autoInitRecords: false,
6487
indices : [{ property: 'source' }, { property: 'target' }],
6588
model : EdgeModel
6689
});
90+
91+
store?.on('mutate', this.onEdgesMutate, this);
92+
93+
return store;
6794
}
6895

6996
/**
@@ -75,10 +102,32 @@ class Database extends Base {
75102
*/
76103
beforeSetNodes(value, oldValue) {
77104
oldValue?.destroy();
78-
return ClassSystemUtil.beforeSetInstance(value, Store, {
105+
let store = ClassSystemUtil.beforeSetInstance(value, Store, {
79106
autoInitRecords: false,
80107
model : NodeModel
81108
});
109+
110+
store?.on('mutate', this.onNodesMutate, this);
111+
112+
return store;
113+
}
114+
115+
/**
116+
* Triggered before the storage config gets changed.
117+
* @param {Object|Neo.ai.graph.storage.Base} value
118+
* @param {Object|Neo.ai.graph.storage.Base} oldValue
119+
* @returns {Neo.ai.graph.storage.Base}
120+
* @protected
121+
*/
122+
beforeSetStorage(value, oldValue) {
123+
if (value) {
124+
value = ClassSystemUtil.beforeSetInstance(value, StorageBase, {
125+
database: this
126+
});
127+
128+
value.database = this;
129+
}
130+
return value;
82131
}
83132

84133
/**
@@ -130,6 +179,36 @@ class Database extends Base {
130179
return nodes;
131180
}
132181

182+
/**
183+
* Triggered on edges Store mutations to sync storage
184+
* @param {Object} mutation
185+
*/
186+
onEdgesMutate(mutation) {
187+
if (this.autoSave && this.storage) {
188+
if (mutation.addedItems?.length > 0) {
189+
this.storage.addEdges(mutation.addedItems);
190+
}
191+
if (mutation.removedItems?.length > 0) {
192+
this.storage.removeEdges(mutation.removedItems);
193+
}
194+
}
195+
}
196+
197+
/**
198+
* Triggered on nodes Store mutations to sync storage
199+
* @param {Object} mutation
200+
*/
201+
onNodesMutate(mutation) {
202+
if (this.autoSave && this.storage) {
203+
if (mutation.addedItems?.length > 0) {
204+
this.storage.addNodes(mutation.addedItems);
205+
}
206+
if (mutation.removedItems?.length > 0) {
207+
this.storage.removeNodes(mutation.removedItems);
208+
}
209+
}
210+
}
211+
133212
/**
134213
* Removes an edge from the Native Edge Graph Database topology.
135214
* @param {String} edgeId

ai/graph/storage/Base.mjs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import NeoBase from '../../../src/core/Base.mjs';
2+
3+
/**
4+
* The abstract blueprint defining the core interaction envelope for Native Edge Persistor paradigms.
5+
* Storage engines extending this Base dynamically coordinate structural object ingestion, schema mapping,
6+
* and GraphRAG disk mutations synchronized instantly against memory traversals bounding the Neo MCP ecosystem.
7+
*
8+
* @class Neo.ai.graph.storage.Base
9+
* @extends Neo.core.Base
10+
*/
11+
class Base extends NeoBase {
12+
static config = {
13+
/**
14+
* @member {String} className='Neo.ai.graph.storage.Base'
15+
* @protected
16+
*/
17+
className: 'Neo.ai.graph.storage.Base',
18+
/**
19+
* Database instance reference
20+
* @member {Neo.ai.graph.Database|null} database=null
21+
*/
22+
database: null
23+
}
24+
25+
/**
26+
* Executes bulk topology injections mapping dynamic array structures into rigid Node.js endpoints.
27+
* @param {Object[]} nodes
28+
*/
29+
addNodes(nodes) {}
30+
31+
/**
32+
* Projects bidirectional edge matrices into structural persistence mechanisms preventing topological drift.
33+
* @param {Object[]} edges
34+
*/
35+
addEdges(edges) {}
36+
37+
/**
38+
* Purges specific Nodes array data natively resolving cascade anomalies internally at the driver stratum.
39+
* @param {Object[]} nodes
40+
*/
41+
removeNodes(nodes) {}
42+
43+
/**
44+
* Exterminates specified Edge links synchronously tracking physical memory un-mappings.
45+
* @param {Object[]} edges
46+
*/
47+
removeEdges(edges) {}
48+
49+
/**
50+
* Annihilates the local physical footprint entirely. Used exclusively to reset Graph matrices to zero state natively.
51+
*/
52+
clear() {}
53+
54+
/**
55+
* Orchestrates the restoration loop, ripping physical rows back out into standard `Neo.data.Record` collections internally.
56+
*/
57+
async load() {}
58+
}
59+
60+
export default Neo.setupClass(Base);

0 commit comments

Comments
 (0)