@soulcraft/brainy 5.10.2 → 5.10.4
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 +10 -0
- package/README.md +1 -0
- package/dist/brainy.js +4 -0
- package/dist/storage/adapters/azureBlobStorage.d.ts +13 -0
- package/dist/storage/adapters/azureBlobStorage.js +44 -0
- package/dist/storage/adapters/fileSystemStorage.d.ts +13 -0
- package/dist/storage/adapters/fileSystemStorage.js +53 -10
- package/dist/storage/adapters/gcsStorage.d.ts +13 -0
- package/dist/storage/adapters/gcsStorage.js +42 -0
- package/dist/storage/adapters/historicalStorageAdapter.d.ts +13 -0
- package/dist/storage/adapters/historicalStorageAdapter.js +17 -0
- package/dist/storage/adapters/memoryStorage.d.ts +13 -0
- package/dist/storage/adapters/memoryStorage.js +18 -0
- package/dist/storage/adapters/opfsStorage.d.ts +13 -0
- package/dist/storage/adapters/opfsStorage.js +50 -0
- package/dist/storage/adapters/r2Storage.d.ts +13 -0
- package/dist/storage/adapters/r2Storage.js +40 -0
- package/dist/storage/adapters/s3CompatibleStorage.d.ts +13 -0
- package/dist/storage/adapters/s3CompatibleStorage.js +53 -0
- package/dist/storage/baseStorage.d.ts +15 -0
- package/dist/storage/baseStorage.js +8 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
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
|
+
### [5.10.4](https://github.com/soulcraftlabs/brainy/compare/v5.10.3...v5.10.4) (2025-11-17)
|
|
6
|
+
|
|
7
|
+
- fix: critical clear() data persistence regression (v5.10.4) (aba1563)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### [5.10.3](https://github.com/soulcraftlabs/brainy/compare/v5.10.2...v5.10.3) (2025-11-14)
|
|
11
|
+
|
|
12
|
+
- docs: add production service architecture guide to public docs (759e7fa)
|
|
13
|
+
|
|
14
|
+
|
|
5
15
|
### [5.10.2](https://github.com/soulcraftlabs/brainy/compare/v5.10.1...v5.10.2) (2025-11-14)
|
|
6
16
|
|
|
7
17
|
- docs: remove external project references from documentation (ccd6c54)
|
package/README.md
CHANGED
|
@@ -197,6 +197,7 @@ const brain = new Brainy({
|
|
|
197
197
|
})
|
|
198
198
|
```
|
|
199
199
|
**Scale:** Thousands to hundreds of thousands • **Performance:** <5ms queries
|
|
200
|
+
**→ [Production Service Architecture](docs/PRODUCTION_SERVICE_ARCHITECTURE.md)** — Singleton patterns, caching, and scaling for Express/Node.js services
|
|
200
201
|
|
|
201
202
|
### 🏢 Growing Company → Multi-Million Scale
|
|
202
203
|
```javascript
|
package/dist/brainy.js
CHANGED
|
@@ -1829,6 +1829,10 @@ export class Brainy {
|
|
|
1829
1829
|
// Recreate index if no clear method
|
|
1830
1830
|
this.index = this.setupIndex();
|
|
1831
1831
|
}
|
|
1832
|
+
// v5.10.4: Recreate metadata index to clear cached data
|
|
1833
|
+
// Bug: Metadata index cache was not being cleared, causing find() with type filters to return stale data
|
|
1834
|
+
this.metadataIndex = new MetadataIndexManager(this.storage);
|
|
1835
|
+
await this.metadataIndex.init();
|
|
1832
1836
|
// Reset dimensions
|
|
1833
1837
|
this.dimensions = undefined;
|
|
1834
1838
|
// Clear any cached sub-APIs
|
|
@@ -240,6 +240,19 @@ export declare class AzureBlobStorage extends BaseStorage {
|
|
|
240
240
|
quota: number | null;
|
|
241
241
|
details?: Record<string, any>;
|
|
242
242
|
}>;
|
|
243
|
+
/**
|
|
244
|
+
* Check if COW has been explicitly disabled via clear()
|
|
245
|
+
* v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
|
|
246
|
+
* @returns true if marker blob exists, false otherwise
|
|
247
|
+
* @protected
|
|
248
|
+
*/
|
|
249
|
+
protected checkClearMarker(): Promise<boolean>;
|
|
250
|
+
/**
|
|
251
|
+
* Create marker indicating COW has been explicitly disabled
|
|
252
|
+
* v5.10.4: Called by clear() to prevent COW reinitialization on new instances
|
|
253
|
+
* @protected
|
|
254
|
+
*/
|
|
255
|
+
protected createClearMarker(): Promise<void>;
|
|
243
256
|
/**
|
|
244
257
|
* Save statistics data to storage
|
|
245
258
|
*/
|
|
@@ -866,6 +866,11 @@ export class AzureBlobStorage extends BaseStorage {
|
|
|
866
866
|
this.blobStorage = undefined;
|
|
867
867
|
this.commitLog = undefined;
|
|
868
868
|
this.cowEnabled = false;
|
|
869
|
+
// v5.10.4: Create persistent marker blob (CRITICAL FIX)
|
|
870
|
+
// Bug: cowEnabled = false only affects current instance, not future instances
|
|
871
|
+
// Fix: Create marker blob that persists across instance restarts
|
|
872
|
+
// When new instance calls initializeCOW(), it checks for this marker
|
|
873
|
+
await this.createClearMarker();
|
|
869
874
|
// Clear caches
|
|
870
875
|
this.nounCacheManager.clear();
|
|
871
876
|
this.verbCacheManager.clear();
|
|
@@ -908,6 +913,45 @@ export class AzureBlobStorage extends BaseStorage {
|
|
|
908
913
|
};
|
|
909
914
|
}
|
|
910
915
|
}
|
|
916
|
+
/**
|
|
917
|
+
* Check if COW has been explicitly disabled via clear()
|
|
918
|
+
* v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
|
|
919
|
+
* @returns true if marker blob exists, false otherwise
|
|
920
|
+
* @protected
|
|
921
|
+
*/
|
|
922
|
+
async checkClearMarker() {
|
|
923
|
+
await this.ensureInitialized();
|
|
924
|
+
try {
|
|
925
|
+
const markerPath = `${this.systemPrefix}cow-disabled`;
|
|
926
|
+
const blockBlobClient = this.containerClient.getBlockBlobClient(markerPath);
|
|
927
|
+
const exists = await blockBlobClient.exists();
|
|
928
|
+
return exists;
|
|
929
|
+
}
|
|
930
|
+
catch (error) {
|
|
931
|
+
this.logger.warn('AzureBlobStorage.checkClearMarker: Error checking marker', error);
|
|
932
|
+
return false;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* Create marker indicating COW has been explicitly disabled
|
|
937
|
+
* v5.10.4: Called by clear() to prevent COW reinitialization on new instances
|
|
938
|
+
* @protected
|
|
939
|
+
*/
|
|
940
|
+
async createClearMarker() {
|
|
941
|
+
await this.ensureInitialized();
|
|
942
|
+
try {
|
|
943
|
+
const markerPath = `${this.systemPrefix}cow-disabled`;
|
|
944
|
+
const blockBlobClient = this.containerClient.getBlockBlobClient(markerPath);
|
|
945
|
+
// Create empty marker blob
|
|
946
|
+
await blockBlobClient.upload(Buffer.from(''), 0, {
|
|
947
|
+
blobHTTPHeaders: { blobContentType: 'text/plain' }
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
catch (error) {
|
|
951
|
+
this.logger.error('AzureBlobStorage.createClearMarker: Failed to create marker blob', error);
|
|
952
|
+
// Don't throw - marker creation failure shouldn't break clear()
|
|
953
|
+
}
|
|
954
|
+
}
|
|
911
955
|
/**
|
|
912
956
|
* Save statistics data to storage
|
|
913
957
|
*/
|
|
@@ -171,6 +171,19 @@ export declare class FileSystemStorage extends BaseStorage {
|
|
|
171
171
|
* Provides progress tracking, backup options, and instance name confirmation
|
|
172
172
|
*/
|
|
173
173
|
clearEnhanced(options?: import('../enhancedClearOperations.js').ClearOptions): Promise<import('../enhancedClearOperations.js').ClearResult>;
|
|
174
|
+
/**
|
|
175
|
+
* Check if COW has been explicitly disabled via clear()
|
|
176
|
+
* v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
|
|
177
|
+
* @returns true if marker file exists, false otherwise
|
|
178
|
+
* @protected
|
|
179
|
+
*/
|
|
180
|
+
protected checkClearMarker(): Promise<boolean>;
|
|
181
|
+
/**
|
|
182
|
+
* Create marker indicating COW has been explicitly disabled
|
|
183
|
+
* v5.10.4: Called by clear() to prevent COW reinitialization on new instances
|
|
184
|
+
* @protected
|
|
185
|
+
*/
|
|
186
|
+
protected createClearMarker(): Promise<void>;
|
|
174
187
|
/**
|
|
175
188
|
* Get information about storage usage and capacity
|
|
176
189
|
*/
|
|
@@ -859,16 +859,13 @@ export class FileSystemStorage extends BaseStorage {
|
|
|
859
859
|
}
|
|
860
860
|
}
|
|
861
861
|
};
|
|
862
|
-
//
|
|
863
|
-
|
|
864
|
-
//
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
await removeDirectoryContents(this.nounMetadataDir);
|
|
870
|
-
// Remove all files in the verb metadata directory
|
|
871
|
-
await removeDirectoryContents(this.verbMetadataDir);
|
|
862
|
+
// v5.10.4: Clear the entire branches/ directory (branch-based storage)
|
|
863
|
+
// Bug fix: Data is stored in branches/main/entities/, not just entities/
|
|
864
|
+
// The branch-based structure was introduced for COW support
|
|
865
|
+
const branchesDir = path.join(this.rootDir, 'branches');
|
|
866
|
+
if (await this.directoryExists(branchesDir)) {
|
|
867
|
+
await removeDirectoryContents(branchesDir);
|
|
868
|
+
}
|
|
872
869
|
// Remove all files in both system directories
|
|
873
870
|
await removeDirectoryContents(this.systemDir);
|
|
874
871
|
if (await this.directoryExists(this.indexDir)) {
|
|
@@ -888,6 +885,11 @@ export class FileSystemStorage extends BaseStorage {
|
|
|
888
885
|
this.blobStorage = undefined;
|
|
889
886
|
this.commitLog = undefined;
|
|
890
887
|
this.cowEnabled = false;
|
|
888
|
+
// v5.10.4: Create persistent marker file (CRITICAL FIX)
|
|
889
|
+
// Bug: cowEnabled = false only affects current instance, not future instances
|
|
890
|
+
// Fix: Create marker file that persists across instance restarts
|
|
891
|
+
// When new instance calls initializeCOW(), it checks for this marker
|
|
892
|
+
await this.createClearMarker();
|
|
891
893
|
}
|
|
892
894
|
// Clear the statistics cache
|
|
893
895
|
this.statisticsCache = null;
|
|
@@ -915,6 +917,47 @@ export class FileSystemStorage extends BaseStorage {
|
|
|
915
917
|
}
|
|
916
918
|
return result;
|
|
917
919
|
}
|
|
920
|
+
/**
|
|
921
|
+
* Check if COW has been explicitly disabled via clear()
|
|
922
|
+
* v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
|
|
923
|
+
* @returns true if marker file exists, false otherwise
|
|
924
|
+
* @protected
|
|
925
|
+
*/
|
|
926
|
+
async checkClearMarker() {
|
|
927
|
+
// Check if fs module is available
|
|
928
|
+
if (!fs || !fs.promises) {
|
|
929
|
+
return false;
|
|
930
|
+
}
|
|
931
|
+
try {
|
|
932
|
+
const markerPath = path.join(this.systemDir, 'cow-disabled');
|
|
933
|
+
await fs.promises.access(markerPath, fs.constants.F_OK);
|
|
934
|
+
return true; // Marker exists
|
|
935
|
+
}
|
|
936
|
+
catch (error) {
|
|
937
|
+
return false; // Marker doesn't exist (ENOENT) or can't be accessed
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
/**
|
|
941
|
+
* Create marker indicating COW has been explicitly disabled
|
|
942
|
+
* v5.10.4: Called by clear() to prevent COW reinitialization on new instances
|
|
943
|
+
* @protected
|
|
944
|
+
*/
|
|
945
|
+
async createClearMarker() {
|
|
946
|
+
// Check if fs module is available
|
|
947
|
+
if (!fs || !fs.promises) {
|
|
948
|
+
console.warn('FileSystemStorage.createClearMarker: fs module not available, skipping marker creation');
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
951
|
+
try {
|
|
952
|
+
const markerPath = path.join(this.systemDir, 'cow-disabled');
|
|
953
|
+
// Create empty marker file
|
|
954
|
+
await fs.promises.writeFile(markerPath, '', 'utf8');
|
|
955
|
+
}
|
|
956
|
+
catch (error) {
|
|
957
|
+
console.error('FileSystemStorage.createClearMarker: Failed to create marker file', error);
|
|
958
|
+
// Don't throw - marker creation failure shouldn't break clear()
|
|
959
|
+
}
|
|
960
|
+
}
|
|
918
961
|
/**
|
|
919
962
|
* Get information about storage usage and capacity
|
|
920
963
|
*/
|
|
@@ -228,6 +228,19 @@ export declare class GcsStorage extends BaseStorage {
|
|
|
228
228
|
quota: number | null;
|
|
229
229
|
details?: Record<string, any>;
|
|
230
230
|
}>;
|
|
231
|
+
/**
|
|
232
|
+
* Check if COW has been explicitly disabled via clear()
|
|
233
|
+
* v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
|
|
234
|
+
* @returns true if marker object exists, false otherwise
|
|
235
|
+
* @protected
|
|
236
|
+
*/
|
|
237
|
+
protected checkClearMarker(): Promise<boolean>;
|
|
238
|
+
/**
|
|
239
|
+
* Create marker indicating COW has been explicitly disabled
|
|
240
|
+
* v5.10.4: Called by clear() to prevent COW reinitialization on new instances
|
|
241
|
+
* @protected
|
|
242
|
+
*/
|
|
243
|
+
protected createClearMarker(): Promise<void>;
|
|
231
244
|
/**
|
|
232
245
|
* Save statistics data to storage
|
|
233
246
|
*/
|
|
@@ -789,6 +789,11 @@ export class GcsStorage extends BaseStorage {
|
|
|
789
789
|
this.blobStorage = undefined;
|
|
790
790
|
this.commitLog = undefined;
|
|
791
791
|
this.cowEnabled = false;
|
|
792
|
+
// v5.10.4: Create persistent marker object (CRITICAL FIX)
|
|
793
|
+
// Bug: cowEnabled = false only affects current instance, not future instances
|
|
794
|
+
// Fix: Create marker object that persists across instance restarts
|
|
795
|
+
// When new instance calls initializeCOW(), it checks for this marker
|
|
796
|
+
await this.createClearMarker();
|
|
792
797
|
// Clear caches
|
|
793
798
|
this.nounCacheManager.clear();
|
|
794
799
|
this.verbCacheManager.clear();
|
|
@@ -834,6 +839,43 @@ export class GcsStorage extends BaseStorage {
|
|
|
834
839
|
};
|
|
835
840
|
}
|
|
836
841
|
}
|
|
842
|
+
/**
|
|
843
|
+
* Check if COW has been explicitly disabled via clear()
|
|
844
|
+
* v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
|
|
845
|
+
* @returns true if marker object exists, false otherwise
|
|
846
|
+
* @protected
|
|
847
|
+
*/
|
|
848
|
+
async checkClearMarker() {
|
|
849
|
+
await this.ensureInitialized();
|
|
850
|
+
try {
|
|
851
|
+
const markerPath = `${this.systemPrefix}cow-disabled`;
|
|
852
|
+
const file = this.bucket.file(markerPath);
|
|
853
|
+
const [exists] = await file.exists();
|
|
854
|
+
return exists;
|
|
855
|
+
}
|
|
856
|
+
catch (error) {
|
|
857
|
+
this.logger.warn('GCSStorage.checkClearMarker: Error checking marker', error);
|
|
858
|
+
return false;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* Create marker indicating COW has been explicitly disabled
|
|
863
|
+
* v5.10.4: Called by clear() to prevent COW reinitialization on new instances
|
|
864
|
+
* @protected
|
|
865
|
+
*/
|
|
866
|
+
async createClearMarker() {
|
|
867
|
+
await this.ensureInitialized();
|
|
868
|
+
try {
|
|
869
|
+
const markerPath = `${this.systemPrefix}cow-disabled`;
|
|
870
|
+
const file = this.bucket.file(markerPath);
|
|
871
|
+
// Create empty marker object
|
|
872
|
+
await file.save('', { contentType: 'text/plain' });
|
|
873
|
+
}
|
|
874
|
+
catch (error) {
|
|
875
|
+
this.logger.error('GCSStorage.createClearMarker: Failed to create marker object', error);
|
|
876
|
+
// Don't throw - marker creation failure shouldn't break clear()
|
|
877
|
+
}
|
|
878
|
+
}
|
|
837
879
|
/**
|
|
838
880
|
* Save statistics data to storage
|
|
839
881
|
*/
|
|
@@ -101,6 +101,19 @@ export declare class HistoricalStorageAdapter extends BaseStorage {
|
|
|
101
101
|
quota: number | null;
|
|
102
102
|
details?: Record<string, any>;
|
|
103
103
|
}>;
|
|
104
|
+
/**
|
|
105
|
+
* Check if COW has been explicitly disabled via clear()
|
|
106
|
+
* v5.10.4: No-op for HistoricalStorageAdapter (read-only, doesn't manage COW)
|
|
107
|
+
* @returns Always false (read-only adapter doesn't manage COW state)
|
|
108
|
+
* @protected
|
|
109
|
+
*/
|
|
110
|
+
protected checkClearMarker(): Promise<boolean>;
|
|
111
|
+
/**
|
|
112
|
+
* Create marker indicating COW has been explicitly disabled
|
|
113
|
+
* v5.10.4: No-op for HistoricalStorageAdapter (read-only)
|
|
114
|
+
* @protected
|
|
115
|
+
*/
|
|
116
|
+
protected createClearMarker(): Promise<void>;
|
|
104
117
|
/**
|
|
105
118
|
* WRITE BLOCKED: Historical storage is read-only
|
|
106
119
|
*/
|
|
@@ -226,6 +226,23 @@ export class HistoricalStorageAdapter extends BaseStorage {
|
|
|
226
226
|
}
|
|
227
227
|
};
|
|
228
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* Check if COW has been explicitly disabled via clear()
|
|
231
|
+
* v5.10.4: No-op for HistoricalStorageAdapter (read-only, doesn't manage COW)
|
|
232
|
+
* @returns Always false (read-only adapter doesn't manage COW state)
|
|
233
|
+
* @protected
|
|
234
|
+
*/
|
|
235
|
+
async checkClearMarker() {
|
|
236
|
+
return false; // Read-only adapter - COW state managed by underlying storage
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Create marker indicating COW has been explicitly disabled
|
|
240
|
+
* v5.10.4: No-op for HistoricalStorageAdapter (read-only)
|
|
241
|
+
* @protected
|
|
242
|
+
*/
|
|
243
|
+
async createClearMarker() {
|
|
244
|
+
// No-op: HistoricalStorageAdapter is read-only, doesn't create markers
|
|
245
|
+
}
|
|
229
246
|
// ============= Override Write Methods (Read-Only) =============
|
|
230
247
|
/**
|
|
231
248
|
* WRITE BLOCKED: Historical storage is read-only
|
|
@@ -79,6 +79,19 @@ export declare class MemoryStorage extends BaseStorage {
|
|
|
79
79
|
quota: number | null;
|
|
80
80
|
details?: Record<string, any>;
|
|
81
81
|
}>;
|
|
82
|
+
/**
|
|
83
|
+
* Check if COW has been explicitly disabled via clear()
|
|
84
|
+
* v5.10.4: No-op for MemoryStorage (doesn't persist)
|
|
85
|
+
* @returns Always false (marker doesn't persist in memory)
|
|
86
|
+
* @protected
|
|
87
|
+
*/
|
|
88
|
+
protected checkClearMarker(): Promise<boolean>;
|
|
89
|
+
/**
|
|
90
|
+
* Create marker indicating COW has been explicitly disabled
|
|
91
|
+
* v5.10.4: No-op for MemoryStorage (doesn't persist)
|
|
92
|
+
* @protected
|
|
93
|
+
*/
|
|
94
|
+
protected createClearMarker(): Promise<void>;
|
|
82
95
|
/**
|
|
83
96
|
* Save statistics data to storage
|
|
84
97
|
* @param statistics The statistics data to save
|
|
@@ -158,6 +158,24 @@ export class MemoryStorage extends BaseStorage {
|
|
|
158
158
|
}
|
|
159
159
|
};
|
|
160
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* Check if COW has been explicitly disabled via clear()
|
|
163
|
+
* v5.10.4: No-op for MemoryStorage (doesn't persist)
|
|
164
|
+
* @returns Always false (marker doesn't persist in memory)
|
|
165
|
+
* @protected
|
|
166
|
+
*/
|
|
167
|
+
async checkClearMarker() {
|
|
168
|
+
return false; // MemoryStorage doesn't persist - marker doesn't survive restart
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Create marker indicating COW has been explicitly disabled
|
|
172
|
+
* v5.10.4: No-op for MemoryStorage (doesn't persist)
|
|
173
|
+
* @protected
|
|
174
|
+
*/
|
|
175
|
+
async createClearMarker() {
|
|
176
|
+
// No-op: MemoryStorage doesn't persist, so marker is not needed
|
|
177
|
+
// clear() in memory already resets all state, no marker survives restart
|
|
178
|
+
}
|
|
161
179
|
/**
|
|
162
180
|
* Save statistics data to storage
|
|
163
181
|
* @param statistics The statistics data to save
|
|
@@ -94,6 +94,19 @@ export declare class OPFSStorage extends BaseStorage {
|
|
|
94
94
|
* Clear all data from storage
|
|
95
95
|
*/
|
|
96
96
|
clear(): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Check if COW has been explicitly disabled via clear()
|
|
99
|
+
* v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
|
|
100
|
+
* @returns true if marker file exists, false otherwise
|
|
101
|
+
* @protected
|
|
102
|
+
*/
|
|
103
|
+
protected checkClearMarker(): Promise<boolean>;
|
|
104
|
+
/**
|
|
105
|
+
* Create marker indicating COW has been explicitly disabled
|
|
106
|
+
* v5.10.4: Called by clear() to prevent COW reinitialization on new instances
|
|
107
|
+
* @protected
|
|
108
|
+
*/
|
|
109
|
+
protected createClearMarker(): Promise<void>;
|
|
97
110
|
private quotaWarningThreshold;
|
|
98
111
|
private quotaCriticalThreshold;
|
|
99
112
|
private lastQuotaCheck;
|
|
@@ -400,6 +400,11 @@ export class OPFSStorage extends BaseStorage {
|
|
|
400
400
|
this.blobStorage = undefined;
|
|
401
401
|
this.commitLog = undefined;
|
|
402
402
|
this.cowEnabled = false;
|
|
403
|
+
// v5.10.4: Create persistent marker file (CRITICAL FIX)
|
|
404
|
+
// Bug: cowEnabled = false only affects current instance, not future instances
|
|
405
|
+
// Fix: Create marker file that persists across instance restarts
|
|
406
|
+
// When new instance calls initializeCOW(), it checks for this marker
|
|
407
|
+
await this.createClearMarker();
|
|
403
408
|
}
|
|
404
409
|
catch (error) {
|
|
405
410
|
// Ignore if _cow directory doesn't exist (not all instances use COW)
|
|
@@ -418,6 +423,51 @@ export class OPFSStorage extends BaseStorage {
|
|
|
418
423
|
throw error;
|
|
419
424
|
}
|
|
420
425
|
}
|
|
426
|
+
/**
|
|
427
|
+
* Check if COW has been explicitly disabled via clear()
|
|
428
|
+
* v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
|
|
429
|
+
* @returns true if marker file exists, false otherwise
|
|
430
|
+
* @protected
|
|
431
|
+
*/
|
|
432
|
+
async checkClearMarker() {
|
|
433
|
+
await this.ensureInitialized();
|
|
434
|
+
try {
|
|
435
|
+
// Get system directory (may not exist yet)
|
|
436
|
+
const systemDir = await this.rootDir.getDirectoryHandle('system', { create: false });
|
|
437
|
+
// Try to get the marker file
|
|
438
|
+
await systemDir.getFileHandle('cow-disabled', { create: false });
|
|
439
|
+
return true; // Marker exists
|
|
440
|
+
}
|
|
441
|
+
catch (error) {
|
|
442
|
+
if (error.name === 'NotFoundError') {
|
|
443
|
+
return false; // Marker doesn't exist (or system dir doesn't exist)
|
|
444
|
+
}
|
|
445
|
+
// Other errors (permissions, etc.) - treat as marker not existing
|
|
446
|
+
console.warn('OPFSStorage.checkClearMarker: Error checking marker', error);
|
|
447
|
+
return false;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Create marker indicating COW has been explicitly disabled
|
|
452
|
+
* v5.10.4: Called by clear() to prevent COW reinitialization on new instances
|
|
453
|
+
* @protected
|
|
454
|
+
*/
|
|
455
|
+
async createClearMarker() {
|
|
456
|
+
await this.ensureInitialized();
|
|
457
|
+
try {
|
|
458
|
+
// Get or create system directory
|
|
459
|
+
const systemDir = await this.rootDir.getDirectoryHandle('system', { create: true });
|
|
460
|
+
// Create empty marker file
|
|
461
|
+
const fileHandle = await systemDir.getFileHandle('cow-disabled', { create: true });
|
|
462
|
+
const writable = await fileHandle.createWritable();
|
|
463
|
+
await writable.write(new Uint8Array(0)); // Empty file
|
|
464
|
+
await writable.close();
|
|
465
|
+
}
|
|
466
|
+
catch (error) {
|
|
467
|
+
console.error('OPFSStorage.createClearMarker: Failed to create marker file', error);
|
|
468
|
+
// Don't throw - marker creation failure shouldn't break clear()
|
|
469
|
+
}
|
|
470
|
+
}
|
|
421
471
|
/**
|
|
422
472
|
* Get information about storage usage and capacity
|
|
423
473
|
*/
|
|
@@ -200,5 +200,18 @@ export declare class R2Storage extends BaseStorage {
|
|
|
200
200
|
quota: number | null;
|
|
201
201
|
details?: Record<string, any>;
|
|
202
202
|
}>;
|
|
203
|
+
/**
|
|
204
|
+
* Check if COW has been explicitly disabled via clear()
|
|
205
|
+
* v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
|
|
206
|
+
* @returns true if marker object exists, false otherwise
|
|
207
|
+
* @protected
|
|
208
|
+
*/
|
|
209
|
+
protected checkClearMarker(): Promise<boolean>;
|
|
210
|
+
/**
|
|
211
|
+
* Create marker indicating COW has been explicitly disabled
|
|
212
|
+
* v5.10.4: Called by clear() to prevent COW reinitialization on new instances
|
|
213
|
+
* @protected
|
|
214
|
+
*/
|
|
215
|
+
protected createClearMarker(): Promise<void>;
|
|
203
216
|
}
|
|
204
217
|
export {};
|
|
@@ -787,6 +787,11 @@ export class R2Storage extends BaseStorage {
|
|
|
787
787
|
this.blobStorage = undefined;
|
|
788
788
|
this.commitLog = undefined;
|
|
789
789
|
this.cowEnabled = false;
|
|
790
|
+
// v5.10.4: Create persistent marker object (CRITICAL FIX)
|
|
791
|
+
// Bug: cowEnabled = false only affects current instance, not future instances
|
|
792
|
+
// Fix: Create marker object that persists across instance restarts
|
|
793
|
+
// When new instance calls initializeCOW(), it checks for this marker
|
|
794
|
+
await this.createClearMarker();
|
|
790
795
|
this.nounCacheManager.clear();
|
|
791
796
|
this.verbCacheManager.clear();
|
|
792
797
|
this.totalNounCount = 0;
|
|
@@ -813,5 +818,40 @@ export class R2Storage extends BaseStorage {
|
|
|
813
818
|
}
|
|
814
819
|
};
|
|
815
820
|
}
|
|
821
|
+
/**
|
|
822
|
+
* Check if COW has been explicitly disabled via clear()
|
|
823
|
+
* v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
|
|
824
|
+
* @returns true if marker object exists, false otherwise
|
|
825
|
+
* @protected
|
|
826
|
+
*/
|
|
827
|
+
async checkClearMarker() {
|
|
828
|
+
await this.ensureInitialized();
|
|
829
|
+
try {
|
|
830
|
+
const markerPath = `${this.systemPrefix}cow-disabled`;
|
|
831
|
+
const data = await this.readObjectFromPath(markerPath);
|
|
832
|
+
return data !== null; // Marker exists if we got any data
|
|
833
|
+
}
|
|
834
|
+
catch (error) {
|
|
835
|
+
prodLog.warn('R2Storage.checkClearMarker: Error checking marker', error);
|
|
836
|
+
return false;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
/**
|
|
840
|
+
* Create marker indicating COW has been explicitly disabled
|
|
841
|
+
* v5.10.4: Called by clear() to prevent COW reinitialization on new instances
|
|
842
|
+
* @protected
|
|
843
|
+
*/
|
|
844
|
+
async createClearMarker() {
|
|
845
|
+
await this.ensureInitialized();
|
|
846
|
+
try {
|
|
847
|
+
const markerPath = `${this.systemPrefix}cow-disabled`;
|
|
848
|
+
// Create empty marker object
|
|
849
|
+
await this.writeObjectToPath(markerPath, '');
|
|
850
|
+
}
|
|
851
|
+
catch (error) {
|
|
852
|
+
prodLog.error('R2Storage.createClearMarker: Failed to create marker object', error);
|
|
853
|
+
// Don't throw - marker creation failure shouldn't break clear()
|
|
854
|
+
}
|
|
855
|
+
}
|
|
816
856
|
}
|
|
817
857
|
//# sourceMappingURL=r2Storage.js.map
|
|
@@ -373,6 +373,19 @@ export declare class S3CompatibleStorage extends BaseStorage {
|
|
|
373
373
|
quota: number | null;
|
|
374
374
|
details?: Record<string, any>;
|
|
375
375
|
}>;
|
|
376
|
+
/**
|
|
377
|
+
* Check if COW has been explicitly disabled via clear()
|
|
378
|
+
* v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
|
|
379
|
+
* @returns true if marker object exists, false otherwise
|
|
380
|
+
* @protected
|
|
381
|
+
*/
|
|
382
|
+
protected checkClearMarker(): Promise<boolean>;
|
|
383
|
+
/**
|
|
384
|
+
* Create marker indicating COW has been explicitly disabled
|
|
385
|
+
* v5.10.4: Called by clear() to prevent COW reinitialization on new instances
|
|
386
|
+
* @protected
|
|
387
|
+
*/
|
|
388
|
+
protected createClearMarker(): Promise<void>;
|
|
376
389
|
protected statisticsBatchUpdateTimerId: NodeJS.Timeout | null;
|
|
377
390
|
protected statisticsModified: boolean;
|
|
378
391
|
protected lastStatisticsFlushTime: number;
|
|
@@ -1632,6 +1632,11 @@ export class S3CompatibleStorage extends BaseStorage {
|
|
|
1632
1632
|
this.blobStorage = undefined;
|
|
1633
1633
|
this.commitLog = undefined;
|
|
1634
1634
|
this.cowEnabled = false;
|
|
1635
|
+
// v5.10.4: Create persistent marker object (CRITICAL FIX)
|
|
1636
|
+
// Bug: cowEnabled = false only affects current instance, not future instances
|
|
1637
|
+
// Fix: Create marker object that persists across instance restarts
|
|
1638
|
+
// When new instance calls initializeCOW(), it checks for this marker
|
|
1639
|
+
await this.createClearMarker();
|
|
1635
1640
|
// Clear the statistics cache
|
|
1636
1641
|
this.statisticsCache = null;
|
|
1637
1642
|
this.statisticsModified = false;
|
|
@@ -1731,6 +1736,54 @@ export class S3CompatibleStorage extends BaseStorage {
|
|
|
1731
1736
|
};
|
|
1732
1737
|
}
|
|
1733
1738
|
}
|
|
1739
|
+
/**
|
|
1740
|
+
* Check if COW has been explicitly disabled via clear()
|
|
1741
|
+
* v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
|
|
1742
|
+
* @returns true if marker object exists, false otherwise
|
|
1743
|
+
* @protected
|
|
1744
|
+
*/
|
|
1745
|
+
async checkClearMarker() {
|
|
1746
|
+
await this.ensureInitialized();
|
|
1747
|
+
try {
|
|
1748
|
+
const { HeadObjectCommand } = await import('@aws-sdk/client-s3');
|
|
1749
|
+
const markerKey = `${this.systemPrefix}cow-disabled`;
|
|
1750
|
+
await this.s3Client.send(new HeadObjectCommand({
|
|
1751
|
+
Bucket: this.bucketName,
|
|
1752
|
+
Key: markerKey
|
|
1753
|
+
}));
|
|
1754
|
+
return true; // Marker exists
|
|
1755
|
+
}
|
|
1756
|
+
catch (error) {
|
|
1757
|
+
if (error.name === 'NotFound' || error.$metadata?.httpStatusCode === 404) {
|
|
1758
|
+
return false; // Marker doesn't exist
|
|
1759
|
+
}
|
|
1760
|
+
prodLog.warn('S3CompatibleStorage.checkClearMarker: Error checking marker', error);
|
|
1761
|
+
return false;
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
/**
|
|
1765
|
+
* Create marker indicating COW has been explicitly disabled
|
|
1766
|
+
* v5.10.4: Called by clear() to prevent COW reinitialization on new instances
|
|
1767
|
+
* @protected
|
|
1768
|
+
*/
|
|
1769
|
+
async createClearMarker() {
|
|
1770
|
+
await this.ensureInitialized();
|
|
1771
|
+
try {
|
|
1772
|
+
const { PutObjectCommand } = await import('@aws-sdk/client-s3');
|
|
1773
|
+
const markerKey = `${this.systemPrefix}cow-disabled`;
|
|
1774
|
+
// Create empty marker object
|
|
1775
|
+
await this.s3Client.send(new PutObjectCommand({
|
|
1776
|
+
Bucket: this.bucketName,
|
|
1777
|
+
Key: markerKey,
|
|
1778
|
+
Body: Buffer.from(''),
|
|
1779
|
+
ContentType: 'text/plain'
|
|
1780
|
+
}));
|
|
1781
|
+
}
|
|
1782
|
+
catch (error) {
|
|
1783
|
+
prodLog.error('S3CompatibleStorage.createClearMarker: Failed to create marker object', error);
|
|
1784
|
+
// Don't throw - marker creation failure shouldn't break clear()
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1734
1787
|
/**
|
|
1735
1788
|
* Get the statistics key for a specific date
|
|
1736
1789
|
* @param date The date to get the key for
|
|
@@ -327,6 +327,21 @@ export declare abstract class BaseStorage extends BaseStorageAdapter {
|
|
|
327
327
|
* This method should be implemented by each specific adapter
|
|
328
328
|
*/
|
|
329
329
|
abstract clear(): Promise<void>;
|
|
330
|
+
/**
|
|
331
|
+
* Check if COW has been explicitly disabled via clear()
|
|
332
|
+
* v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
|
|
333
|
+
* Each adapter checks for a marker file/object (e.g., "_system/cow-disabled")
|
|
334
|
+
* @returns true if COW was disabled by clear(), false otherwise
|
|
335
|
+
* @protected
|
|
336
|
+
*/
|
|
337
|
+
protected abstract checkClearMarker(): Promise<boolean>;
|
|
338
|
+
/**
|
|
339
|
+
* Create marker indicating COW has been explicitly disabled
|
|
340
|
+
* v5.10.4: Called by clear() to prevent COW reinitialization on new instances
|
|
341
|
+
* Each adapter creates a marker file/object (e.g., "_system/cow-disabled")
|
|
342
|
+
* @protected
|
|
343
|
+
*/
|
|
344
|
+
protected abstract createClearMarker(): Promise<void>;
|
|
330
345
|
/**
|
|
331
346
|
* Get information about storage usage and capacity
|
|
332
347
|
* This method should be implemented by each specific adapter
|
|
@@ -212,6 +212,14 @@ export class BaseStorage extends BaseStorageAdapter {
|
|
|
212
212
|
* @returns Promise that resolves when COW is initialized
|
|
213
213
|
*/
|
|
214
214
|
async initializeCOW(options) {
|
|
215
|
+
// v5.10.4: Check for persistent marker file (CRITICAL FIX)
|
|
216
|
+
// Bug: Setting cowEnabled = false on OLD instance doesn't affect NEW instances
|
|
217
|
+
// Fix: Check storage for persistent marker created by clear()
|
|
218
|
+
// If marker exists, COW was explicitly disabled and should NOT reinitialize
|
|
219
|
+
const markerExists = await this.checkClearMarker();
|
|
220
|
+
if (markerExists) {
|
|
221
|
+
return; // COW was disabled by clear() - don't recreate _cow/ directory
|
|
222
|
+
}
|
|
215
223
|
// v5.6.1: If COW was explicitly disabled (e.g., via clear()), don't reinitialize
|
|
216
224
|
// This prevents automatic recreation of COW data after clear() operations
|
|
217
225
|
if (this.cowEnabled === false) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soulcraft/brainy",
|
|
3
|
-
"version": "5.10.
|
|
3
|
+
"version": "5.10.4",
|
|
4
4
|
"description": "Universal Knowledge Protocol™ - World's first Triple Intelligence database unifying vector, graph, and document search in one API. Stage 3 CANONICAL: 42 nouns × 127 verbs covering 96-97% of all human knowledge.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|