@soulcraft/brainy 6.4.0 → 6.5.0
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.
|
@@ -285,8 +285,22 @@ export declare class VirtualFileSystem implements IVirtualFileSystem {
|
|
|
285
285
|
type: string;
|
|
286
286
|
metadata: any;
|
|
287
287
|
}>>;
|
|
288
|
+
/**
|
|
289
|
+
* Sort bulk operations to prevent race conditions
|
|
290
|
+
*
|
|
291
|
+
* Strategy:
|
|
292
|
+
* 1. mkdir operations first, sorted by path depth (shallowest first)
|
|
293
|
+
* 2. Other operations (write, delete, update) after, in original order
|
|
294
|
+
*
|
|
295
|
+
* This ensures parent directories exist before files are written,
|
|
296
|
+
* preventing duplicate entity creation from concurrent mkdir calls.
|
|
297
|
+
*/
|
|
298
|
+
private sortBulkOperations;
|
|
288
299
|
/**
|
|
289
300
|
* Bulk write operations for performance
|
|
301
|
+
*
|
|
302
|
+
* v6.5.0: Prevents race condition by processing mkdir operations
|
|
303
|
+
* sequentially before parallel batch processing of other operations.
|
|
290
304
|
*/
|
|
291
305
|
bulkWrite(operations: Array<{
|
|
292
306
|
type: 'write' | 'delete' | 'mkdir' | 'update';
|
|
@@ -1930,8 +1930,40 @@ export class VirtualFileSystem {
|
|
|
1930
1930
|
metadata: result.entity?.metadata || {}
|
|
1931
1931
|
}));
|
|
1932
1932
|
}
|
|
1933
|
+
/**
|
|
1934
|
+
* Sort bulk operations to prevent race conditions
|
|
1935
|
+
*
|
|
1936
|
+
* Strategy:
|
|
1937
|
+
* 1. mkdir operations first, sorted by path depth (shallowest first)
|
|
1938
|
+
* 2. Other operations (write, delete, update) after, in original order
|
|
1939
|
+
*
|
|
1940
|
+
* This ensures parent directories exist before files are written,
|
|
1941
|
+
* preventing duplicate entity creation from concurrent mkdir calls.
|
|
1942
|
+
*/
|
|
1943
|
+
sortBulkOperations(operations) {
|
|
1944
|
+
const mkdirOps = [];
|
|
1945
|
+
const otherOps = [];
|
|
1946
|
+
for (const op of operations) {
|
|
1947
|
+
if (op.type === 'mkdir') {
|
|
1948
|
+
mkdirOps.push(op);
|
|
1949
|
+
}
|
|
1950
|
+
else {
|
|
1951
|
+
otherOps.push(op);
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
// Sort mkdir by path depth (shallowest first)
|
|
1955
|
+
mkdirOps.sort((a, b) => {
|
|
1956
|
+
const depthA = (a.path.match(/\//g) || []).length;
|
|
1957
|
+
const depthB = (b.path.match(/\//g) || []).length;
|
|
1958
|
+
return depthA !== depthB ? depthA - depthB : a.path.localeCompare(b.path);
|
|
1959
|
+
});
|
|
1960
|
+
return [...mkdirOps, ...otherOps];
|
|
1961
|
+
}
|
|
1933
1962
|
/**
|
|
1934
1963
|
* Bulk write operations for performance
|
|
1964
|
+
*
|
|
1965
|
+
* v6.5.0: Prevents race condition by processing mkdir operations
|
|
1966
|
+
* sequentially before parallel batch processing of other operations.
|
|
1935
1967
|
*/
|
|
1936
1968
|
async bulkWrite(operations) {
|
|
1937
1969
|
await this.ensureInitialized();
|
|
@@ -1939,10 +1971,31 @@ export class VirtualFileSystem {
|
|
|
1939
1971
|
successful: 0,
|
|
1940
1972
|
failed: []
|
|
1941
1973
|
};
|
|
1942
|
-
//
|
|
1974
|
+
// Sort operations: mkdirs first (by depth), then others
|
|
1975
|
+
const sortedOps = this.sortBulkOperations(operations);
|
|
1976
|
+
// Separate mkdir operations for sequential processing
|
|
1977
|
+
const mkdirOps = sortedOps.filter(op => op.type === 'mkdir');
|
|
1978
|
+
const otherOps = sortedOps.filter(op => op.type !== 'mkdir');
|
|
1979
|
+
// Phase 1: Process mkdir operations SEQUENTIALLY
|
|
1980
|
+
// This prevents the race condition where parallel mkdir calls
|
|
1981
|
+
// create duplicate directory entities due to mutex timing window
|
|
1982
|
+
for (const op of mkdirOps) {
|
|
1983
|
+
try {
|
|
1984
|
+
await this.mkdir(op.path, op.options);
|
|
1985
|
+
result.successful++;
|
|
1986
|
+
}
|
|
1987
|
+
catch (error) {
|
|
1988
|
+
result.failed.push({
|
|
1989
|
+
operation: op,
|
|
1990
|
+
error: error.message || 'Unknown error'
|
|
1991
|
+
});
|
|
1992
|
+
}
|
|
1993
|
+
}
|
|
1994
|
+
// Phase 2: Process other operations in parallel batches
|
|
1995
|
+
// These can safely run in parallel since parent directories now exist
|
|
1943
1996
|
const batchSize = 10;
|
|
1944
|
-
for (let i = 0; i <
|
|
1945
|
-
const batch =
|
|
1997
|
+
for (let i = 0; i < otherOps.length; i += batchSize) {
|
|
1998
|
+
const batch = otherOps.slice(i, i + batchSize);
|
|
1946
1999
|
// Process batch in parallel
|
|
1947
2000
|
const promises = batch.map(async (op) => {
|
|
1948
2001
|
try {
|
|
@@ -1953,9 +2006,6 @@ export class VirtualFileSystem {
|
|
|
1953
2006
|
case 'delete':
|
|
1954
2007
|
await this.unlink(op.path);
|
|
1955
2008
|
break;
|
|
1956
|
-
case 'mkdir':
|
|
1957
|
-
await this.mkdir(op.path, op.options);
|
|
1958
|
-
break;
|
|
1959
2009
|
case 'update': {
|
|
1960
2010
|
// Update only metadata without changing content
|
|
1961
2011
|
const entityId = await this.pathResolver.resolve(op.path);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soulcraft/brainy",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.5.0",
|
|
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",
|