@soulcraft/brainy 3.40.1 → 3.40.3
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/CHANGELOG.md +12 -0
- package/dist/utils/metadataIndex.js +31 -1
- package/dist/utils/unifiedCache.d.ts +6 -0
- package/dist/utils/unifiedCache.js +32 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [3.40.3](https://github.com/soulcraftlabs/brainy/compare/v3.40.2...v3.40.3) (2025-10-13)
|
|
6
|
+
|
|
7
|
+
- fix: prevent metadata index file pollution by excluding high-cardinality fields (0c86c4f)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### [3.40.2](https://github.com/soulcraftlabs/brainy/compare/v3.40.1...v3.40.2) (2025-10-13)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### ⚡ Performance Improvements
|
|
14
|
+
|
|
15
|
+
* more aggressive cache fairness to prevent thrashing ([829a8a6](https://github.com/soulcraftlabs/brainy/commit/829a8a61a23688aae1384b2844f1e75b1fd773d9))
|
|
16
|
+
|
|
5
17
|
### [3.40.1](https://github.com/soulcraftlabs/brainy/compare/v3.40.0...v3.40.1) (2025-10-13)
|
|
6
18
|
|
|
7
19
|
|
|
@@ -39,7 +39,37 @@ export class MetadataIndexManager {
|
|
|
39
39
|
rebuildThreshold: config.rebuildThreshold ?? 0.1,
|
|
40
40
|
autoOptimize: config.autoOptimize ?? true,
|
|
41
41
|
indexedFields: config.indexedFields ?? [],
|
|
42
|
-
excludeFields: config.excludeFields ?? [
|
|
42
|
+
excludeFields: config.excludeFields ?? [
|
|
43
|
+
// Timestamps (nearly unique per operation - causes massive file pollution)
|
|
44
|
+
'accessed',
|
|
45
|
+
'modified',
|
|
46
|
+
'createdAt',
|
|
47
|
+
'updatedAt',
|
|
48
|
+
'importedAt',
|
|
49
|
+
'extractedAt',
|
|
50
|
+
// UUIDs (unique per entity/relationship - creates one file per entity)
|
|
51
|
+
'id',
|
|
52
|
+
'parent',
|
|
53
|
+
'sourceId',
|
|
54
|
+
'targetId',
|
|
55
|
+
'source',
|
|
56
|
+
'target',
|
|
57
|
+
'owner',
|
|
58
|
+
// Paths and hashes (unique per file - creates one file per path)
|
|
59
|
+
'path',
|
|
60
|
+
'hash',
|
|
61
|
+
'url',
|
|
62
|
+
// Content fields (too large/unique - unnecessary for indexing)
|
|
63
|
+
'content',
|
|
64
|
+
'data',
|
|
65
|
+
'originalData',
|
|
66
|
+
'_data',
|
|
67
|
+
// Vectors (already excluded - keeping for backward compatibility)
|
|
68
|
+
'embedding',
|
|
69
|
+
'vector',
|
|
70
|
+
'embeddings',
|
|
71
|
+
'vectors'
|
|
72
|
+
]
|
|
43
73
|
};
|
|
44
74
|
// Initialize metadata cache with similar config to search cache
|
|
45
75
|
this.metadataCache = new MetadataIndexCache({
|
|
@@ -78,6 +78,12 @@ export declare class UnifiedCache {
|
|
|
78
78
|
*/
|
|
79
79
|
private startFairnessMonitor;
|
|
80
80
|
private checkFairness;
|
|
81
|
+
/**
|
|
82
|
+
* Proactive fairness check (v3.40.2)
|
|
83
|
+
* Called immediately when adding items to prevent imbalance formation
|
|
84
|
+
* Uses same thresholds as periodic check but runs on-demand
|
|
85
|
+
*/
|
|
86
|
+
private checkProactiveFairness;
|
|
81
87
|
/**
|
|
82
88
|
* Force evict items of a specific type
|
|
83
89
|
*/
|
|
@@ -50,7 +50,7 @@ export class UnifiedCache {
|
|
|
50
50
|
this.config = {
|
|
51
51
|
enableRequestCoalescing: true,
|
|
52
52
|
enableFairnessCheck: true,
|
|
53
|
-
fairnessCheckInterval:
|
|
53
|
+
fairnessCheckInterval: 30000, // Check fairness every 30 seconds (v3.40.2: was 60s)
|
|
54
54
|
persistPatterns: true,
|
|
55
55
|
enableMemoryMonitoring: true,
|
|
56
56
|
memoryCheckInterval: 30000, // Check memory every 30s
|
|
@@ -149,6 +149,11 @@ export class UnifiedCache {
|
|
|
149
149
|
this.currentSize += size;
|
|
150
150
|
this.typeAccessCounts[type]++;
|
|
151
151
|
this.totalAccessCount++;
|
|
152
|
+
// Proactive fairness check (v3.40.2): Check immediately if adding to a dominant type
|
|
153
|
+
// This prevents imbalance formation instead of reacting to it
|
|
154
|
+
if (this.config.enableFairnessCheck && this.cache.size > 10) {
|
|
155
|
+
this.checkProactiveFairness(type);
|
|
156
|
+
}
|
|
152
157
|
}
|
|
153
158
|
/**
|
|
154
159
|
* Evict item with lowest value (access count / rebuild cost)
|
|
@@ -235,14 +240,36 @@ export class UnifiedCache {
|
|
|
235
240
|
embedding: typeSizes.embedding / totalSize,
|
|
236
241
|
other: typeSizes.other / totalSize
|
|
237
242
|
};
|
|
238
|
-
// Check for starvation (
|
|
243
|
+
// Check for starvation (v3.40.2: more aggressive - 70% cache with <15% accesses)
|
|
244
|
+
// Previous: 90% cache, <10% access (too lenient, caused thrashing)
|
|
239
245
|
for (const type of ['hnsw', 'metadata', 'embedding', 'other']) {
|
|
240
|
-
if (sizeRatios[type] > 0.
|
|
246
|
+
if (sizeRatios[type] > 0.7 && accessRatios[type] < 0.15) {
|
|
241
247
|
prodLog.warn(`Type ${type} is hogging cache (${(sizeRatios[type] * 100).toFixed(1)}% size, ${(accessRatios[type] * 100).toFixed(1)}% access)`);
|
|
242
248
|
this.evictType(type);
|
|
243
249
|
}
|
|
244
250
|
}
|
|
245
251
|
}
|
|
252
|
+
/**
|
|
253
|
+
* Proactive fairness check (v3.40.2)
|
|
254
|
+
* Called immediately when adding items to prevent imbalance formation
|
|
255
|
+
* Uses same thresholds as periodic check but runs on-demand
|
|
256
|
+
*/
|
|
257
|
+
checkProactiveFairness(addedType) {
|
|
258
|
+
// Quick check: only evaluate the type being added
|
|
259
|
+
let typeSize = 0;
|
|
260
|
+
for (const item of this.cache.values()) {
|
|
261
|
+
if (item.type === addedType) {
|
|
262
|
+
typeSize += item.size;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
const sizeRatio = typeSize / (this.currentSize || 1);
|
|
266
|
+
const accessRatio = this.typeAccessCounts[addedType] / (this.totalAccessCount || 1);
|
|
267
|
+
// Same threshold as periodic check: 70% size, <15% access
|
|
268
|
+
if (sizeRatio > 0.7 && accessRatio < 0.15) {
|
|
269
|
+
prodLog.debug(`Proactive fairness: ${addedType} reaching dominance (${(sizeRatio * 100).toFixed(1)}% size, ${(accessRatio * 100).toFixed(1)}% access)`);
|
|
270
|
+
this.evictType(addedType);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
246
273
|
/**
|
|
247
274
|
* Force evict items of a specific type
|
|
248
275
|
*/
|
|
@@ -256,8 +283,8 @@ export class UnifiedCache {
|
|
|
256
283
|
}
|
|
257
284
|
// Sort by score (lower is worse)
|
|
258
285
|
candidates.sort((a, b) => a[1] - b[1]);
|
|
259
|
-
// Evict bottom
|
|
260
|
-
const evictCount = Math.max(1, Math.floor(candidates.length * 0.
|
|
286
|
+
// Evict bottom 50% of this type (v3.40.2: was 20%, too slow to prevent thrashing)
|
|
287
|
+
const evictCount = Math.max(1, Math.floor(candidates.length * 0.5));
|
|
261
288
|
for (let i = 0; i < evictCount && i < candidates.length; i++) {
|
|
262
289
|
const [key, , item] = candidates[i];
|
|
263
290
|
this.currentSize -= item.size;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soulcraft/brainy",
|
|
3
|
-
"version": "3.40.
|
|
3
|
+
"version": "3.40.3",
|
|
4
4
|
"description": "Universal Knowledge Protocol™ - World's first Triple Intelligence database unifying vector, graph, and document search in one API. 31 nouns × 40 verbs for infinite expressiveness.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|