@inerrata-corporation/errata 2.0.22-dev.4652 → 2.0.22-dev.4657
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/consolidate-worker.mjs
CHANGED
|
@@ -17126,6 +17126,7 @@ var EXPOSURE_SCOPE = "exposure";
|
|
|
17126
17126
|
// ../../packages/local-graph/src/change-feed.ts
|
|
17127
17127
|
var CHANGE_FEED_KEY = "change-feed";
|
|
17128
17128
|
var ANY_CHANGE = "*";
|
|
17129
|
+
var nodeScope = (label) => `node:${label}`;
|
|
17129
17130
|
var CHANGE_LOG_KEEP = 25e4;
|
|
17130
17131
|
var PRUNED_TO_KEY = "change-log-pruned-to";
|
|
17131
17132
|
function installChangeFeed(db) {
|
|
@@ -18040,6 +18041,7 @@ var SqliteGraphStore = class {
|
|
|
18040
18041
|
initialPageRankScale;
|
|
18041
18042
|
constructor(opts) {
|
|
18042
18043
|
this.db = openDatabase(opts.path);
|
|
18044
|
+
this.db.exec("PRAGMA cache_size = -32768");
|
|
18043
18045
|
this.db.exec(SCHEMA_SQL);
|
|
18044
18046
|
const versionRow = this.db.prepare("SELECT version FROM schema_version LIMIT 1").get();
|
|
18045
18047
|
if (!versionRow) {
|
|
@@ -18104,6 +18106,7 @@ var SqliteGraphStore = class {
|
|
|
18104
18106
|
attrs_json = excluded.attrs_json
|
|
18105
18107
|
`),
|
|
18106
18108
|
getNode: this.db.prepare("SELECT * FROM nodes WHERE id = ?"),
|
|
18109
|
+
labelOf: this.db.prepare("SELECT label FROM nodes WHERE id = ?"),
|
|
18107
18110
|
// Single-column fast paths for the nightly pass — writing 100k pageRank
|
|
18108
18111
|
// values through the 18-column COALESCE updateNode took ~30s; these are ~10x
|
|
18109
18112
|
// cheaper (one bound column, no COALESCE evaluation per row).
|
|
@@ -18603,11 +18606,13 @@ var SqliteGraphStore = class {
|
|
|
18603
18606
|
}
|
|
18604
18607
|
}
|
|
18605
18608
|
edgeRuleViolation(edge) {
|
|
18606
|
-
return localEdgeViolation(
|
|
18607
|
-
|
|
18608
|
-
|
|
18609
|
-
|
|
18610
|
-
|
|
18609
|
+
return localEdgeViolation(this.labelOf(edge.from), edge.type, this.labelOf(edge.to));
|
|
18610
|
+
}
|
|
18611
|
+
/** An endpoint's label, any version, as `getNode(id)?.label` reads it. Every
|
|
18612
|
+
* edge write checks both endpoints, and hydrating them (attrs + vector) to
|
|
18613
|
+
* read one leading column was most of an incremental reindex's reads. */
|
|
18614
|
+
labelOf(id) {
|
|
18615
|
+
return this.stmts.labelOf.get(id)?.label;
|
|
18611
18616
|
}
|
|
18612
18617
|
updateEdge(id, patch) {
|
|
18613
18618
|
this.stmts.updateEdge.run({
|
|
@@ -18651,7 +18656,21 @@ var SqliteGraphStore = class {
|
|
|
18651
18656
|
* per project per request; the materializing form held the daemon's event
|
|
18652
18657
|
* loop for seconds at scale. */
|
|
18653
18658
|
countNodesByLabel(label) {
|
|
18654
|
-
return Number(this.stmts.countByLabel.get(label).n);
|
|
18659
|
+
return this.countAt(`label:${label}`, [nodeScope(label)], () => Number(this.stmts.countByLabel.get(label).n));
|
|
18660
|
+
}
|
|
18661
|
+
/** Counts asked for on every status poll (/health, `errata status`, the
|
|
18662
|
+
* dashboards): a live-node COUNT(*) reads the whole liveness index, ~3 MB per
|
|
18663
|
+
* call on a 1.1 GB store, to recount a set that moves only on a write. Each is
|
|
18664
|
+
* kept with the change-feed reading of the rows it counts — triggers bump it on
|
|
18665
|
+
* every write from any connection, so a hit is exact, not a TTL guess. */
|
|
18666
|
+
counts = /* @__PURE__ */ new Map();
|
|
18667
|
+
countAt(key, scopes, count) {
|
|
18668
|
+
const seq = readChangeSeq(this.db, scopes);
|
|
18669
|
+
const hit = this.counts.get(key);
|
|
18670
|
+
if (hit && hit.seq === seq) return hit.n;
|
|
18671
|
+
const n = count();
|
|
18672
|
+
this.counts.set(key, { seq, n });
|
|
18673
|
+
return n;
|
|
18655
18674
|
}
|
|
18656
18675
|
/** Live rows for a label with attrs and creation stamps only — for scans that
|
|
18657
18676
|
* read attrs and never the vector. `findNodesByLabel` decodes every embedding
|
|
@@ -18918,7 +18937,7 @@ var SqliteGraphStore = class {
|
|
|
18918
18937
|
return out;
|
|
18919
18938
|
}
|
|
18920
18939
|
nodeCount() {
|
|
18921
|
-
return Number(this.stmts.nodeCount.get().n);
|
|
18940
|
+
return this.countAt("nodes", [ANY_CHANGE], () => Number(this.stmts.nodeCount.get().n));
|
|
18922
18941
|
}
|
|
18923
18942
|
mutationCount() {
|
|
18924
18943
|
return this.mutations;
|
|
@@ -18962,7 +18981,7 @@ var SqliteGraphStore = class {
|
|
|
18962
18981
|
return this.ingestSeq;
|
|
18963
18982
|
}
|
|
18964
18983
|
edgeCount() {
|
|
18965
|
-
return Number(this.stmts.edgeCount.get().n);
|
|
18984
|
+
return this.countAt("edges", [ANY_CHANGE], () => Number(this.stmts.edgeCount.get().n));
|
|
18966
18985
|
}
|
|
18967
18986
|
// Lightweight whole-graph scans — select only the columns the caller needs so a
|
|
18968
18987
|
// 100k-node pass skips the per-row attrs JSON.parse + embedding decode rowToNode
|
package/errata.mjs
CHANGED
|
@@ -20892,6 +20892,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
20892
20892
|
initialPageRankScale;
|
|
20893
20893
|
constructor(opts) {
|
|
20894
20894
|
this.db = openDatabase(opts.path);
|
|
20895
|
+
this.db.exec("PRAGMA cache_size = -32768");
|
|
20895
20896
|
this.db.exec(SCHEMA_SQL);
|
|
20896
20897
|
const versionRow = this.db.prepare("SELECT version FROM schema_version LIMIT 1").get();
|
|
20897
20898
|
if (!versionRow) {
|
|
@@ -20956,6 +20957,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
20956
20957
|
attrs_json = excluded.attrs_json
|
|
20957
20958
|
`),
|
|
20958
20959
|
getNode: this.db.prepare("SELECT * FROM nodes WHERE id = ?"),
|
|
20960
|
+
labelOf: this.db.prepare("SELECT label FROM nodes WHERE id = ?"),
|
|
20959
20961
|
// Single-column fast paths for the nightly pass — writing 100k pageRank
|
|
20960
20962
|
// values through the 18-column COALESCE updateNode took ~30s; these are ~10x
|
|
20961
20963
|
// cheaper (one bound column, no COALESCE evaluation per row).
|
|
@@ -21455,11 +21457,13 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21455
21457
|
}
|
|
21456
21458
|
}
|
|
21457
21459
|
edgeRuleViolation(edge2) {
|
|
21458
|
-
return localEdgeViolation(
|
|
21459
|
-
|
|
21460
|
-
|
|
21461
|
-
|
|
21462
|
-
|
|
21460
|
+
return localEdgeViolation(this.labelOf(edge2.from), edge2.type, this.labelOf(edge2.to));
|
|
21461
|
+
}
|
|
21462
|
+
/** An endpoint's label, any version, as `getNode(id)?.label` reads it. Every
|
|
21463
|
+
* edge write checks both endpoints, and hydrating them (attrs + vector) to
|
|
21464
|
+
* read one leading column was most of an incremental reindex's reads. */
|
|
21465
|
+
labelOf(id) {
|
|
21466
|
+
return this.stmts.labelOf.get(id)?.label;
|
|
21463
21467
|
}
|
|
21464
21468
|
updateEdge(id, patch) {
|
|
21465
21469
|
this.stmts.updateEdge.run({
|
|
@@ -21503,7 +21507,21 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21503
21507
|
* per project per request; the materializing form held the daemon's event
|
|
21504
21508
|
* loop for seconds at scale. */
|
|
21505
21509
|
countNodesByLabel(label) {
|
|
21506
|
-
return Number(this.stmts.countByLabel.get(label).n);
|
|
21510
|
+
return this.countAt(`label:${label}`, [nodeScope(label)], () => Number(this.stmts.countByLabel.get(label).n));
|
|
21511
|
+
}
|
|
21512
|
+
/** Counts asked for on every status poll (/health, `errata status`, the
|
|
21513
|
+
* dashboards): a live-node COUNT(*) reads the whole liveness index, ~3 MB per
|
|
21514
|
+
* call on a 1.1 GB store, to recount a set that moves only on a write. Each is
|
|
21515
|
+
* kept with the change-feed reading of the rows it counts — triggers bump it on
|
|
21516
|
+
* every write from any connection, so a hit is exact, not a TTL guess. */
|
|
21517
|
+
counts = /* @__PURE__ */ new Map();
|
|
21518
|
+
countAt(key, scopes, count) {
|
|
21519
|
+
const seq = readChangeSeq(this.db, scopes);
|
|
21520
|
+
const hit = this.counts.get(key);
|
|
21521
|
+
if (hit && hit.seq === seq) return hit.n;
|
|
21522
|
+
const n = count();
|
|
21523
|
+
this.counts.set(key, { seq, n });
|
|
21524
|
+
return n;
|
|
21507
21525
|
}
|
|
21508
21526
|
/** Live rows for a label with attrs and creation stamps only — for scans that
|
|
21509
21527
|
* read attrs and never the vector. `findNodesByLabel` decodes every embedding
|
|
@@ -21770,7 +21788,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21770
21788
|
return out2;
|
|
21771
21789
|
}
|
|
21772
21790
|
nodeCount() {
|
|
21773
|
-
return Number(this.stmts.nodeCount.get().n);
|
|
21791
|
+
return this.countAt("nodes", [ANY_CHANGE], () => Number(this.stmts.nodeCount.get().n));
|
|
21774
21792
|
}
|
|
21775
21793
|
mutationCount() {
|
|
21776
21794
|
return this.mutations;
|
|
@@ -21814,7 +21832,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21814
21832
|
return this.ingestSeq;
|
|
21815
21833
|
}
|
|
21816
21834
|
edgeCount() {
|
|
21817
|
-
return Number(this.stmts.edgeCount.get().n);
|
|
21835
|
+
return this.countAt("edges", [ANY_CHANGE], () => Number(this.stmts.edgeCount.get().n));
|
|
21818
21836
|
}
|
|
21819
21837
|
// Lightweight whole-graph scans — select only the columns the caller needs so a
|
|
21820
21838
|
// 100k-node pass skips the per-row attrs JSON.parse + embedding decode rowToNode
|
|
@@ -39603,9 +39621,10 @@ async function runIndexer(store, opts) {
|
|
|
39603
39621
|
if (ei > 0) await new Promise((r) => setImmediate(r));
|
|
39604
39622
|
const slice = pendingEdges.slice(ei, ei + EDGE_BATCH);
|
|
39605
39623
|
store.transaction(() => {
|
|
39624
|
+
const present = store.nodeLabels([...new Set(slice.flatMap((e) => [e.from, e.to]))]);
|
|
39606
39625
|
for (const e of slice) {
|
|
39607
39626
|
if (e.from === e.to) continue;
|
|
39608
|
-
if (!
|
|
39627
|
+
if (!present.has(e.from) || !present.has(e.to)) continue;
|
|
39609
39628
|
upsertEdge(
|
|
39610
39629
|
store,
|
|
39611
39630
|
e.from,
|
|
@@ -87006,7 +87025,7 @@ function createWatchBreaker(deps) {
|
|
|
87006
87025
|
}
|
|
87007
87026
|
|
|
87008
87027
|
// src/engine.ts
|
|
87009
|
-
var DAEMON_VERSION = true ? "2.0.22-dev.
|
|
87028
|
+
var DAEMON_VERSION = true ? "2.0.22-dev.4657" : "2.0.0-alpha.0";
|
|
87010
87029
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
87011
87030
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
87012
87031
|
var GIT_OP_MUTE_MS = 4e3;
|
package/generalize-worker.mjs
CHANGED
|
@@ -15700,6 +15700,7 @@ var EXPOSURE_SCOPE = "exposure";
|
|
|
15700
15700
|
// ../../packages/local-graph/src/change-feed.ts
|
|
15701
15701
|
var CHANGE_FEED_KEY = "change-feed";
|
|
15702
15702
|
var ANY_CHANGE = "*";
|
|
15703
|
+
var nodeScope = (label) => `node:${label}`;
|
|
15703
15704
|
var CHANGE_LOG_KEEP = 25e4;
|
|
15704
15705
|
var PRUNED_TO_KEY = "change-log-pruned-to";
|
|
15705
15706
|
function installChangeFeed(db) {
|
|
@@ -16437,6 +16438,7 @@ var SqliteGraphStore = class {
|
|
|
16437
16438
|
initialPageRankScale;
|
|
16438
16439
|
constructor(opts) {
|
|
16439
16440
|
this.db = openDatabase(opts.path);
|
|
16441
|
+
this.db.exec("PRAGMA cache_size = -32768");
|
|
16440
16442
|
this.db.exec(SCHEMA_SQL);
|
|
16441
16443
|
const versionRow = this.db.prepare("SELECT version FROM schema_version LIMIT 1").get();
|
|
16442
16444
|
if (!versionRow) {
|
|
@@ -16501,6 +16503,7 @@ var SqliteGraphStore = class {
|
|
|
16501
16503
|
attrs_json = excluded.attrs_json
|
|
16502
16504
|
`),
|
|
16503
16505
|
getNode: this.db.prepare("SELECT * FROM nodes WHERE id = ?"),
|
|
16506
|
+
labelOf: this.db.prepare("SELECT label FROM nodes WHERE id = ?"),
|
|
16504
16507
|
// Single-column fast paths for the nightly pass — writing 100k pageRank
|
|
16505
16508
|
// values through the 18-column COALESCE updateNode took ~30s; these are ~10x
|
|
16506
16509
|
// cheaper (one bound column, no COALESCE evaluation per row).
|
|
@@ -17000,11 +17003,13 @@ var SqliteGraphStore = class {
|
|
|
17000
17003
|
}
|
|
17001
17004
|
}
|
|
17002
17005
|
edgeRuleViolation(edge) {
|
|
17003
|
-
return localEdgeViolation(
|
|
17004
|
-
|
|
17005
|
-
|
|
17006
|
-
|
|
17007
|
-
|
|
17006
|
+
return localEdgeViolation(this.labelOf(edge.from), edge.type, this.labelOf(edge.to));
|
|
17007
|
+
}
|
|
17008
|
+
/** An endpoint's label, any version, as `getNode(id)?.label` reads it. Every
|
|
17009
|
+
* edge write checks both endpoints, and hydrating them (attrs + vector) to
|
|
17010
|
+
* read one leading column was most of an incremental reindex's reads. */
|
|
17011
|
+
labelOf(id) {
|
|
17012
|
+
return this.stmts.labelOf.get(id)?.label;
|
|
17008
17013
|
}
|
|
17009
17014
|
updateEdge(id, patch) {
|
|
17010
17015
|
this.stmts.updateEdge.run({
|
|
@@ -17048,7 +17053,21 @@ var SqliteGraphStore = class {
|
|
|
17048
17053
|
* per project per request; the materializing form held the daemon's event
|
|
17049
17054
|
* loop for seconds at scale. */
|
|
17050
17055
|
countNodesByLabel(label) {
|
|
17051
|
-
return Number(this.stmts.countByLabel.get(label).n);
|
|
17056
|
+
return this.countAt(`label:${label}`, [nodeScope(label)], () => Number(this.stmts.countByLabel.get(label).n));
|
|
17057
|
+
}
|
|
17058
|
+
/** Counts asked for on every status poll (/health, `errata status`, the
|
|
17059
|
+
* dashboards): a live-node COUNT(*) reads the whole liveness index, ~3 MB per
|
|
17060
|
+
* call on a 1.1 GB store, to recount a set that moves only on a write. Each is
|
|
17061
|
+
* kept with the change-feed reading of the rows it counts — triggers bump it on
|
|
17062
|
+
* every write from any connection, so a hit is exact, not a TTL guess. */
|
|
17063
|
+
counts = /* @__PURE__ */ new Map();
|
|
17064
|
+
countAt(key, scopes, count) {
|
|
17065
|
+
const seq = readChangeSeq(this.db, scopes);
|
|
17066
|
+
const hit = this.counts.get(key);
|
|
17067
|
+
if (hit && hit.seq === seq) return hit.n;
|
|
17068
|
+
const n = count();
|
|
17069
|
+
this.counts.set(key, { seq, n });
|
|
17070
|
+
return n;
|
|
17052
17071
|
}
|
|
17053
17072
|
/** Live rows for a label with attrs and creation stamps only — for scans that
|
|
17054
17073
|
* read attrs and never the vector. `findNodesByLabel` decodes every embedding
|
|
@@ -17315,7 +17334,7 @@ var SqliteGraphStore = class {
|
|
|
17315
17334
|
return out;
|
|
17316
17335
|
}
|
|
17317
17336
|
nodeCount() {
|
|
17318
|
-
return Number(this.stmts.nodeCount.get().n);
|
|
17337
|
+
return this.countAt("nodes", [ANY_CHANGE], () => Number(this.stmts.nodeCount.get().n));
|
|
17319
17338
|
}
|
|
17320
17339
|
mutationCount() {
|
|
17321
17340
|
return this.mutations;
|
|
@@ -17359,7 +17378,7 @@ var SqliteGraphStore = class {
|
|
|
17359
17378
|
return this.ingestSeq;
|
|
17360
17379
|
}
|
|
17361
17380
|
edgeCount() {
|
|
17362
|
-
return Number(this.stmts.edgeCount.get().n);
|
|
17381
|
+
return this.countAt("edges", [ANY_CHANGE], () => Number(this.stmts.edgeCount.get().n));
|
|
17363
17382
|
}
|
|
17364
17383
|
// Lightweight whole-graph scans — select only the columns the caller needs so a
|
|
17365
17384
|
// 100k-node pass skips the per-row attrs JSON.parse + embedding decode rowToNode
|
package/package.json
CHANGED
package/pass-worker.mjs
CHANGED
|
@@ -18280,9 +18280,10 @@ async function runIndexer(store2, opts) {
|
|
|
18280
18280
|
if (ei > 0) await new Promise((r) => setImmediate(r));
|
|
18281
18281
|
const slice = pendingEdges.slice(ei, ei + EDGE_BATCH);
|
|
18282
18282
|
store2.transaction(() => {
|
|
18283
|
+
const present = store2.nodeLabels([...new Set(slice.flatMap((e) => [e.from, e.to]))]);
|
|
18283
18284
|
for (const e of slice) {
|
|
18284
18285
|
if (e.from === e.to) continue;
|
|
18285
|
-
if (!
|
|
18286
|
+
if (!present.has(e.from) || !present.has(e.to)) continue;
|
|
18286
18287
|
upsertEdge(
|
|
18287
18288
|
store2,
|
|
18288
18289
|
e.from,
|
|
@@ -26142,6 +26143,7 @@ var EXPOSURE_SCOPE = "exposure";
|
|
|
26142
26143
|
// ../../packages/local-graph/src/change-feed.ts
|
|
26143
26144
|
var CHANGE_FEED_KEY = "change-feed";
|
|
26144
26145
|
var ANY_CHANGE = "*";
|
|
26146
|
+
var nodeScope = (label) => `node:${label}`;
|
|
26145
26147
|
var CHANGE_LOG_KEEP = 25e4;
|
|
26146
26148
|
var PRUNED_TO_KEY = "change-log-pruned-to";
|
|
26147
26149
|
function installChangeFeed(db) {
|
|
@@ -27315,6 +27317,7 @@ var SqliteGraphStore = class {
|
|
|
27315
27317
|
initialPageRankScale;
|
|
27316
27318
|
constructor(opts) {
|
|
27317
27319
|
this.db = openDatabase(opts.path);
|
|
27320
|
+
this.db.exec("PRAGMA cache_size = -32768");
|
|
27318
27321
|
this.db.exec(SCHEMA_SQL);
|
|
27319
27322
|
const versionRow = this.db.prepare("SELECT version FROM schema_version LIMIT 1").get();
|
|
27320
27323
|
if (!versionRow) {
|
|
@@ -27379,6 +27382,7 @@ var SqliteGraphStore = class {
|
|
|
27379
27382
|
attrs_json = excluded.attrs_json
|
|
27380
27383
|
`),
|
|
27381
27384
|
getNode: this.db.prepare("SELECT * FROM nodes WHERE id = ?"),
|
|
27385
|
+
labelOf: this.db.prepare("SELECT label FROM nodes WHERE id = ?"),
|
|
27382
27386
|
// Single-column fast paths for the nightly pass — writing 100k pageRank
|
|
27383
27387
|
// values through the 18-column COALESCE updateNode took ~30s; these are ~10x
|
|
27384
27388
|
// cheaper (one bound column, no COALESCE evaluation per row).
|
|
@@ -27878,11 +27882,13 @@ var SqliteGraphStore = class {
|
|
|
27878
27882
|
}
|
|
27879
27883
|
}
|
|
27880
27884
|
edgeRuleViolation(edge) {
|
|
27881
|
-
return localEdgeViolation(
|
|
27882
|
-
|
|
27883
|
-
|
|
27884
|
-
|
|
27885
|
-
|
|
27885
|
+
return localEdgeViolation(this.labelOf(edge.from), edge.type, this.labelOf(edge.to));
|
|
27886
|
+
}
|
|
27887
|
+
/** An endpoint's label, any version, as `getNode(id)?.label` reads it. Every
|
|
27888
|
+
* edge write checks both endpoints, and hydrating them (attrs + vector) to
|
|
27889
|
+
* read one leading column was most of an incremental reindex's reads. */
|
|
27890
|
+
labelOf(id) {
|
|
27891
|
+
return this.stmts.labelOf.get(id)?.label;
|
|
27886
27892
|
}
|
|
27887
27893
|
updateEdge(id, patch) {
|
|
27888
27894
|
this.stmts.updateEdge.run({
|
|
@@ -27926,7 +27932,21 @@ var SqliteGraphStore = class {
|
|
|
27926
27932
|
* per project per request; the materializing form held the daemon's event
|
|
27927
27933
|
* loop for seconds at scale. */
|
|
27928
27934
|
countNodesByLabel(label) {
|
|
27929
|
-
return Number(this.stmts.countByLabel.get(label).n);
|
|
27935
|
+
return this.countAt(`label:${label}`, [nodeScope(label)], () => Number(this.stmts.countByLabel.get(label).n));
|
|
27936
|
+
}
|
|
27937
|
+
/** Counts asked for on every status poll (/health, `errata status`, the
|
|
27938
|
+
* dashboards): a live-node COUNT(*) reads the whole liveness index, ~3 MB per
|
|
27939
|
+
* call on a 1.1 GB store, to recount a set that moves only on a write. Each is
|
|
27940
|
+
* kept with the change-feed reading of the rows it counts — triggers bump it on
|
|
27941
|
+
* every write from any connection, so a hit is exact, not a TTL guess. */
|
|
27942
|
+
counts = /* @__PURE__ */ new Map();
|
|
27943
|
+
countAt(key, scopes, count) {
|
|
27944
|
+
const seq = readChangeSeq(this.db, scopes);
|
|
27945
|
+
const hit = this.counts.get(key);
|
|
27946
|
+
if (hit && hit.seq === seq) return hit.n;
|
|
27947
|
+
const n = count();
|
|
27948
|
+
this.counts.set(key, { seq, n });
|
|
27949
|
+
return n;
|
|
27930
27950
|
}
|
|
27931
27951
|
/** Live rows for a label with attrs and creation stamps only — for scans that
|
|
27932
27952
|
* read attrs and never the vector. `findNodesByLabel` decodes every embedding
|
|
@@ -28193,7 +28213,7 @@ var SqliteGraphStore = class {
|
|
|
28193
28213
|
return out2;
|
|
28194
28214
|
}
|
|
28195
28215
|
nodeCount() {
|
|
28196
|
-
return Number(this.stmts.nodeCount.get().n);
|
|
28216
|
+
return this.countAt("nodes", [ANY_CHANGE], () => Number(this.stmts.nodeCount.get().n));
|
|
28197
28217
|
}
|
|
28198
28218
|
mutationCount() {
|
|
28199
28219
|
return this.mutations;
|
|
@@ -28237,7 +28257,7 @@ var SqliteGraphStore = class {
|
|
|
28237
28257
|
return this.ingestSeq;
|
|
28238
28258
|
}
|
|
28239
28259
|
edgeCount() {
|
|
28240
|
-
return Number(this.stmts.edgeCount.get().n);
|
|
28260
|
+
return this.countAt("edges", [ANY_CHANGE], () => Number(this.stmts.edgeCount.get().n));
|
|
28241
28261
|
}
|
|
28242
28262
|
// Lightweight whole-graph scans — select only the columns the caller needs so a
|
|
28243
28263
|
// 100k-node pass skips the per-row attrs JSON.parse + embedding decode rowToNode
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
e7f2b11ac106aa4f1ad1c492a48adfed53759ae7c7d5cba5f087ff791f67f48d .codex-plugin/plugin.json
|
|
2
2
|
a7bebae9fb01c838d6c75fc784129e28be571233fa66ff5ee8039b574f35ccf7 assets/icon.png
|
|
3
3
|
fc38b64e4df1e0b72c35764bef6c4c05430d97c9009ad0ecc8a9e75b4deab232 configure-local.mjs
|
|
4
4
|
73dc6028b3b070257c7c31f252d11e55a9e096f4aed0f187f10cb21716e1e6d7 dist/client.js
|