document-dataply 0.0.14-alpha.1 → 0.0.14-alpha.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/cjs/index.js +196 -135
- package/dist/types/core/AnalysisManager.d.ts +2 -2
- package/dist/types/core/IndexManager.d.ts +2 -2
- package/dist/types/core/MetadataManager.d.ts +2 -2
- package/dist/types/core/MutationManager.d.ts +2 -2
- package/dist/types/core/QueryManager.d.ts +2 -2
- package/dist/types/core/document.d.ts +14 -0
- package/dist/types/core/documentAPI.d.ts +14 -0
- package/dist/types/utils/{DeadlineChunker.d.ts → eventLoopManager.d.ts} +1 -0
- package/package.json +2 -2
package/dist/cjs/index.js
CHANGED
|
@@ -82,6 +82,8 @@ var require_cjs = __commonJS({
|
|
|
82
82
|
IndexPageManager: () => IndexPageManager,
|
|
83
83
|
InvertedWeakMap: () => InvertedWeakMap,
|
|
84
84
|
LRUMap: () => LRUMap2,
|
|
85
|
+
Logger: () => Logger2,
|
|
86
|
+
LoggerManager: () => LoggerManager,
|
|
85
87
|
MVCCStrategy: () => MVCCStrategy2,
|
|
86
88
|
MVCCTransaction: () => MVCCTransaction2,
|
|
87
89
|
MetadataPageManager: () => MetadataPageManager,
|
|
@@ -476,11 +478,7 @@ var require_cjs = __commonJS({
|
|
|
476
478
|
*/
|
|
477
479
|
rollback() {
|
|
478
480
|
const { created, updated, deleted } = this.getResultEntries();
|
|
479
|
-
this.
|
|
480
|
-
this.deleteBuffer.clear();
|
|
481
|
-
this.createdKeys.clear();
|
|
482
|
-
this.deletedValues.clear();
|
|
483
|
-
this.originallyExisted.clear();
|
|
481
|
+
this._cleanupAll();
|
|
484
482
|
this.committed = true;
|
|
485
483
|
if (this.root !== this) {
|
|
486
484
|
this.root.activeTransactions.delete(this);
|
|
@@ -516,6 +514,19 @@ var require_cjs = __commonJS({
|
|
|
516
514
|
}
|
|
517
515
|
return Array.from(conflicts);
|
|
518
516
|
}
|
|
517
|
+
/**
|
|
518
|
+
* Cleans up all buffers and history.
|
|
519
|
+
* This method is called by the commit method.
|
|
520
|
+
*/
|
|
521
|
+
_cleanupAll() {
|
|
522
|
+
this.writeBuffer.clear();
|
|
523
|
+
this.deleteBuffer.clear();
|
|
524
|
+
this.createdKeys.clear();
|
|
525
|
+
this.deletedValues.clear();
|
|
526
|
+
this.originallyExisted.clear();
|
|
527
|
+
this.keyVersions.clear();
|
|
528
|
+
this.bufferHistory.clear();
|
|
529
|
+
}
|
|
519
530
|
/**
|
|
520
531
|
* Cleans up both deletedCache and versionIndex based on minActiveVersion.
|
|
521
532
|
* Root transactions call this after commit to reclaim memory.
|
|
@@ -707,6 +718,7 @@ var require_cjs = __commonJS({
|
|
|
707
718
|
if (this.parent) {
|
|
708
719
|
const failure = this.parent._merge(this);
|
|
709
720
|
if (failure) {
|
|
721
|
+
this.rollback();
|
|
710
722
|
return {
|
|
711
723
|
label,
|
|
712
724
|
success: false,
|
|
@@ -717,11 +729,13 @@ var require_cjs = __commonJS({
|
|
|
717
729
|
deleted
|
|
718
730
|
};
|
|
719
731
|
}
|
|
732
|
+
this._cleanupAll();
|
|
720
733
|
this.committed = true;
|
|
721
734
|
} else {
|
|
722
735
|
if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
|
|
723
736
|
const failure = this._merge(this);
|
|
724
737
|
if (failure) {
|
|
738
|
+
this.rollback();
|
|
725
739
|
return {
|
|
726
740
|
label,
|
|
727
741
|
success: false,
|
|
@@ -732,13 +746,7 @@ var require_cjs = __commonJS({
|
|
|
732
746
|
deleted: []
|
|
733
747
|
};
|
|
734
748
|
}
|
|
735
|
-
this.
|
|
736
|
-
this.deleteBuffer.clear();
|
|
737
|
-
this.createdKeys.clear();
|
|
738
|
-
this.deletedValues.clear();
|
|
739
|
-
this.originallyExisted.clear();
|
|
740
|
-
this.keyVersions.clear();
|
|
741
|
-
this.bufferHistory.clear();
|
|
749
|
+
this._cleanupAll();
|
|
742
750
|
this.localVersion = 0;
|
|
743
751
|
this.snapshotVersion = this.version;
|
|
744
752
|
}
|
|
@@ -1372,6 +1380,7 @@ var require_cjs = __commonJS({
|
|
|
1372
1380
|
if (this.parent) {
|
|
1373
1381
|
const failure = await this.parent._merge(this);
|
|
1374
1382
|
if (failure) {
|
|
1383
|
+
this.rollback();
|
|
1375
1384
|
return {
|
|
1376
1385
|
label,
|
|
1377
1386
|
success: false,
|
|
@@ -1382,11 +1391,13 @@ var require_cjs = __commonJS({
|
|
|
1382
1391
|
deleted
|
|
1383
1392
|
};
|
|
1384
1393
|
}
|
|
1394
|
+
this._cleanupAll();
|
|
1385
1395
|
this.committed = true;
|
|
1386
1396
|
} else {
|
|
1387
1397
|
if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
|
|
1388
1398
|
const failure = await this._merge(this);
|
|
1389
1399
|
if (failure) {
|
|
1400
|
+
this.rollback();
|
|
1390
1401
|
return {
|
|
1391
1402
|
label,
|
|
1392
1403
|
success: false,
|
|
@@ -1397,13 +1408,7 @@ var require_cjs = __commonJS({
|
|
|
1397
1408
|
deleted: []
|
|
1398
1409
|
};
|
|
1399
1410
|
}
|
|
1400
|
-
this.
|
|
1401
|
-
this.deleteBuffer.clear();
|
|
1402
|
-
this.createdKeys.clear();
|
|
1403
|
-
this.deletedValues.clear();
|
|
1404
|
-
this.originallyExisted.clear();
|
|
1405
|
-
this.keyVersions.clear();
|
|
1406
|
-
this.bufferHistory.clear();
|
|
1411
|
+
this._cleanupAll();
|
|
1407
1412
|
this.localVersion = 0;
|
|
1408
1413
|
this.snapshotVersion = this.version;
|
|
1409
1414
|
}
|
|
@@ -2958,8 +2963,12 @@ var require_cjs = __commonJS({
|
|
|
2958
2963
|
result = this.rootTx.commit(label);
|
|
2959
2964
|
if (result.success) {
|
|
2960
2965
|
this.rootTx.rootId = this.rootId;
|
|
2966
|
+
} else {
|
|
2967
|
+
this.mvcc.rollback();
|
|
2961
2968
|
}
|
|
2962
2969
|
}
|
|
2970
|
+
} else {
|
|
2971
|
+
this.mvcc.rollback();
|
|
2963
2972
|
}
|
|
2964
2973
|
return result;
|
|
2965
2974
|
}
|
|
@@ -4160,8 +4169,12 @@ var require_cjs = __commonJS({
|
|
|
4160
4169
|
result = await this.rootTx.commit(label);
|
|
4161
4170
|
if (result.success) {
|
|
4162
4171
|
this.rootTx.rootId = this.rootId;
|
|
4172
|
+
} else {
|
|
4173
|
+
this.mvcc.rollback();
|
|
4163
4174
|
}
|
|
4164
4175
|
}
|
|
4176
|
+
} else {
|
|
4177
|
+
this.mvcc.rollback();
|
|
4165
4178
|
}
|
|
4166
4179
|
return result;
|
|
4167
4180
|
}
|
|
@@ -5426,11 +5439,7 @@ var require_cjs = __commonJS({
|
|
|
5426
5439
|
*/
|
|
5427
5440
|
rollback() {
|
|
5428
5441
|
const { created, updated, deleted } = this.getResultEntries();
|
|
5429
|
-
this.
|
|
5430
|
-
this.deleteBuffer.clear();
|
|
5431
|
-
this.createdKeys.clear();
|
|
5432
|
-
this.deletedValues.clear();
|
|
5433
|
-
this.originallyExisted.clear();
|
|
5442
|
+
this._cleanupAll();
|
|
5434
5443
|
this.committed = true;
|
|
5435
5444
|
if (this.root !== this) {
|
|
5436
5445
|
this.root.activeTransactions.delete(this);
|
|
@@ -5466,6 +5475,19 @@ var require_cjs = __commonJS({
|
|
|
5466
5475
|
}
|
|
5467
5476
|
return Array.from(conflicts);
|
|
5468
5477
|
}
|
|
5478
|
+
/**
|
|
5479
|
+
* Cleans up all buffers and history.
|
|
5480
|
+
* This method is called by the commit method.
|
|
5481
|
+
*/
|
|
5482
|
+
_cleanupAll() {
|
|
5483
|
+
this.writeBuffer.clear();
|
|
5484
|
+
this.deleteBuffer.clear();
|
|
5485
|
+
this.createdKeys.clear();
|
|
5486
|
+
this.deletedValues.clear();
|
|
5487
|
+
this.originallyExisted.clear();
|
|
5488
|
+
this.keyVersions.clear();
|
|
5489
|
+
this.bufferHistory.clear();
|
|
5490
|
+
}
|
|
5469
5491
|
/**
|
|
5470
5492
|
* Cleans up both deletedCache and versionIndex based on minActiveVersion.
|
|
5471
5493
|
* Root transactions call this after commit to reclaim memory.
|
|
@@ -5657,6 +5679,7 @@ var require_cjs = __commonJS({
|
|
|
5657
5679
|
if (this.parent) {
|
|
5658
5680
|
const failure = this.parent._merge(this);
|
|
5659
5681
|
if (failure) {
|
|
5682
|
+
this.rollback();
|
|
5660
5683
|
return {
|
|
5661
5684
|
label,
|
|
5662
5685
|
success: false,
|
|
@@ -5667,11 +5690,13 @@ var require_cjs = __commonJS({
|
|
|
5667
5690
|
deleted
|
|
5668
5691
|
};
|
|
5669
5692
|
}
|
|
5693
|
+
this._cleanupAll();
|
|
5670
5694
|
this.committed = true;
|
|
5671
5695
|
} else {
|
|
5672
5696
|
if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
|
|
5673
5697
|
const failure = this._merge(this);
|
|
5674
5698
|
if (failure) {
|
|
5699
|
+
this.rollback();
|
|
5675
5700
|
return {
|
|
5676
5701
|
label,
|
|
5677
5702
|
success: false,
|
|
@@ -5682,13 +5707,7 @@ var require_cjs = __commonJS({
|
|
|
5682
5707
|
deleted: []
|
|
5683
5708
|
};
|
|
5684
5709
|
}
|
|
5685
|
-
this.
|
|
5686
|
-
this.deleteBuffer.clear();
|
|
5687
|
-
this.createdKeys.clear();
|
|
5688
|
-
this.deletedValues.clear();
|
|
5689
|
-
this.originallyExisted.clear();
|
|
5690
|
-
this.keyVersions.clear();
|
|
5691
|
-
this.bufferHistory.clear();
|
|
5710
|
+
this._cleanupAll();
|
|
5692
5711
|
this.localVersion = 0;
|
|
5693
5712
|
this.snapshotVersion = this.version;
|
|
5694
5713
|
}
|
|
@@ -6322,6 +6341,7 @@ var require_cjs = __commonJS({
|
|
|
6322
6341
|
if (this.parent) {
|
|
6323
6342
|
const failure = await this.parent._merge(this);
|
|
6324
6343
|
if (failure) {
|
|
6344
|
+
this.rollback();
|
|
6325
6345
|
return {
|
|
6326
6346
|
label,
|
|
6327
6347
|
success: false,
|
|
@@ -6332,11 +6352,13 @@ var require_cjs = __commonJS({
|
|
|
6332
6352
|
deleted
|
|
6333
6353
|
};
|
|
6334
6354
|
}
|
|
6355
|
+
this._cleanupAll();
|
|
6335
6356
|
this.committed = true;
|
|
6336
6357
|
} else {
|
|
6337
6358
|
if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
|
|
6338
6359
|
const failure = await this._merge(this);
|
|
6339
6360
|
if (failure) {
|
|
6361
|
+
this.rollback();
|
|
6340
6362
|
return {
|
|
6341
6363
|
label,
|
|
6342
6364
|
success: false,
|
|
@@ -6347,13 +6369,7 @@ var require_cjs = __commonJS({
|
|
|
6347
6369
|
deleted: []
|
|
6348
6370
|
};
|
|
6349
6371
|
}
|
|
6350
|
-
this.
|
|
6351
|
-
this.deleteBuffer.clear();
|
|
6352
|
-
this.createdKeys.clear();
|
|
6353
|
-
this.deletedValues.clear();
|
|
6354
|
-
this.originallyExisted.clear();
|
|
6355
|
-
this.keyVersions.clear();
|
|
6356
|
-
this.bufferHistory.clear();
|
|
6372
|
+
this._cleanupAll();
|
|
6357
6373
|
this.localVersion = 0;
|
|
6358
6374
|
this.snapshotVersion = this.version;
|
|
6359
6375
|
}
|
|
@@ -9967,10 +9983,10 @@ var require_cjs = __commonJS({
|
|
|
9967
9983
|
if (shouldTriggerCheckpoint) {
|
|
9968
9984
|
await this.pfs.checkpoint();
|
|
9969
9985
|
}
|
|
9986
|
+
} finally {
|
|
9970
9987
|
this.dirtyPages.clear();
|
|
9971
9988
|
this.undoPages.clear();
|
|
9972
9989
|
this.releaseAllLocks();
|
|
9973
|
-
} finally {
|
|
9974
9990
|
if (this._writeLockRelease) {
|
|
9975
9991
|
this._writeLockRelease();
|
|
9976
9992
|
this._writeLockRelease = null;
|
|
@@ -10053,10 +10069,10 @@ var require_cjs = __commonJS({
|
|
|
10053
10069
|
return level >= this.level;
|
|
10054
10070
|
}
|
|
10055
10071
|
create(moduleName) {
|
|
10056
|
-
return new
|
|
10072
|
+
return new Logger2(this, moduleName);
|
|
10057
10073
|
}
|
|
10058
10074
|
};
|
|
10059
|
-
var
|
|
10075
|
+
var Logger2 = class {
|
|
10060
10076
|
constructor(parent, moduleName) {
|
|
10061
10077
|
this.parent = parent;
|
|
10062
10078
|
this.moduleName = moduleName;
|
|
@@ -11699,6 +11715,71 @@ var DocumentSerializeStrategyAsync = class extends import_dataply2.SerializeStra
|
|
|
11699
11715
|
}
|
|
11700
11716
|
};
|
|
11701
11717
|
|
|
11718
|
+
// src/utils/eventLoopManager.ts
|
|
11719
|
+
function yieldEventLoop() {
|
|
11720
|
+
return new Promise(setImmediate);
|
|
11721
|
+
}
|
|
11722
|
+
var DeadlineChunker = class {
|
|
11723
|
+
/**
|
|
11724
|
+
* 이벤트 루프를 막을 최대 허용 시간
|
|
11725
|
+
*/
|
|
11726
|
+
targetMs;
|
|
11727
|
+
/**
|
|
11728
|
+
* 현재 chunk size
|
|
11729
|
+
*/
|
|
11730
|
+
chunkSize;
|
|
11731
|
+
/**
|
|
11732
|
+
* Exponential Weighted Moving Average
|
|
11733
|
+
*/
|
|
11734
|
+
ewmaMs;
|
|
11735
|
+
/**
|
|
11736
|
+
* EWMA 평활화 계수
|
|
11737
|
+
*/
|
|
11738
|
+
alpha;
|
|
11739
|
+
constructor(startChunkSize = 0, targetMs = 5, alpha = 0.5) {
|
|
11740
|
+
this.chunkSize = startChunkSize;
|
|
11741
|
+
this.targetMs = targetMs;
|
|
11742
|
+
this.alpha = alpha;
|
|
11743
|
+
this.ewmaMs = null;
|
|
11744
|
+
}
|
|
11745
|
+
/**
|
|
11746
|
+
* EWMA 평활화 계수를 사용하여 평균 처리 시간을 업데이트합니다.
|
|
11747
|
+
*/
|
|
11748
|
+
updateEstimate(elapsed, count) {
|
|
11749
|
+
const msPerItem = elapsed / count;
|
|
11750
|
+
this.ewmaMs = this.ewmaMs === null ? msPerItem : this.alpha * msPerItem + (1 - this.alpha) * this.ewmaMs;
|
|
11751
|
+
}
|
|
11752
|
+
/**
|
|
11753
|
+
* 현재 chunk size를 업데이트합니다.
|
|
11754
|
+
*/
|
|
11755
|
+
nextChunkSize() {
|
|
11756
|
+
if (!this.ewmaMs || this.ewmaMs === 0) return this.chunkSize;
|
|
11757
|
+
const next = Math.floor(this.targetMs / this.ewmaMs);
|
|
11758
|
+
return Math.max(1, next);
|
|
11759
|
+
}
|
|
11760
|
+
/**
|
|
11761
|
+
* 주어진 items를 chunk로 분할하여 처리합니다.
|
|
11762
|
+
*/
|
|
11763
|
+
async processInChunks(items, processFn) {
|
|
11764
|
+
let i = 0;
|
|
11765
|
+
let len = items.length;
|
|
11766
|
+
if (this.chunkSize === 0) {
|
|
11767
|
+
this.chunkSize = Math.floor(items.length / 100 * 5);
|
|
11768
|
+
}
|
|
11769
|
+
while (i < len) {
|
|
11770
|
+
const chunk = items.slice(i, i + this.chunkSize);
|
|
11771
|
+
const count = chunk.length;
|
|
11772
|
+
const start = performance.now();
|
|
11773
|
+
await processFn(chunk);
|
|
11774
|
+
const elapsed = performance.now() - start;
|
|
11775
|
+
this.updateEstimate(elapsed, count);
|
|
11776
|
+
this.chunkSize = this.nextChunkSize();
|
|
11777
|
+
i += count;
|
|
11778
|
+
await yieldEventLoop();
|
|
11779
|
+
}
|
|
11780
|
+
}
|
|
11781
|
+
};
|
|
11782
|
+
|
|
11702
11783
|
// src/core/IndexManager.ts
|
|
11703
11784
|
var IndexManager = class {
|
|
11704
11785
|
constructor(api, logger) {
|
|
@@ -11878,7 +11959,7 @@ var IndexManager = class {
|
|
|
11878
11959
|
this.indices = metadata.indices;
|
|
11879
11960
|
this.registeredIndices.delete(name);
|
|
11880
11961
|
const fields = this.getFieldsFromConfig(config);
|
|
11881
|
-
for (let i = 0
|
|
11962
|
+
for (let i = 0, len = fields.length; i < len; i++) {
|
|
11882
11963
|
const field = fields[i];
|
|
11883
11964
|
const indexNames = this.fieldToIndices.get(field);
|
|
11884
11965
|
if (indexNames) {
|
|
@@ -11972,6 +12053,7 @@ var IndexManager = class {
|
|
|
11972
12053
|
await treeTx.rollback();
|
|
11973
12054
|
throw err;
|
|
11974
12055
|
}
|
|
12056
|
+
await yieldEventLoop();
|
|
11975
12057
|
}
|
|
11976
12058
|
this.pendingBackfillFields = [];
|
|
11977
12059
|
return backfilledCount;
|
|
@@ -12043,7 +12125,9 @@ var IndexManager = class {
|
|
|
12043
12125
|
indexName
|
|
12044
12126
|
),
|
|
12045
12127
|
this.api.comparator,
|
|
12046
|
-
{
|
|
12128
|
+
{
|
|
12129
|
+
capacity: perIndexCapacity
|
|
12130
|
+
}
|
|
12047
12131
|
);
|
|
12048
12132
|
await tree.init();
|
|
12049
12133
|
this.trees.set(indexName, tree);
|
|
@@ -12061,6 +12145,7 @@ var IndexManager = class {
|
|
|
12061
12145
|
await treeTx.rollback();
|
|
12062
12146
|
throw err;
|
|
12063
12147
|
}
|
|
12148
|
+
await yieldEventLoop();
|
|
12064
12149
|
}
|
|
12065
12150
|
}
|
|
12066
12151
|
return docCount;
|
|
@@ -12171,77 +12256,15 @@ async function catchPromise(promise) {
|
|
|
12171
12256
|
return promise.then((res) => [void 0, res]).catch((reason) => [reason]);
|
|
12172
12257
|
}
|
|
12173
12258
|
|
|
12174
|
-
// src/utils/DeadlineChunker.ts
|
|
12175
|
-
var DeadlineChunker = class {
|
|
12176
|
-
/**
|
|
12177
|
-
* 이벤트 루프를 막을 최대 허용 시간
|
|
12178
|
-
*/
|
|
12179
|
-
targetMs;
|
|
12180
|
-
/**
|
|
12181
|
-
* 현재 chunk size
|
|
12182
|
-
*/
|
|
12183
|
-
chunkSize;
|
|
12184
|
-
/**
|
|
12185
|
-
* Exponential Weighted Moving Average
|
|
12186
|
-
*/
|
|
12187
|
-
ewmaMs;
|
|
12188
|
-
/**
|
|
12189
|
-
* EWMA 평활화 계수
|
|
12190
|
-
*/
|
|
12191
|
-
alpha;
|
|
12192
|
-
constructor(startChunkSize = 0, targetMs = 5, alpha = 0.5) {
|
|
12193
|
-
this.chunkSize = startChunkSize;
|
|
12194
|
-
this.targetMs = targetMs;
|
|
12195
|
-
this.alpha = alpha;
|
|
12196
|
-
this.ewmaMs = null;
|
|
12197
|
-
}
|
|
12198
|
-
/**
|
|
12199
|
-
* EWMA 평활화 계수를 사용하여 평균 처리 시간을 업데이트합니다.
|
|
12200
|
-
*/
|
|
12201
|
-
updateEstimate(elapsed, count) {
|
|
12202
|
-
const msPerItem = elapsed / count;
|
|
12203
|
-
this.ewmaMs = this.ewmaMs === null ? msPerItem : this.alpha * msPerItem + (1 - this.alpha) * this.ewmaMs;
|
|
12204
|
-
}
|
|
12205
|
-
/**
|
|
12206
|
-
* 현재 chunk size를 업데이트합니다.
|
|
12207
|
-
*/
|
|
12208
|
-
nextChunkSize() {
|
|
12209
|
-
if (!this.ewmaMs || this.ewmaMs === 0) return this.chunkSize;
|
|
12210
|
-
const next = Math.floor(this.targetMs / this.ewmaMs);
|
|
12211
|
-
return Math.max(1, next);
|
|
12212
|
-
}
|
|
12213
|
-
/**
|
|
12214
|
-
* 주어진 items를 chunk로 분할하여 처리합니다.
|
|
12215
|
-
*/
|
|
12216
|
-
async processInChunks(items, processFn) {
|
|
12217
|
-
let i = 0;
|
|
12218
|
-
let len = items.length;
|
|
12219
|
-
if (this.chunkSize === 0) {
|
|
12220
|
-
this.chunkSize = Math.floor(items.length / 100 * 5);
|
|
12221
|
-
}
|
|
12222
|
-
while (i < len) {
|
|
12223
|
-
const chunk = items.slice(i, i + this.chunkSize);
|
|
12224
|
-
const count = chunk.length;
|
|
12225
|
-
const start = performance.now();
|
|
12226
|
-
await processFn(chunk);
|
|
12227
|
-
const elapsed = performance.now() - start;
|
|
12228
|
-
this.updateEstimate(elapsed, count);
|
|
12229
|
-
this.chunkSize = this.nextChunkSize();
|
|
12230
|
-
i += count;
|
|
12231
|
-
await new Promise(setImmediate);
|
|
12232
|
-
}
|
|
12233
|
-
}
|
|
12234
|
-
};
|
|
12235
|
-
|
|
12236
12259
|
// src/core/MutationManager.ts
|
|
12237
12260
|
var MutationManager = class {
|
|
12238
12261
|
constructor(api, logger) {
|
|
12239
12262
|
this.api = api;
|
|
12240
12263
|
this.logger = logger;
|
|
12241
12264
|
}
|
|
12242
|
-
async isTreeEmpty(tree) {
|
|
12265
|
+
async isTreeEmpty(tree, tx) {
|
|
12243
12266
|
try {
|
|
12244
|
-
const root = await tree.getNode(tree.rootId);
|
|
12267
|
+
const root = await tree.getNode(tree.rootId, tx);
|
|
12245
12268
|
return root.leaf && root.values.length === 0;
|
|
12246
12269
|
} catch {
|
|
12247
12270
|
return true;
|
|
@@ -12288,16 +12311,19 @@ var MutationManager = class {
|
|
|
12288
12311
|
}
|
|
12289
12312
|
}
|
|
12290
12313
|
await this.api.analysisManager.notifyInsert([flattenDocument], tx2);
|
|
12314
|
+
this.logger.debug(`Inserted single document with ID: ${dataplyDocument._id}`);
|
|
12291
12315
|
return dataplyDocument._id;
|
|
12292
12316
|
}, tx);
|
|
12293
12317
|
}
|
|
12294
12318
|
async insertBatchDocuments(documents, tx) {
|
|
12295
12319
|
return this.api.runWithDefaultWrite(async (tx2) => {
|
|
12320
|
+
this.logger.debug(`Batch inserting ${documents.length} documents`);
|
|
12296
12321
|
const metadata = await this.api.getDocumentInnerMetadata(tx2);
|
|
12297
|
-
|
|
12322
|
+
let startId = metadata.lastId + 1;
|
|
12298
12323
|
metadata.lastId += documents.length;
|
|
12299
12324
|
await this.api.updateDocumentInnerMetadata(metadata, tx2);
|
|
12300
|
-
const ids =
|
|
12325
|
+
const ids = new Float64Array(documents.length);
|
|
12326
|
+
const pks = new Float64Array(documents.length);
|
|
12301
12327
|
const dataplyDocuments = [];
|
|
12302
12328
|
const flattenedData = [];
|
|
12303
12329
|
for (let i = 0, len = documents.length; i < len; i++) {
|
|
@@ -12309,17 +12335,15 @@ var MutationManager = class {
|
|
|
12309
12335
|
dataplyDocuments.push(stringified);
|
|
12310
12336
|
const flattenDocument = this.api.flattenDocument(dataplyDocument);
|
|
12311
12337
|
flattenedData.push({ pk: -1, data: flattenDocument });
|
|
12312
|
-
ids
|
|
12338
|
+
ids[i] = id;
|
|
12313
12339
|
}
|
|
12314
|
-
const
|
|
12315
|
-
|
|
12316
|
-
|
|
12317
|
-
|
|
12318
|
-
|
|
12319
|
-
});
|
|
12320
|
-
for (let i = 0, len = pks.length; i < len; i++) {
|
|
12321
|
-
flattenedData[i].pk = pks[i];
|
|
12340
|
+
const res = await this.api.insertBatch(dataplyDocuments, true, tx2);
|
|
12341
|
+
for (let i = 0, len = res.length; i < len; i++) {
|
|
12342
|
+
const index = i;
|
|
12343
|
+
pks[index] = res[i];
|
|
12344
|
+
flattenedData[index].pk = res[i];
|
|
12322
12345
|
}
|
|
12346
|
+
await yieldEventLoop();
|
|
12323
12347
|
for (const [indexName, config] of this.api.indexManager.registeredIndices) {
|
|
12324
12348
|
const tree = this.api.trees.get(indexName);
|
|
12325
12349
|
if (!tree) continue;
|
|
@@ -12346,42 +12370,39 @@ var MutationManager = class {
|
|
|
12346
12370
|
batchInsertData.push([item.pk, { k: item.pk, v: indexVal }]);
|
|
12347
12371
|
}
|
|
12348
12372
|
}
|
|
12349
|
-
const isEmptyTree = await this.isTreeEmpty(tree);
|
|
12373
|
+
const isEmptyTree = await this.isTreeEmpty(tree, tx2);
|
|
12350
12374
|
if (isEmptyTree) {
|
|
12351
12375
|
const [error] = await catchPromise(treeTx.bulkLoad(batchInsertData));
|
|
12352
12376
|
if (error) {
|
|
12353
12377
|
throw error;
|
|
12354
12378
|
}
|
|
12355
12379
|
} else {
|
|
12356
|
-
const
|
|
12357
|
-
|
|
12358
|
-
|
|
12359
|
-
|
|
12360
|
-
);
|
|
12361
|
-
const chunker = new DeadlineChunker(initChunkSize);
|
|
12362
|
-
await chunker.processInChunks(batchInsertData, async (chunk) => {
|
|
12363
|
-
const [error] = await catchPromise(treeTx.batchInsert(chunk));
|
|
12364
|
-
if (error) {
|
|
12365
|
-
throw error;
|
|
12366
|
-
}
|
|
12367
|
-
});
|
|
12380
|
+
const [error] = await catchPromise(treeTx.batchInsert(batchInsertData));
|
|
12381
|
+
if (error) {
|
|
12382
|
+
throw error;
|
|
12383
|
+
}
|
|
12368
12384
|
}
|
|
12369
|
-
const
|
|
12370
|
-
if (!
|
|
12385
|
+
const res2 = await treeTx.commit();
|
|
12386
|
+
if (!res2.success) {
|
|
12371
12387
|
await treeTx.rollback();
|
|
12372
|
-
|
|
12388
|
+
this.logger.error(`Failed to commit batch insert for index ${indexName}: ${res2.error}`);
|
|
12389
|
+
throw res2.error;
|
|
12373
12390
|
}
|
|
12391
|
+
await yieldEventLoop();
|
|
12374
12392
|
}
|
|
12375
12393
|
const flatDocs = [];
|
|
12376
12394
|
for (let i = 0, len = flattenedData.length; i < len; i++) {
|
|
12377
12395
|
flatDocs.push(flattenedData[i].data);
|
|
12378
12396
|
}
|
|
12379
12397
|
await this.api.analysisManager.notifyInsert(flatDocs, tx2);
|
|
12380
|
-
|
|
12398
|
+
await yieldEventLoop();
|
|
12399
|
+
this.logger.debug(`Successfully batch inserted ${documents.length} documents`);
|
|
12400
|
+
return Array.from(ids);
|
|
12381
12401
|
}, tx);
|
|
12382
12402
|
}
|
|
12383
12403
|
async updateInternal(query, computeUpdatedDoc, tx) {
|
|
12384
12404
|
const pks = await this.api.queryManager.getKeys(query);
|
|
12405
|
+
this.logger.debug(`Found ${pks.length} documents to update`);
|
|
12385
12406
|
let updatedCount = 0;
|
|
12386
12407
|
const updatePairs = [];
|
|
12387
12408
|
const treeTxs = /* @__PURE__ */ new Map();
|
|
@@ -12430,9 +12451,11 @@ var MutationManager = class {
|
|
|
12430
12451
|
await treeTx.batchInsert([[pk, { k: pk, v: newIndexVal }]]);
|
|
12431
12452
|
}
|
|
12432
12453
|
}
|
|
12454
|
+
await yieldEventLoop();
|
|
12433
12455
|
}
|
|
12434
12456
|
updatePairs.push({ oldDocument: oldFlatDoc, newDocument: newFlatDoc });
|
|
12435
12457
|
await this.api.update(pk, JSON.stringify(updatedDoc), tx);
|
|
12458
|
+
await yieldEventLoop();
|
|
12436
12459
|
updatedCount++;
|
|
12437
12460
|
}
|
|
12438
12461
|
for (const [indexName, treeTx] of treeTxs) {
|
|
@@ -12441,10 +12464,14 @@ var MutationManager = class {
|
|
|
12441
12464
|
for (const rollbackTx of treeTxs.values()) {
|
|
12442
12465
|
rollbackTx.rollback();
|
|
12443
12466
|
}
|
|
12467
|
+
await yieldEventLoop();
|
|
12468
|
+
this.logger.error(`Failed to commit update for index ${indexName}: ${result.error}`);
|
|
12444
12469
|
throw result.error;
|
|
12445
12470
|
}
|
|
12446
12471
|
}
|
|
12447
12472
|
await this.api.analysisManager.notifyUpdate(updatePairs, tx);
|
|
12473
|
+
await yieldEventLoop();
|
|
12474
|
+
this.logger.debug(`Successfully updated ${updatedCount} documents`);
|
|
12448
12475
|
return updatedCount;
|
|
12449
12476
|
}
|
|
12450
12477
|
async fullUpdate(query, newRecord, tx) {
|
|
@@ -12468,6 +12495,7 @@ var MutationManager = class {
|
|
|
12468
12495
|
async deleteDocuments(query, tx) {
|
|
12469
12496
|
return this.api.runWithDefaultWrite(async (tx2) => {
|
|
12470
12497
|
const pks = await this.api.queryManager.getKeys(query);
|
|
12498
|
+
this.logger.debug(`Found ${pks.length} documents to delete`);
|
|
12471
12499
|
let deletedCount = 0;
|
|
12472
12500
|
const deletedFlatDocs = [];
|
|
12473
12501
|
for (let i = 0, len = pks.length; i < len; i++) {
|
|
@@ -12492,12 +12520,16 @@ var MutationManager = class {
|
|
|
12492
12520
|
if (indexVal === void 0) continue;
|
|
12493
12521
|
await tree.delete(pk, { k: pk, v: indexVal });
|
|
12494
12522
|
}
|
|
12523
|
+
await yieldEventLoop();
|
|
12495
12524
|
}
|
|
12496
12525
|
deletedFlatDocs.push(flatDoc);
|
|
12497
12526
|
await this.api.delete(pk, true, tx2);
|
|
12527
|
+
await yieldEventLoop();
|
|
12498
12528
|
deletedCount++;
|
|
12499
12529
|
}
|
|
12500
12530
|
await this.api.analysisManager.notifyDelete(deletedFlatDocs, tx2);
|
|
12531
|
+
await yieldEventLoop();
|
|
12532
|
+
this.logger.debug(`Successfully deleted ${deletedCount} documents`);
|
|
12501
12533
|
return deletedCount;
|
|
12502
12534
|
}, tx);
|
|
12503
12535
|
}
|
|
@@ -13701,6 +13733,22 @@ var DocumentDataplyAPI = class extends import_dataply4.DataplyAPI {
|
|
|
13701
13733
|
get indexedFields() {
|
|
13702
13734
|
return this.indexManager.indexedFields;
|
|
13703
13735
|
}
|
|
13736
|
+
/**
|
|
13737
|
+
* Method for reliably processing large batches (chunks) of data.
|
|
13738
|
+
* Processes data in fragments to prevent blocking the event loop while handling large volumes of data.
|
|
13739
|
+
* @param items The items to process
|
|
13740
|
+
* @param callback The callback to process each chunk
|
|
13741
|
+
* @param options The options for the chunk splitter
|
|
13742
|
+
* @param options.firstChunkSize The size of the first chunk. Subsequent chunk sizes are determined based on this value and the processing time. If not specified or set to 0, 5% of the total data is used as the initial value.
|
|
13743
|
+
* @param options.alpha A value that determines the weight given to recent processing times. Higher values weigh recent times more heavily. Lower values are recommended for stability, but excessively low values may impact performance. Default is 0.5.
|
|
13744
|
+
* @returns The processed items
|
|
13745
|
+
*/
|
|
13746
|
+
processInChunks(items, callback, options) {
|
|
13747
|
+
this.logger.debug(`Processing ${items.length} items in chunks`);
|
|
13748
|
+
const firstChunkSize = options?.firstChunkSize ?? 0;
|
|
13749
|
+
const alpha = options?.alpha ?? 0.5;
|
|
13750
|
+
return new DeadlineChunker(firstChunkSize, alpha).processInChunks(items, callback);
|
|
13751
|
+
}
|
|
13704
13752
|
/**
|
|
13705
13753
|
* Register an index.
|
|
13706
13754
|
* @param name The name of the index
|
|
@@ -13950,6 +13998,19 @@ var DocumentDataply = class _DocumentDataply {
|
|
|
13950
13998
|
constructor(file, options) {
|
|
13951
13999
|
this.api = new DocumentDataplyAPI(file, options ?? {});
|
|
13952
14000
|
}
|
|
14001
|
+
/**
|
|
14002
|
+
* Method for reliably processing large batches (chunks) of data.
|
|
14003
|
+
* Processes data in fragments to prevent blocking the event loop while handling large volumes of data.
|
|
14004
|
+
* @param items The items to process
|
|
14005
|
+
* @param callback The callback to process each chunk
|
|
14006
|
+
* @param options The options for the chunk splitter
|
|
14007
|
+
* @param options.firstChunkSize The size of the first chunk. Subsequent chunk sizes are determined based on this value and the processing time. If not specified or set to 0, 5% of the total data is used as the initial value.
|
|
14008
|
+
* @param options.alpha A value that determines the weight given to recent processing times. Higher values weigh recent times more heavily. Lower values are recommended for stability, but excessively low values may impact performance. Default is 0.5.
|
|
14009
|
+
* @returns The processed items
|
|
14010
|
+
*/
|
|
14011
|
+
processInChunks(items, callback, options) {
|
|
14012
|
+
return this.api.processInChunks(items, callback, options);
|
|
14013
|
+
}
|
|
13953
14014
|
/**
|
|
13954
14015
|
* Create a named index on the database.
|
|
13955
14016
|
* Can be called before or after init().
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AnalysisHeader, DocumentJSON, FlattenedDocumentJSON } from '../types';
|
|
2
2
|
import type { DocumentDataplyAPI } from './documentAPI';
|
|
3
3
|
import type { AnalysisProvider } from './AnalysisProvider';
|
|
4
|
-
import { Transaction } from 'dataply';
|
|
4
|
+
import { Transaction, Logger } from 'dataply';
|
|
5
5
|
export declare class AnalysisManager<T extends DocumentJSON> {
|
|
6
6
|
private api;
|
|
7
7
|
readonly sampleSize: number;
|
|
@@ -9,7 +9,7 @@ export declare class AnalysisManager<T extends DocumentJSON> {
|
|
|
9
9
|
private providers;
|
|
10
10
|
private cron;
|
|
11
11
|
private flushing;
|
|
12
|
-
constructor(api: DocumentDataplyAPI<T>, schedule: string, sampleSize: number, logger:
|
|
12
|
+
constructor(api: DocumentDataplyAPI<T>, schedule: string, sampleSize: number, logger: Logger);
|
|
13
13
|
/**
|
|
14
14
|
* Stop the background analysis cron job.
|
|
15
15
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { DataplyTreeValue, DocumentDataplyInnerMetadata, Primitive, CreateIndexOption, IndexMetaConfig, FTSConfig, DocumentJSON, FlattenedDocumentJSON } from '../types';
|
|
2
2
|
import type { DocumentDataplyAPI } from './documentAPI';
|
|
3
|
-
import { BPTreeAsync, Transaction } from 'dataply';
|
|
3
|
+
import { BPTreeAsync, Transaction, Logger } from 'dataply';
|
|
4
4
|
export declare class IndexManager<T extends DocumentJSON> {
|
|
5
5
|
private api;
|
|
6
6
|
private logger;
|
|
@@ -23,7 +23,7 @@ export declare class IndexManager<T extends DocumentJSON> {
|
|
|
23
23
|
*/
|
|
24
24
|
fieldToIndices: Map<string, string[]>;
|
|
25
25
|
pendingBackfillFields: string[];
|
|
26
|
-
constructor(api: DocumentDataplyAPI<T>, logger:
|
|
26
|
+
constructor(api: DocumentDataplyAPI<T>, logger: Logger);
|
|
27
27
|
/**
|
|
28
28
|
* Validate and apply indices from DB metadata and pending indices.
|
|
29
29
|
* Called during database initialization.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { DocumentDataplyMetadata, DocumentDataplyInnerMetadata, DocumentJSON } from '../types';
|
|
2
2
|
import type { DocumentDataplyAPI } from './documentAPI';
|
|
3
|
-
import { Transaction } from 'dataply';
|
|
3
|
+
import { Transaction, Logger } from 'dataply';
|
|
4
4
|
export declare class MetadataManager<T extends DocumentJSON> {
|
|
5
5
|
private api;
|
|
6
6
|
private logger;
|
|
7
|
-
constructor(api: DocumentDataplyAPI<T>, logger:
|
|
7
|
+
constructor(api: DocumentDataplyAPI<T>, logger: Logger);
|
|
8
8
|
getDocumentMetadata(tx: Transaction): Promise<DocumentDataplyMetadata>;
|
|
9
9
|
getDocumentInnerMetadata(tx: Transaction): Promise<DocumentDataplyInnerMetadata>;
|
|
10
10
|
updateDocumentInnerMetadata(metadata: DocumentDataplyInnerMetadata, tx: Transaction): Promise<void>;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { DocumentJSON, DataplyDocument, DocumentDataplyQuery } from '../types';
|
|
2
2
|
import type { DocumentDataplyAPI } from './documentAPI';
|
|
3
|
-
import { Transaction } from 'dataply';
|
|
3
|
+
import { Transaction, Logger } from 'dataply';
|
|
4
4
|
export declare class MutationManager<T extends DocumentJSON> {
|
|
5
5
|
private api;
|
|
6
6
|
private logger;
|
|
7
|
-
constructor(api: DocumentDataplyAPI<T>, logger:
|
|
7
|
+
constructor(api: DocumentDataplyAPI<T>, logger: Logger);
|
|
8
8
|
private isTreeEmpty;
|
|
9
9
|
private insertDocumentInternal;
|
|
10
10
|
insertSingleDocument(document: T, tx?: Transaction): Promise<number>;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { DataplyTreeValue, DocumentDataplyQuery, DocumentDataplyQueryOptions, DataplyDocument, Primitive, DocumentJSON } from '../types';
|
|
2
2
|
import type { DocumentDataplyAPI } from './documentAPI';
|
|
3
3
|
import type { Optimizer } from './Optimizer';
|
|
4
|
-
import { BPTreeAsync } from 'dataply';
|
|
4
|
+
import { BPTreeAsync, Logger } from 'dataply';
|
|
5
5
|
export declare class QueryManager<T extends DocumentJSON> {
|
|
6
6
|
private api;
|
|
7
7
|
private optimizer;
|
|
8
8
|
private logger;
|
|
9
9
|
private readonly operatorConverters;
|
|
10
|
-
constructor(api: DocumentDataplyAPI<T>, optimizer: Optimizer<T>, logger:
|
|
10
|
+
constructor(api: DocumentDataplyAPI<T>, optimizer: Optimizer<T>, logger: Logger);
|
|
11
11
|
/**
|
|
12
12
|
* Transforms a query object into a verbose query object
|
|
13
13
|
*/
|
|
@@ -30,6 +30,20 @@ export declare class DocumentDataply<T extends DocumentJSON> {
|
|
|
30
30
|
private static Open;
|
|
31
31
|
protected readonly api: DocumentDataplyAPI<T>;
|
|
32
32
|
protected constructor(file: string, options?: DocumentDataplyOptions);
|
|
33
|
+
/**
|
|
34
|
+
* Method for reliably processing large batches (chunks) of data.
|
|
35
|
+
* Processes data in fragments to prevent blocking the event loop while handling large volumes of data.
|
|
36
|
+
* @param items The items to process
|
|
37
|
+
* @param callback The callback to process each chunk
|
|
38
|
+
* @param options The options for the chunk splitter
|
|
39
|
+
* @param options.firstChunkSize The size of the first chunk. Subsequent chunk sizes are determined based on this value and the processing time. If not specified or set to 0, 5% of the total data is used as the initial value.
|
|
40
|
+
* @param options.alpha A value that determines the weight given to recent processing times. Higher values weigh recent times more heavily. Lower values are recommended for stability, but excessively low values may impact performance. Default is 0.5.
|
|
41
|
+
* @returns The processed items
|
|
42
|
+
*/
|
|
43
|
+
processInChunks<T>(items: T[], callback: (chunk: T[]) => Promise<void>, options?: {
|
|
44
|
+
firstChunkSize?: number;
|
|
45
|
+
alpha?: number;
|
|
46
|
+
}): Promise<void>;
|
|
33
47
|
/**
|
|
34
48
|
* Create a named index on the database.
|
|
35
49
|
* Can be called before or after init().
|
|
@@ -31,6 +31,20 @@ export declare class DocumentDataplyAPI<T extends DocumentJSON> extends DataplyA
|
|
|
31
31
|
};
|
|
32
32
|
get trees(): Map<string, import("dataply").BPTreeAsync<string | number, import("../types").DataplyTreeValue<import("../types").Primitive>>>;
|
|
33
33
|
get indexedFields(): Set<string>;
|
|
34
|
+
/**
|
|
35
|
+
* Method for reliably processing large batches (chunks) of data.
|
|
36
|
+
* Processes data in fragments to prevent blocking the event loop while handling large volumes of data.
|
|
37
|
+
* @param items The items to process
|
|
38
|
+
* @param callback The callback to process each chunk
|
|
39
|
+
* @param options The options for the chunk splitter
|
|
40
|
+
* @param options.firstChunkSize The size of the first chunk. Subsequent chunk sizes are determined based on this value and the processing time. If not specified or set to 0, 5% of the total data is used as the initial value.
|
|
41
|
+
* @param options.alpha A value that determines the weight given to recent processing times. Higher values weigh recent times more heavily. Lower values are recommended for stability, but excessively low values may impact performance. Default is 0.5.
|
|
42
|
+
* @returns The processed items
|
|
43
|
+
*/
|
|
44
|
+
processInChunks<T>(items: T[], callback: (chunk: T[]) => Promise<void>, options?: {
|
|
45
|
+
firstChunkSize?: number;
|
|
46
|
+
alpha?: number;
|
|
47
|
+
}): Promise<void>;
|
|
34
48
|
/**
|
|
35
49
|
* Register an index.
|
|
36
50
|
* @param name The name of the index
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "document-dataply",
|
|
3
|
-
"version": "0.0.14-alpha.
|
|
3
|
+
"version": "0.0.14-alpha.2",
|
|
4
4
|
"description": "Simple and powerful JSON document database supporting complex queries and flexible indexing policies.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "izure <admin@izure.org>",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
],
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"croner": "^10.0.1",
|
|
46
|
-
"dataply": "^0.0.26-alpha.
|
|
46
|
+
"dataply": "^0.0.26-alpha.4"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/jest": "^30.0.0",
|