opencode-telos 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/code-intelligence/ast/cache.d.ts.map +1 -1
- package/dist/code-intelligence/ast/cache.js +8 -5
- package/dist/code-intelligence/ast/cache.js.map +1 -1
- package/dist/opencode/hooks.d.ts.map +1 -1
- package/dist/opencode/hooks.js +0 -6
- package/dist/opencode/hooks.js.map +1 -1
- package/dist/opencode/tools.d.ts.map +1 -1
- package/dist/opencode/tools.js +9 -8
- package/dist/opencode/tools.js.map +1 -1
- package/dist/sdd/cache/atomic.d.ts +3 -0
- package/dist/sdd/cache/atomic.d.ts.map +1 -0
- package/dist/sdd/cache/atomic.js +35 -0
- package/dist/sdd/cache/atomic.js.map +1 -0
- package/dist/sdd/cache/fingerprint.d.ts +18 -0
- package/dist/sdd/cache/fingerprint.d.ts.map +1 -0
- package/dist/sdd/cache/fingerprint.js +99 -0
- package/dist/sdd/cache/fingerprint.js.map +1 -0
- package/dist/sdd/cache/manager.d.ts +24 -10
- package/dist/sdd/cache/manager.d.ts.map +1 -1
- package/dist/sdd/cache/manager.js +184 -33
- package/dist/sdd/cache/manager.js.map +1 -1
- package/dist/sdd/cache/snapshot-store.d.ts +2 -1
- package/dist/sdd/cache/snapshot-store.d.ts.map +1 -1
- package/dist/sdd/cache/snapshot-store.js +13 -6
- package/dist/sdd/cache/snapshot-store.js.map +1 -1
- package/dist/sdd/persistence/sqlite.d.ts.map +1 -1
- package/dist/sdd/persistence/sqlite.js +66 -41
- package/dist/sdd/persistence/sqlite.js.map +1 -1
- package/dist/sdd/persistence/yaml.d.ts.map +1 -1
- package/dist/sdd/persistence/yaml.js +33 -25
- package/dist/sdd/persistence/yaml.js.map +1 -1
- package/package.json +1 -1
- package/src/code-intelligence/ast/cache.ts +11 -6
- package/src/opencode/hooks.ts +0 -5
- package/src/opencode/tools.ts +9 -8
- package/src/sdd/cache/atomic.ts +30 -0
- package/src/sdd/cache/fingerprint.ts +98 -0
- package/src/sdd/cache/manager.ts +182 -39
- package/src/sdd/cache/snapshot-store.ts +14 -7
- package/src/sdd/persistence/sqlite.ts +50 -24
- package/src/sdd/persistence/yaml.ts +40 -26
|
@@ -7,9 +7,11 @@
|
|
|
7
7
|
* Solução G: Snapshot persistente do grafo.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { existsSync, readFileSync,
|
|
10
|
+
import { existsSync, readFileSync, mkdirSync } from "fs"
|
|
11
11
|
import { join, dirname } from "path"
|
|
12
12
|
import type { KnowledgeGraph, AnyNode, Relationship } from "../domain/types.js"
|
|
13
|
+
import { atomicWriteFile } from "./atomic.js"
|
|
14
|
+
import { graphFingerprint } from "./fingerprint.js"
|
|
13
15
|
|
|
14
16
|
const SNAPSHOT_FILE = ".sdd/graph-cache.json"
|
|
15
17
|
const SNAPSHOT_MAX_AGE_MS = 60 * 60 * 1000 // 1 hour
|
|
@@ -31,6 +33,7 @@ interface SerializedSnapshot {
|
|
|
31
33
|
graph: KnowledgeGraph
|
|
32
34
|
indices: SerializedIndices
|
|
33
35
|
graphHash: string
|
|
36
|
+
sourceSignature: string
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
export class GraphSnapshotStore {
|
|
@@ -43,27 +46,28 @@ export class GraphSnapshotStore {
|
|
|
43
46
|
/**
|
|
44
47
|
* Save full graph + indices to disk.
|
|
45
48
|
*/
|
|
46
|
-
save(graph: KnowledgeGraph, graphHash: string): void {
|
|
49
|
+
save(graph: KnowledgeGraph, graphHash: string, sourceSignature: string): void {
|
|
47
50
|
const snapshot: SerializedSnapshot = {
|
|
48
|
-
version:
|
|
51
|
+
version: 3,
|
|
49
52
|
timestamp: Date.now(),
|
|
50
53
|
graph,
|
|
51
54
|
indices: this.serializeIndices(graph),
|
|
52
55
|
graphHash,
|
|
56
|
+
sourceSignature,
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
const path = join(this.projectDir, SNAPSHOT_FILE)
|
|
56
60
|
const dir = dirname(path)
|
|
57
61
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true })
|
|
58
62
|
|
|
59
|
-
|
|
63
|
+
atomicWriteFile(path, JSON.stringify(snapshot))
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
/**
|
|
63
67
|
* Load graph from snapshot if valid.
|
|
64
68
|
* Returns null if snapshot is missing, stale, or corrupted.
|
|
65
69
|
*/
|
|
66
|
-
load(): { graph: KnowledgeGraph; graphHash: string } | null {
|
|
70
|
+
load(): { graph: KnowledgeGraph; graphHash: string; sourceSignature: string } | null {
|
|
67
71
|
const path = join(this.projectDir, SNAPSHOT_FILE)
|
|
68
72
|
if (!existsSync(path)) return null
|
|
69
73
|
|
|
@@ -72,17 +76,19 @@ export class GraphSnapshotStore {
|
|
|
72
76
|
const snapshot: SerializedSnapshot = JSON.parse(raw)
|
|
73
77
|
|
|
74
78
|
// Validate version
|
|
75
|
-
if (snapshot.version !==
|
|
79
|
+
if (snapshot.version !== 3) return null
|
|
76
80
|
|
|
77
81
|
// Validate age
|
|
78
82
|
if (Date.now() - snapshot.timestamp > SNAPSHOT_MAX_AGE_MS) return null
|
|
79
83
|
|
|
80
84
|
// Validate graph structure
|
|
81
85
|
if (!snapshot.graph || !Array.isArray(snapshot.graph.nodes)) return null
|
|
86
|
+
if (!snapshot.sourceSignature || snapshot.graphHash !== graphFingerprint(snapshot.graph)) return null
|
|
82
87
|
|
|
83
88
|
return {
|
|
84
89
|
graph: snapshot.graph,
|
|
85
90
|
graphHash: snapshot.graphHash || "",
|
|
91
|
+
sourceSignature: snapshot.sourceSignature,
|
|
86
92
|
}
|
|
87
93
|
} catch {
|
|
88
94
|
return null
|
|
@@ -99,7 +105,8 @@ export class GraphSnapshotStore {
|
|
|
99
105
|
try {
|
|
100
106
|
const raw = readFileSync(path, "utf-8")
|
|
101
107
|
const snapshot: SerializedSnapshot = JSON.parse(raw)
|
|
102
|
-
return snapshot.version ===
|
|
108
|
+
return snapshot.version === 3 && Boolean(snapshot.sourceSignature) &&
|
|
109
|
+
(Date.now() - snapshot.timestamp) < SNAPSHOT_MAX_AGE_MS
|
|
103
110
|
} catch {
|
|
104
111
|
return false
|
|
105
112
|
}
|
|
@@ -10,6 +10,7 @@ import { GraphIndices } from "../graph/index.js"
|
|
|
10
10
|
import { ensureDir } from "./yaml.js"
|
|
11
11
|
import { join } from "path"
|
|
12
12
|
import { getCacheManager } from "../cache/manager.js"
|
|
13
|
+
import { fileSignature } from "../cache/fingerprint.js"
|
|
13
14
|
import type { GraphRepository } from "./repository.js"
|
|
14
15
|
import { recordLegitimateSave, validateGraphIntegrity } from "../graph/integrity-guard.js"
|
|
15
16
|
|
|
@@ -30,7 +31,7 @@ export class SqliteGraphRepository {
|
|
|
30
31
|
private baseDir: string
|
|
31
32
|
private dbPath: string
|
|
32
33
|
private db: any
|
|
33
|
-
private static cache: Map<string, { graph: KnowledgeGraph; indices: GraphIndices }> = new Map()
|
|
34
|
+
private static cache: Map<string, { graph: KnowledgeGraph; indices: GraphIndices; sourceSignature: string }> = new Map()
|
|
34
35
|
|
|
35
36
|
constructor(projectDir: string) {
|
|
36
37
|
this.baseDir = join(projectDir, ".sdd")
|
|
@@ -106,18 +107,34 @@ export class SqliteGraphRepository {
|
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
loadGraph(): KnowledgeGraph {
|
|
110
|
+
const cacheMgr = getCacheManager(require("path").dirname(this.baseDir))
|
|
111
|
+
const sourcePaths = [this.dbPath, `${this.dbPath}-wal`, `${this.dbPath}-shm`]
|
|
112
|
+
const currentSourceSignature = fileSignature(sourcePaths)
|
|
113
|
+
|
|
109
114
|
// Check cache with revalidation
|
|
110
115
|
const cached = SqliteGraphRepository.cache.get(this.dbPath)
|
|
111
116
|
if (cached) {
|
|
112
|
-
// Revalidation: check
|
|
113
|
-
|
|
114
|
-
if (!cacheMgr.checkCrossProcessInvalidation(this.dbPath)) {
|
|
117
|
+
// Revalidation: check content signature and durable invalidation events.
|
|
118
|
+
if (cached.sourceSignature === currentSourceSignature && !cacheMgr.checkCrossProcessInvalidation(this.dbPath)) {
|
|
115
119
|
return structuredClone(cached.graph)
|
|
116
120
|
}
|
|
117
121
|
// DB was modified externally, invalidate cache
|
|
118
122
|
SqliteGraphRepository.cache.delete(this.dbPath)
|
|
119
123
|
}
|
|
120
124
|
|
|
125
|
+
const snapshot = cacheMgr.loadGraphSnapshot()
|
|
126
|
+
if (snapshot?.sourceSignature === currentSourceSignature) {
|
|
127
|
+
const graph = snapshot.graph
|
|
128
|
+
const indices = GraphIndices.from(graph)
|
|
129
|
+
SqliteGraphRepository.cache.set(this.dbPath, {
|
|
130
|
+
graph: structuredClone(graph),
|
|
131
|
+
indices,
|
|
132
|
+
sourceSignature: currentSourceSignature,
|
|
133
|
+
})
|
|
134
|
+
cacheMgr.initGraphHash(graph.nodes.length, graph.relationships.length)
|
|
135
|
+
return structuredClone(graph)
|
|
136
|
+
}
|
|
137
|
+
|
|
121
138
|
const db = this.getDb()
|
|
122
139
|
|
|
123
140
|
// Load metadata
|
|
@@ -168,7 +185,7 @@ export class SqliteGraphRepository {
|
|
|
168
185
|
|
|
169
186
|
// Build indices and cache
|
|
170
187
|
const indices = GraphIndices.from(graph)
|
|
171
|
-
SqliteGraphRepository.cache.set(this.dbPath, { graph, indices })
|
|
188
|
+
SqliteGraphRepository.cache.set(this.dbPath, { graph, indices, sourceSignature: currentSourceSignature })
|
|
172
189
|
|
|
173
190
|
// Anti-bypass: check for out-of-band modifications
|
|
174
191
|
const projectDir = require("path").dirname(this.baseDir)
|
|
@@ -184,21 +201,26 @@ export class SqliteGraphRepository {
|
|
|
184
201
|
|
|
185
202
|
saveGraph(graph: KnowledgeGraph): void {
|
|
186
203
|
const db = this.getDb()
|
|
204
|
+
const cacheMgr = getCacheManager(require("path").dirname(this.baseDir))
|
|
205
|
+
if (!cacheMgr.acquireWriteLock()) {
|
|
206
|
+
throw new Error("Another process is writing the SDD graph; retry the mutation")
|
|
207
|
+
}
|
|
187
208
|
|
|
188
209
|
// Use transaction for atomicity
|
|
189
|
-
db.exec("BEGIN TRANSACTION")
|
|
190
|
-
|
|
191
210
|
try {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
211
|
+
db.exec("BEGIN TRANSACTION")
|
|
212
|
+
|
|
213
|
+
try {
|
|
214
|
+
// Differential persistence: update only changed rows and delete only
|
|
215
|
+
// rows that disappeared. This keeps SQLite useful for large graphs.
|
|
216
|
+
const upsertMeta = db.prepare(
|
|
217
|
+
"INSERT INTO graph_metadata (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value",
|
|
218
|
+
)
|
|
219
|
+
upsertMeta.run("project_id", graph.project_id)
|
|
220
|
+
upsertMeta.run("version", graph.version)
|
|
221
|
+
upsertMeta.run("created_at", graph.metadata.created_at)
|
|
222
|
+
upsertMeta.run("updated_at", graph.metadata.updated_at)
|
|
223
|
+
upsertMeta.run("sdd_version", graph.metadata.sdd_version)
|
|
202
224
|
|
|
203
225
|
// Save nodes in batches for performance
|
|
204
226
|
const upsertNode = db.prepare(`
|
|
@@ -258,10 +280,13 @@ export class SqliteGraphRepository {
|
|
|
258
280
|
const deleteRelationship = db.prepare("DELETE FROM relationships WHERE id = ?")
|
|
259
281
|
for (const row of existingRelationshipIds) if (!relationshipIds.has(row.id)) deleteRelationship.run(row.id)
|
|
260
282
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
283
|
+
db.exec("COMMIT")
|
|
284
|
+
} catch (e) {
|
|
285
|
+
db.exec("ROLLBACK")
|
|
286
|
+
throw e
|
|
287
|
+
}
|
|
288
|
+
} finally {
|
|
289
|
+
cacheMgr.releaseWriteLock()
|
|
265
290
|
}
|
|
266
291
|
|
|
267
292
|
// Compare against the immutable cached snapshot before replacing it.
|
|
@@ -270,7 +295,9 @@ export class SqliteGraphRepository {
|
|
|
270
295
|
const snapshot = structuredClone(graph) as KnowledgeGraph
|
|
271
296
|
const dirty = computeDirtyState(cached?.graph || null, snapshot)
|
|
272
297
|
const indices = GraphIndices.from(snapshot)
|
|
273
|
-
|
|
298
|
+
const sourcePaths = [this.dbPath, `${this.dbPath}-wal`, `${this.dbPath}-shm`]
|
|
299
|
+
const sourceSignature = fileSignature(sourcePaths)
|
|
300
|
+
SqliteGraphRepository.cache.set(this.dbPath, { graph: snapshot, indices, sourceSignature })
|
|
274
301
|
/*
|
|
275
302
|
if (cached) {
|
|
276
303
|
const oldGraph = cached.graph
|
|
@@ -313,7 +340,6 @@ export class SqliteGraphRepository {
|
|
|
313
340
|
*/
|
|
314
341
|
|
|
315
342
|
// Update incremental hash
|
|
316
|
-
const cacheMgr = getCacheManager(require("path").dirname(this.baseDir))
|
|
317
343
|
cacheMgr.initGraphHash(graph.nodes.length, graph.relationships.length)
|
|
318
344
|
|
|
319
345
|
// A: Granular invalidation — only invalidate caches for changed types
|
|
@@ -326,7 +352,7 @@ export class SqliteGraphRepository {
|
|
|
326
352
|
}
|
|
327
353
|
|
|
328
354
|
// G: Save graph snapshot to disk for cross-session restore
|
|
329
|
-
cacheMgr.saveGraphSnapshot(graph)
|
|
355
|
+
cacheMgr.saveGraphSnapshot(graph, sourceSignature)
|
|
330
356
|
|
|
331
357
|
// Anti-bypass: record legitimate save for integrity tracking
|
|
332
358
|
const projectDir = require("path").dirname(this.baseDir)
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import * as yaml from "js-yaml"
|
|
2
|
-
import { readFileSync,
|
|
2
|
+
import { readFileSync, existsSync, mkdirSync, readdirSync } from "fs"
|
|
3
3
|
import { join, dirname } from "path"
|
|
4
4
|
import type { KnowledgeGraph, AnyNode, NodeType, NodeStatus, Relationship } from "../domain/types.js"
|
|
5
5
|
import { GraphIndices } from "../graph/index.js"
|
|
6
6
|
import type { GraphRepository } from "./repository.js"
|
|
7
7
|
import { getCacheManager } from "../cache/manager.js"
|
|
8
|
+
import { atomicWriteFile } from "../cache/atomic.js"
|
|
9
|
+
import { fileSignature } from "../cache/fingerprint.js"
|
|
8
10
|
import { recordLegitimateSave, validateGraphIntegrity, isGraphTampered } from "../graph/integrity-guard.js"
|
|
9
11
|
|
|
10
12
|
export function readYaml<T>(filePath: string): T {
|
|
@@ -21,7 +23,7 @@ export function writeYaml(filePath: string, data: unknown): void {
|
|
|
21
23
|
quotingType: '"',
|
|
22
24
|
forceQuotes: false,
|
|
23
25
|
})
|
|
24
|
-
|
|
26
|
+
atomicWriteFile(filePath, content)
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
export function readJson<T>(filePath: string): T {
|
|
@@ -32,7 +34,7 @@ export function readJson<T>(filePath: string): T {
|
|
|
32
34
|
export function writeJson(filePath: string, data: unknown): void {
|
|
33
35
|
const dir = dirname(filePath)
|
|
34
36
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true })
|
|
35
|
-
|
|
37
|
+
atomicWriteFile(filePath, JSON.stringify(data, null, 2))
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
export function ensureDir(dirPath: string): void {
|
|
@@ -73,6 +75,7 @@ interface GraphCache {
|
|
|
73
75
|
graph: KnowledgeGraph
|
|
74
76
|
indices: GraphIndices
|
|
75
77
|
lastModified: number
|
|
78
|
+
sourceSignature: string
|
|
76
79
|
}
|
|
77
80
|
|
|
78
81
|
// ── Repository ───────────────────────────────────────────────────────
|
|
@@ -110,29 +113,36 @@ export class YamlGraphRepository implements GraphRepository {
|
|
|
110
113
|
throw new Error("SDD not initialized. Run sdd.initialize first.")
|
|
111
114
|
}
|
|
112
115
|
|
|
116
|
+
const cacheMgr = getCacheManager(require("path").dirname(this.baseDir))
|
|
117
|
+
const currentSourceSignature = fileSignature([this.graphPath])
|
|
118
|
+
const externallyInvalidated = cacheMgr.checkCrossProcessInvalidation(this.graphPath)
|
|
119
|
+
|
|
113
120
|
// Check cache with revalidation
|
|
114
121
|
const cached = YamlGraphRepository.cache.get(this.graphPath)
|
|
115
122
|
if (cached) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
//
|
|
120
|
-
|
|
121
|
-
if (cacheMgr.isGraphHashValid(cached.indices.totalNodes + ":" + cached.indices.totalRelationships)) {
|
|
122
|
-
// Never expose the cached snapshot itself: callers intentionally
|
|
123
|
-
// mutate the graph before saveGraph(), and leaking this reference
|
|
124
|
-
// makes old/new comparisons impossible.
|
|
125
|
-
return structuredClone(cached.graph)
|
|
126
|
-
}
|
|
123
|
+
if (!externallyInvalidated && cached.sourceSignature === currentSourceSignature) {
|
|
124
|
+
// Never expose the cached snapshot itself: callers intentionally
|
|
125
|
+
// mutate the graph before saveGraph(), and leaking this reference
|
|
126
|
+
// makes old/new comparisons impossible.
|
|
127
|
+
return structuredClone(cached.graph)
|
|
127
128
|
}
|
|
128
129
|
// File was modified externally or hash mismatch, invalidate cache
|
|
129
130
|
YamlGraphRepository.cache.delete(this.graphPath)
|
|
130
131
|
}
|
|
132
|
+
if (externallyInvalidated) YamlGraphRepository.cache.delete(this.graphPath)
|
|
131
133
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
134
|
+
const snapshot = cacheMgr.loadGraphSnapshot()
|
|
135
|
+
if (snapshot?.sourceSignature === currentSourceSignature) {
|
|
136
|
+
const graph = snapshot.graph
|
|
137
|
+
const indices = GraphIndices.from(graph)
|
|
138
|
+
YamlGraphRepository.cache.set(this.graphPath, {
|
|
139
|
+
graph: structuredClone(graph),
|
|
140
|
+
indices,
|
|
141
|
+
lastModified: Date.now(),
|
|
142
|
+
sourceSignature: currentSourceSignature,
|
|
143
|
+
})
|
|
144
|
+
cacheMgr.initGraphHash(graph.nodes.length, graph.relationships.length)
|
|
145
|
+
return structuredClone(graph)
|
|
136
146
|
}
|
|
137
147
|
|
|
138
148
|
const graph = readYaml<KnowledgeGraph>(this.graphPath)
|
|
@@ -143,9 +153,10 @@ export class YamlGraphRepository implements GraphRepository {
|
|
|
143
153
|
graph,
|
|
144
154
|
indices,
|
|
145
155
|
lastModified: stat,
|
|
156
|
+
sourceSignature: currentSourceSignature,
|
|
146
157
|
})
|
|
147
158
|
|
|
148
|
-
// Initialize
|
|
159
|
+
// Initialize the legacy mutation counter used by compatibility APIs.
|
|
149
160
|
cacheMgr.initGraphHash(graph.nodes.length, graph.relationships.length)
|
|
150
161
|
|
|
151
162
|
// Anti-bypass: check for out-of-band modifications
|
|
@@ -174,7 +185,9 @@ export class YamlGraphRepository implements GraphRepository {
|
|
|
174
185
|
|
|
175
186
|
// Acquire cross-process lock
|
|
176
187
|
const cacheMgr = getCacheManager(require("path").dirname(this.baseDir))
|
|
177
|
-
cacheMgr.acquireWriteLock()
|
|
188
|
+
if (!cacheMgr.acquireWriteLock()) {
|
|
189
|
+
throw new Error("Another process is writing the SDD graph; retry the mutation")
|
|
190
|
+
}
|
|
178
191
|
|
|
179
192
|
try {
|
|
180
193
|
writeYaml(this.graphPath, graph)
|
|
@@ -199,11 +212,12 @@ export class YamlGraphRepository implements GraphRepository {
|
|
|
199
212
|
// readonly totals/search entries after additions and removals. YAML is
|
|
200
213
|
// limited to small graphs; large graphs migrate to SQLite.
|
|
201
214
|
const indices = GraphIndices.from(snapshot)
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
215
|
+
YamlGraphRepository.cache.set(this.graphPath, {
|
|
216
|
+
graph: snapshot,
|
|
217
|
+
indices,
|
|
218
|
+
lastModified: Date.now(),
|
|
219
|
+
sourceSignature: fileSignature([this.graphPath]),
|
|
220
|
+
})
|
|
207
221
|
/*
|
|
208
222
|
if (cached) {
|
|
209
223
|
// Compute dirty nodes incrementally
|
|
@@ -273,7 +287,7 @@ export class YamlGraphRepository implements GraphRepository {
|
|
|
273
287
|
}
|
|
274
288
|
|
|
275
289
|
// G: Save graph snapshot to disk for cross-session restore
|
|
276
|
-
cacheMgr.saveGraphSnapshot(graph)
|
|
290
|
+
cacheMgr.saveGraphSnapshot(graph, fileSignature([this.graphPath]))
|
|
277
291
|
}
|
|
278
292
|
|
|
279
293
|
getStorageType(): "yaml" {
|