document-dataply 0.0.14-alpha.0 → 0.0.14-alpha.1
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 +560 -118
- package/dist/types/core/AnalysisManager.d.ts +2 -1
- package/dist/types/core/IndexManager.d.ts +7 -1
- package/dist/types/core/MetadataManager.d.ts +2 -1
- package/dist/types/core/MutationManager.d.ts +3 -1
- package/dist/types/core/QueryManager.d.ts +2 -1
- package/dist/types/core/document.d.ts +8 -0
- package/dist/types/core/documentAPI.d.ts +8 -0
- package/package.json +3 -3
package/dist/cjs/index.js
CHANGED
|
@@ -66,7 +66,7 @@ var require_cjs = __commonJS({
|
|
|
66
66
|
AsyncMVCCStrategy: () => AsyncMVCCStrategy2,
|
|
67
67
|
AsyncMVCCTransaction: () => AsyncMVCCTransaction2,
|
|
68
68
|
BPTreeAsync: () => BPTreeAsync2,
|
|
69
|
-
BPTreeAsyncTransaction: () =>
|
|
69
|
+
BPTreeAsyncTransaction: () => BPTreeAsyncTransaction,
|
|
70
70
|
BPTreeSync: () => BPTreeSync,
|
|
71
71
|
BPTreeSyncTransaction: () => BPTreeSyncTransaction,
|
|
72
72
|
BitmapPageManager: () => BitmapPageManager,
|
|
@@ -1985,30 +1985,22 @@ var require_cjs = __commonJS({
|
|
|
1985
1985
|
*/
|
|
1986
1986
|
_insertValueIntoLeaf(leaf, key, value) {
|
|
1987
1987
|
if (leaf.values.length) {
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
if (
|
|
1991
|
-
|
|
1992
|
-
return false;
|
|
1993
|
-
}
|
|
1994
|
-
leaf.keys[i].push(key);
|
|
1995
|
-
return true;
|
|
1996
|
-
} else if (this.comparator.isLower(value, nValue)) {
|
|
1997
|
-
leaf.values.splice(i, 0, value);
|
|
1998
|
-
leaf.keys.splice(i, 0, [key]);
|
|
1999
|
-
return true;
|
|
2000
|
-
} else if (i + 1 === leaf.values.length) {
|
|
2001
|
-
leaf.values.push(value);
|
|
2002
|
-
leaf.keys.push([key]);
|
|
2003
|
-
return true;
|
|
1988
|
+
const { index, found } = this._binarySearchValues(leaf.values, value);
|
|
1989
|
+
if (found) {
|
|
1990
|
+
if (leaf.keys[index].includes(key)) {
|
|
1991
|
+
return false;
|
|
2004
1992
|
}
|
|
1993
|
+
leaf.keys[index].push(key);
|
|
1994
|
+
return true;
|
|
2005
1995
|
}
|
|
1996
|
+
leaf.values.splice(index, 0, value);
|
|
1997
|
+
leaf.keys.splice(index, 0, [key]);
|
|
1998
|
+
return true;
|
|
2006
1999
|
} else {
|
|
2007
2000
|
leaf.values = [value];
|
|
2008
2001
|
leaf.keys = [[key]];
|
|
2009
2002
|
return true;
|
|
2010
2003
|
}
|
|
2011
|
-
return false;
|
|
2012
2004
|
}
|
|
2013
2005
|
_cloneNode(node) {
|
|
2014
2006
|
return JSON.parse(JSON.stringify(node));
|
|
@@ -2299,12 +2291,8 @@ var require_cjs = __commonJS({
|
|
|
2299
2291
|
const midValue = parentNode.values[mid];
|
|
2300
2292
|
parentNode.values = parentNode.values.slice(0, mid);
|
|
2301
2293
|
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
2302
|
-
for (
|
|
2303
|
-
const
|
|
2304
|
-
n.parent = parentNode.id;
|
|
2305
|
-
this._updateNode(n);
|
|
2306
|
-
}
|
|
2307
|
-
for (const k2 of newSiblingNodeRecursive.keys) {
|
|
2294
|
+
for (let i = 0, len = newSiblingNodeRecursive.keys.length; i < len; i++) {
|
|
2295
|
+
const k2 = newSiblingNodeRecursive.keys[i];
|
|
2308
2296
|
const n = this._cloneNode(this.getNode(k2));
|
|
2309
2297
|
n.parent = newSiblingNodeRecursive.id;
|
|
2310
2298
|
this._updateNode(n);
|
|
@@ -2386,7 +2374,7 @@ var require_cjs = __commonJS({
|
|
|
2386
2374
|
for (let i = 0; i < len; i++) {
|
|
2387
2375
|
const nValue = node.values[i];
|
|
2388
2376
|
const keys = node.keys[i];
|
|
2389
|
-
for (let j = 0,
|
|
2377
|
+
for (let j = 0, len2 = keys.length; j < len2; j++) {
|
|
2390
2378
|
yield [keys[j], nValue];
|
|
2391
2379
|
}
|
|
2392
2380
|
}
|
|
@@ -2465,7 +2453,7 @@ var require_cjs = __commonJS({
|
|
|
2465
2453
|
while (true) {
|
|
2466
2454
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2467
2455
|
const keys = node.keys[i];
|
|
2468
|
-
for (let j = 0,
|
|
2456
|
+
for (let j = 0, len2 = keys.length; j < len2; j++) {
|
|
2469
2457
|
if (keys[j] === key) {
|
|
2470
2458
|
return node.values[i];
|
|
2471
2459
|
}
|
|
@@ -2574,8 +2562,16 @@ var require_cjs = __commonJS({
|
|
|
2574
2562
|
const sorted = [...entries].sort((a, b2) => this.comparator.asc(a[1], b2[1]));
|
|
2575
2563
|
let currentLeaf = null;
|
|
2576
2564
|
let modified = false;
|
|
2577
|
-
|
|
2578
|
-
|
|
2565
|
+
let cachedLeafId = null;
|
|
2566
|
+
let cachedLeafMaxValue = null;
|
|
2567
|
+
for (let i = 0, len = sorted.length; i < len; i++) {
|
|
2568
|
+
const [key, value] = sorted[i];
|
|
2569
|
+
let targetLeaf;
|
|
2570
|
+
if (cachedLeafId !== null && cachedLeafMaxValue !== null && currentLeaf !== null && (this.comparator.isLower(value, cachedLeafMaxValue) || this.comparator.isSame(value, cachedLeafMaxValue))) {
|
|
2571
|
+
targetLeaf = currentLeaf;
|
|
2572
|
+
} else {
|
|
2573
|
+
targetLeaf = this.locateLeaf(value);
|
|
2574
|
+
}
|
|
2579
2575
|
if (currentLeaf !== null && currentLeaf.id === targetLeaf.id) {
|
|
2580
2576
|
} else {
|
|
2581
2577
|
if (currentLeaf !== null && modified) {
|
|
@@ -2584,8 +2580,10 @@ var require_cjs = __commonJS({
|
|
|
2584
2580
|
currentLeaf = this._cloneNode(targetLeaf);
|
|
2585
2581
|
modified = false;
|
|
2586
2582
|
}
|
|
2583
|
+
cachedLeafId = currentLeaf.id;
|
|
2587
2584
|
const changed = this._insertValueIntoLeaf(currentLeaf, key, value);
|
|
2588
2585
|
modified = modified || changed;
|
|
2586
|
+
cachedLeafMaxValue = currentLeaf.values[currentLeaf.values.length - 1];
|
|
2589
2587
|
if (currentLeaf.values.length === this.order) {
|
|
2590
2588
|
this._updateNode(currentLeaf);
|
|
2591
2589
|
let after = this._createNode(
|
|
@@ -2606,6 +2604,8 @@ var require_cjs = __commonJS({
|
|
|
2606
2604
|
this._updateNode(after);
|
|
2607
2605
|
this._insertInParent(currentLeaf, after.values[0], after);
|
|
2608
2606
|
currentLeaf = null;
|
|
2607
|
+
cachedLeafId = null;
|
|
2608
|
+
cachedLeafMaxValue = null;
|
|
2609
2609
|
modified = false;
|
|
2610
2610
|
}
|
|
2611
2611
|
}
|
|
@@ -2613,6 +2613,85 @@ var require_cjs = __commonJS({
|
|
|
2613
2613
|
this._updateNode(currentLeaf);
|
|
2614
2614
|
}
|
|
2615
2615
|
}
|
|
2616
|
+
bulkLoad(entries) {
|
|
2617
|
+
if (entries.length === 0) return;
|
|
2618
|
+
const root = this.getNode(this.rootId);
|
|
2619
|
+
if (!root.leaf || root.values.length > 0) {
|
|
2620
|
+
throw new Error("bulkLoad can only be called on an empty tree. Use batchInsert for non-empty trees.");
|
|
2621
|
+
}
|
|
2622
|
+
const sorted = [...entries].sort((a, b2) => this.comparator.asc(a[1], b2[1]));
|
|
2623
|
+
const grouped = [];
|
|
2624
|
+
for (let i = 0, len = sorted.length; i < len; i++) {
|
|
2625
|
+
const [key, value] = sorted[i];
|
|
2626
|
+
const last = grouped[grouped.length - 1];
|
|
2627
|
+
if (last && this.comparator.isSame(last.value, value)) {
|
|
2628
|
+
if (!last.keys.includes(key)) {
|
|
2629
|
+
last.keys.push(key);
|
|
2630
|
+
}
|
|
2631
|
+
} else {
|
|
2632
|
+
grouped.push({ keys: [key], value });
|
|
2633
|
+
}
|
|
2634
|
+
}
|
|
2635
|
+
this._deleteNode(root);
|
|
2636
|
+
const maxLeafSize = this.order - 1;
|
|
2637
|
+
const leaves = [];
|
|
2638
|
+
for (let i = 0, len = grouped.length; i < len; i += maxLeafSize) {
|
|
2639
|
+
const chunk = grouped.slice(i, i + maxLeafSize);
|
|
2640
|
+
const leafKeys = chunk.map((g2) => g2.keys);
|
|
2641
|
+
const leafValues = chunk.map((g2) => g2.value);
|
|
2642
|
+
const leaf = this._createNode(
|
|
2643
|
+
true,
|
|
2644
|
+
leafKeys,
|
|
2645
|
+
leafValues,
|
|
2646
|
+
null,
|
|
2647
|
+
null,
|
|
2648
|
+
null
|
|
2649
|
+
);
|
|
2650
|
+
leaves.push(leaf);
|
|
2651
|
+
}
|
|
2652
|
+
for (let i = 0, len = leaves.length; i < len; i++) {
|
|
2653
|
+
if (i > 0) {
|
|
2654
|
+
leaves[i].prev = leaves[i - 1].id;
|
|
2655
|
+
}
|
|
2656
|
+
if (i < len - 1) {
|
|
2657
|
+
leaves[i].next = leaves[i + 1].id;
|
|
2658
|
+
}
|
|
2659
|
+
this._updateNode(leaves[i]);
|
|
2660
|
+
}
|
|
2661
|
+
let currentLevel = leaves;
|
|
2662
|
+
while (currentLevel.length > 1) {
|
|
2663
|
+
const nextLevel = [];
|
|
2664
|
+
for (let i = 0, len = currentLevel.length; i < len; i += this.order) {
|
|
2665
|
+
const children = currentLevel.slice(i, i + this.order);
|
|
2666
|
+
const childIds = children.map((c) => c.id);
|
|
2667
|
+
const separators = [];
|
|
2668
|
+
for (let j = 1, len2 = children.length; j < len2; j++) {
|
|
2669
|
+
separators.push(children[j].values[0]);
|
|
2670
|
+
}
|
|
2671
|
+
const internalNode = this._createNode(
|
|
2672
|
+
false,
|
|
2673
|
+
childIds,
|
|
2674
|
+
separators,
|
|
2675
|
+
null,
|
|
2676
|
+
null,
|
|
2677
|
+
null
|
|
2678
|
+
);
|
|
2679
|
+
for (let j = 0, len2 = children.length; j < len2; j++) {
|
|
2680
|
+
const child = children[j];
|
|
2681
|
+
child.parent = internalNode.id;
|
|
2682
|
+
this._updateNode(child);
|
|
2683
|
+
}
|
|
2684
|
+
nextLevel.push(internalNode);
|
|
2685
|
+
}
|
|
2686
|
+
currentLevel = nextLevel;
|
|
2687
|
+
}
|
|
2688
|
+
const newRoot = currentLevel[0];
|
|
2689
|
+
this._writeHead({
|
|
2690
|
+
root: newRoot.id,
|
|
2691
|
+
order: this.order,
|
|
2692
|
+
data: this.strategy.head.data
|
|
2693
|
+
});
|
|
2694
|
+
}
|
|
2616
2695
|
_deleteEntry(node, key) {
|
|
2617
2696
|
if (!node.leaf) {
|
|
2618
2697
|
let keyIndex = -1;
|
|
@@ -2716,7 +2795,8 @@ var require_cjs = __commonJS({
|
|
|
2716
2795
|
siblingNode.values.push(...node.values);
|
|
2717
2796
|
if (!siblingNode.leaf) {
|
|
2718
2797
|
const keys = siblingNode.keys;
|
|
2719
|
-
for (
|
|
2798
|
+
for (let i = 0, len = keys.length; i < len; i++) {
|
|
2799
|
+
const key2 = keys[i];
|
|
2720
2800
|
const node2 = this._cloneNode(this.getNode(key2));
|
|
2721
2801
|
node2.parent = siblingNode.id;
|
|
2722
2802
|
this._updateNode(node2);
|
|
@@ -2784,21 +2864,24 @@ var require_cjs = __commonJS({
|
|
|
2784
2864
|
this._updateNode(siblingNode);
|
|
2785
2865
|
}
|
|
2786
2866
|
if (!siblingNode.leaf) {
|
|
2787
|
-
for (
|
|
2867
|
+
for (let i = 0, len = siblingNode.keys.length; i < len; i++) {
|
|
2868
|
+
const key2 = siblingNode.keys[i];
|
|
2788
2869
|
const n = this._cloneNode(this.getNode(key2));
|
|
2789
2870
|
n.parent = siblingNode.id;
|
|
2790
2871
|
this._updateNode(n);
|
|
2791
2872
|
}
|
|
2792
2873
|
}
|
|
2793
2874
|
if (!node.leaf) {
|
|
2794
|
-
for (
|
|
2875
|
+
for (let i = 0, len = node.keys.length; i < len; i++) {
|
|
2876
|
+
const key2 = node.keys[i];
|
|
2795
2877
|
const n = this._cloneNode(this.getNode(key2));
|
|
2796
2878
|
n.parent = node.id;
|
|
2797
2879
|
this._updateNode(n);
|
|
2798
2880
|
}
|
|
2799
2881
|
}
|
|
2800
2882
|
if (!parentNode.leaf) {
|
|
2801
|
-
for (
|
|
2883
|
+
for (let i = 0, len = parentNode.keys.length; i < len; i++) {
|
|
2884
|
+
const key2 = parentNode.keys[i];
|
|
2802
2885
|
const n = this._cloneNode(this.getNode(key2));
|
|
2803
2886
|
n.parent = parentNode.id;
|
|
2804
2887
|
this._updateNode(n);
|
|
@@ -2972,6 +3055,14 @@ var require_cjs = __commonJS({
|
|
|
2972
3055
|
throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
|
|
2973
3056
|
}
|
|
2974
3057
|
}
|
|
3058
|
+
bulkLoad(entries) {
|
|
3059
|
+
const tx = this.createTransaction();
|
|
3060
|
+
tx.bulkLoad(entries);
|
|
3061
|
+
const result = tx.commit();
|
|
3062
|
+
if (!result.success) {
|
|
3063
|
+
throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
2975
3066
|
};
|
|
2976
3067
|
var Ryoiki2 = class _Ryoiki2 {
|
|
2977
3068
|
readings;
|
|
@@ -3229,7 +3320,7 @@ var require_cjs = __commonJS({
|
|
|
3229
3320
|
this._free(this.writings, lockId);
|
|
3230
3321
|
}
|
|
3231
3322
|
};
|
|
3232
|
-
var
|
|
3323
|
+
var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
3233
3324
|
lock;
|
|
3234
3325
|
constructor(rootTx, mvccRoot, mvcc, strategy, comparator, option) {
|
|
3235
3326
|
super(
|
|
@@ -3385,12 +3476,8 @@ var require_cjs = __commonJS({
|
|
|
3385
3476
|
const midValue = parentNode.values[mid];
|
|
3386
3477
|
parentNode.values = parentNode.values.slice(0, mid);
|
|
3387
3478
|
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
3388
|
-
for (
|
|
3389
|
-
const
|
|
3390
|
-
n.parent = parentNode.id;
|
|
3391
|
-
await this._updateNode(n);
|
|
3392
|
-
}
|
|
3393
|
-
for (const k2 of newSiblingNodeRecursive.keys) {
|
|
3479
|
+
for (let i = 0, len = newSiblingNodeRecursive.keys.length; i < len; i++) {
|
|
3480
|
+
const k2 = newSiblingNodeRecursive.keys[i];
|
|
3394
3481
|
const n = this._cloneNode(await this.getNode(k2));
|
|
3395
3482
|
n.parent = newSiblingNodeRecursive.id;
|
|
3396
3483
|
await this._updateNode(n);
|
|
@@ -3482,7 +3569,7 @@ var require_cjs = __commonJS({
|
|
|
3482
3569
|
for (let i = 0; i < len; i++) {
|
|
3483
3570
|
const nValue = node.values[i];
|
|
3484
3571
|
const keys = node.keys[i];
|
|
3485
|
-
for (let j = 0,
|
|
3572
|
+
for (let j = 0, len2 = keys.length; j < len2; j++) {
|
|
3486
3573
|
yield [keys[j], nValue];
|
|
3487
3574
|
}
|
|
3488
3575
|
}
|
|
@@ -3560,7 +3647,7 @@ var require_cjs = __commonJS({
|
|
|
3560
3647
|
while (true) {
|
|
3561
3648
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
3562
3649
|
const keys = node.keys[i];
|
|
3563
|
-
for (let j = 0,
|
|
3650
|
+
for (let j = 0, len2 = keys.length; j < len2; j++) {
|
|
3564
3651
|
if (keys[j] === key) {
|
|
3565
3652
|
return node.values[i];
|
|
3566
3653
|
}
|
|
@@ -3672,8 +3759,16 @@ var require_cjs = __commonJS({
|
|
|
3672
3759
|
const sorted = [...entries].sort((a, b2) => this.comparator.asc(a[1], b2[1]));
|
|
3673
3760
|
let currentLeaf = null;
|
|
3674
3761
|
let modified = false;
|
|
3675
|
-
|
|
3676
|
-
|
|
3762
|
+
let cachedLeafId = null;
|
|
3763
|
+
let cachedLeafMaxValue = null;
|
|
3764
|
+
for (let i = 0, len = sorted.length; i < len; i++) {
|
|
3765
|
+
const [key, value] = sorted[i];
|
|
3766
|
+
let targetLeaf;
|
|
3767
|
+
if (cachedLeafId !== null && cachedLeafMaxValue !== null && currentLeaf !== null && (this.comparator.isLower(value, cachedLeafMaxValue) || this.comparator.isSame(value, cachedLeafMaxValue))) {
|
|
3768
|
+
targetLeaf = currentLeaf;
|
|
3769
|
+
} else {
|
|
3770
|
+
targetLeaf = await this.locateLeaf(value);
|
|
3771
|
+
}
|
|
3677
3772
|
if (currentLeaf !== null && currentLeaf.id === targetLeaf.id) {
|
|
3678
3773
|
} else {
|
|
3679
3774
|
if (currentLeaf !== null && modified) {
|
|
@@ -3682,8 +3777,10 @@ var require_cjs = __commonJS({
|
|
|
3682
3777
|
currentLeaf = this._cloneNode(targetLeaf);
|
|
3683
3778
|
modified = false;
|
|
3684
3779
|
}
|
|
3780
|
+
cachedLeafId = currentLeaf.id;
|
|
3685
3781
|
const changed = this._insertValueIntoLeaf(currentLeaf, key, value);
|
|
3686
3782
|
modified = modified || changed;
|
|
3783
|
+
cachedLeafMaxValue = currentLeaf.values[currentLeaf.values.length - 1];
|
|
3687
3784
|
if (currentLeaf.values.length === this.order) {
|
|
3688
3785
|
await this._updateNode(currentLeaf);
|
|
3689
3786
|
let after = await this._createNode(
|
|
@@ -3704,6 +3801,8 @@ var require_cjs = __commonJS({
|
|
|
3704
3801
|
await this._updateNode(after);
|
|
3705
3802
|
await this._insertInParent(currentLeaf, after.values[0], after);
|
|
3706
3803
|
currentLeaf = null;
|
|
3804
|
+
cachedLeafId = null;
|
|
3805
|
+
cachedLeafMaxValue = null;
|
|
3707
3806
|
modified = false;
|
|
3708
3807
|
}
|
|
3709
3808
|
}
|
|
@@ -3712,6 +3811,87 @@ var require_cjs = __commonJS({
|
|
|
3712
3811
|
}
|
|
3713
3812
|
});
|
|
3714
3813
|
}
|
|
3814
|
+
async bulkLoad(entries) {
|
|
3815
|
+
if (entries.length === 0) return;
|
|
3816
|
+
return this.writeLock(0, async () => {
|
|
3817
|
+
const root = await this.getNode(this.rootId);
|
|
3818
|
+
if (!root.leaf || root.values.length > 0) {
|
|
3819
|
+
throw new Error("bulkLoad can only be called on an empty tree. Use batchInsert for non-empty trees.");
|
|
3820
|
+
}
|
|
3821
|
+
const sorted = [...entries].sort((a, b2) => this.comparator.asc(a[1], b2[1]));
|
|
3822
|
+
const grouped = [];
|
|
3823
|
+
for (let i = 0, len = sorted.length; i < len; i++) {
|
|
3824
|
+
const [key, value] = sorted[i];
|
|
3825
|
+
const last = grouped[grouped.length - 1];
|
|
3826
|
+
if (last && this.comparator.isSame(last.value, value)) {
|
|
3827
|
+
if (!last.keys.includes(key)) {
|
|
3828
|
+
last.keys.push(key);
|
|
3829
|
+
}
|
|
3830
|
+
} else {
|
|
3831
|
+
grouped.push({ keys: [key], value });
|
|
3832
|
+
}
|
|
3833
|
+
}
|
|
3834
|
+
await this._deleteNode(root);
|
|
3835
|
+
const maxLeafSize = this.order - 1;
|
|
3836
|
+
const leaves = [];
|
|
3837
|
+
for (let i = 0, len = grouped.length; i < len; i += maxLeafSize) {
|
|
3838
|
+
const chunk = grouped.slice(i, i + maxLeafSize);
|
|
3839
|
+
const leafKeys = chunk.map((g2) => g2.keys);
|
|
3840
|
+
const leafValues = chunk.map((g2) => g2.value);
|
|
3841
|
+
const leaf = await this._createNode(
|
|
3842
|
+
true,
|
|
3843
|
+
leafKeys,
|
|
3844
|
+
leafValues,
|
|
3845
|
+
null,
|
|
3846
|
+
null,
|
|
3847
|
+
null
|
|
3848
|
+
);
|
|
3849
|
+
leaves.push(leaf);
|
|
3850
|
+
}
|
|
3851
|
+
for (let i = 0, len = leaves.length; i < len; i++) {
|
|
3852
|
+
if (i > 0) {
|
|
3853
|
+
leaves[i].prev = leaves[i - 1].id;
|
|
3854
|
+
}
|
|
3855
|
+
if (i < len - 1) {
|
|
3856
|
+
leaves[i].next = leaves[i + 1].id;
|
|
3857
|
+
}
|
|
3858
|
+
await this._updateNode(leaves[i]);
|
|
3859
|
+
}
|
|
3860
|
+
let currentLevel = leaves;
|
|
3861
|
+
while (currentLevel.length > 1) {
|
|
3862
|
+
const nextLevel = [];
|
|
3863
|
+
for (let i = 0, len = currentLevel.length; i < len; i += this.order) {
|
|
3864
|
+
const children = currentLevel.slice(i, i + this.order);
|
|
3865
|
+
const childIds = children.map((c) => c.id);
|
|
3866
|
+
const separators = [];
|
|
3867
|
+
for (let j = 1, len2 = children.length; j < len2; j++) {
|
|
3868
|
+
separators.push(children[j].values[0]);
|
|
3869
|
+
}
|
|
3870
|
+
const internalNode = await this._createNode(
|
|
3871
|
+
false,
|
|
3872
|
+
childIds,
|
|
3873
|
+
separators,
|
|
3874
|
+
null,
|
|
3875
|
+
null,
|
|
3876
|
+
null
|
|
3877
|
+
);
|
|
3878
|
+
for (let j = 0, len2 = children.length; j < len2; j++) {
|
|
3879
|
+
const child = children[j];
|
|
3880
|
+
child.parent = internalNode.id;
|
|
3881
|
+
await this._updateNode(child);
|
|
3882
|
+
}
|
|
3883
|
+
nextLevel.push(internalNode);
|
|
3884
|
+
}
|
|
3885
|
+
currentLevel = nextLevel;
|
|
3886
|
+
}
|
|
3887
|
+
const newRoot = currentLevel[0];
|
|
3888
|
+
await this._writeHead({
|
|
3889
|
+
root: newRoot.id,
|
|
3890
|
+
order: this.order,
|
|
3891
|
+
data: this.strategy.head.data
|
|
3892
|
+
});
|
|
3893
|
+
});
|
|
3894
|
+
}
|
|
3715
3895
|
async _deleteEntry(node, key) {
|
|
3716
3896
|
if (!node.leaf) {
|
|
3717
3897
|
let keyIndex = -1;
|
|
@@ -3815,7 +3995,8 @@ var require_cjs = __commonJS({
|
|
|
3815
3995
|
siblingNode.values.push(...node.values);
|
|
3816
3996
|
if (!siblingNode.leaf) {
|
|
3817
3997
|
const keys = siblingNode.keys;
|
|
3818
|
-
for (
|
|
3998
|
+
for (let i = 0, len = keys.length; i < len; i++) {
|
|
3999
|
+
const key2 = keys[i];
|
|
3819
4000
|
const node2 = this._cloneNode(await this.getNode(key2));
|
|
3820
4001
|
node2.parent = siblingNode.id;
|
|
3821
4002
|
await this._updateNode(node2);
|
|
@@ -3883,21 +4064,24 @@ var require_cjs = __commonJS({
|
|
|
3883
4064
|
await this._updateNode(siblingNode);
|
|
3884
4065
|
}
|
|
3885
4066
|
if (!siblingNode.leaf) {
|
|
3886
|
-
for (
|
|
4067
|
+
for (let i = 0, len = siblingNode.keys.length; i < len; i++) {
|
|
4068
|
+
const key2 = siblingNode.keys[i];
|
|
3887
4069
|
const n = this._cloneNode(await this.getNode(key2));
|
|
3888
4070
|
n.parent = siblingNode.id;
|
|
3889
4071
|
await this._updateNode(n);
|
|
3890
4072
|
}
|
|
3891
4073
|
}
|
|
3892
4074
|
if (!node.leaf) {
|
|
3893
|
-
for (
|
|
4075
|
+
for (let i = 0, len = node.keys.length; i < len; i++) {
|
|
4076
|
+
const key2 = node.keys[i];
|
|
3894
4077
|
const n = this._cloneNode(await this.getNode(key2));
|
|
3895
4078
|
n.parent = node.id;
|
|
3896
4079
|
await this._updateNode(n);
|
|
3897
4080
|
}
|
|
3898
4081
|
}
|
|
3899
4082
|
if (!parentNode.leaf) {
|
|
3900
|
-
for (
|
|
4083
|
+
for (let i = 0, len = parentNode.keys.length; i < len; i++) {
|
|
4084
|
+
const key2 = parentNode.keys[i];
|
|
3901
4085
|
const n = this._cloneNode(await this.getNode(key2));
|
|
3902
4086
|
n.parent = parentNode.id;
|
|
3903
4087
|
await this._updateNode(n);
|
|
@@ -4018,7 +4202,7 @@ var require_cjs = __commonJS({
|
|
|
4018
4202
|
}
|
|
4019
4203
|
}
|
|
4020
4204
|
};
|
|
4021
|
-
var BPTreeAsync2 = class extends
|
|
4205
|
+
var BPTreeAsync2 = class extends BPTreeAsyncTransaction {
|
|
4022
4206
|
constructor(strategy, comparator, option) {
|
|
4023
4207
|
const mvccRoot = new AsyncMVCCTransaction(new BPTreeMVCCStrategyAsync(strategy), {
|
|
4024
4208
|
cacheCapacity: option?.capacity ?? void 0
|
|
@@ -4038,7 +4222,7 @@ var require_cjs = __commonJS({
|
|
|
4038
4222
|
*/
|
|
4039
4223
|
async createTransaction() {
|
|
4040
4224
|
const nestedTx = this.mvcc.createNested();
|
|
4041
|
-
const tx = new
|
|
4225
|
+
const tx = new BPTreeAsyncTransaction(
|
|
4042
4226
|
this,
|
|
4043
4227
|
this.mvcc,
|
|
4044
4228
|
nestedTx,
|
|
@@ -4079,6 +4263,16 @@ var require_cjs = __commonJS({
|
|
|
4079
4263
|
}
|
|
4080
4264
|
});
|
|
4081
4265
|
}
|
|
4266
|
+
async bulkLoad(entries) {
|
|
4267
|
+
return this.writeLock(1, async () => {
|
|
4268
|
+
const tx = await this.createTransaction();
|
|
4269
|
+
await tx.bulkLoad(entries);
|
|
4270
|
+
const result = await tx.commit();
|
|
4271
|
+
if (!result.success) {
|
|
4272
|
+
throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
|
|
4273
|
+
}
|
|
4274
|
+
});
|
|
4275
|
+
}
|
|
4082
4276
|
};
|
|
4083
4277
|
var SerializeStrategy = class {
|
|
4084
4278
|
order;
|
|
@@ -8065,12 +8259,14 @@ var require_cjs = __commonJS({
|
|
|
8065
8259
|
buffer;
|
|
8066
8260
|
view;
|
|
8067
8261
|
totalWrittenPages = 0;
|
|
8262
|
+
logger;
|
|
8068
8263
|
/**
|
|
8069
8264
|
* Constructor
|
|
8070
8265
|
* @param walFilePath WAL file path
|
|
8071
8266
|
* @param pageSize Page size
|
|
8267
|
+
* @param logger Logger instance
|
|
8072
8268
|
*/
|
|
8073
|
-
constructor(walFilePath, pageSize) {
|
|
8269
|
+
constructor(walFilePath, pageSize, logger) {
|
|
8074
8270
|
if ((pageSize & pageSize - 1) !== 0) {
|
|
8075
8271
|
throw new Error("Page size must be a power of 2");
|
|
8076
8272
|
}
|
|
@@ -8079,6 +8275,7 @@ var require_cjs = __commonJS({
|
|
|
8079
8275
|
this.entrySize = 4 + pageSize;
|
|
8080
8276
|
this.buffer = new Uint8Array(this.entrySize);
|
|
8081
8277
|
this.view = new DataView(this.buffer.buffer);
|
|
8278
|
+
this.logger = logger;
|
|
8082
8279
|
}
|
|
8083
8280
|
/**
|
|
8084
8281
|
* Opens the log file.
|
|
@@ -8106,11 +8303,11 @@ var require_cjs = __commonJS({
|
|
|
8106
8303
|
try {
|
|
8107
8304
|
const manager = new PageManagerFactory().getManager(data);
|
|
8108
8305
|
if (!manager.verifyChecksum(data)) {
|
|
8109
|
-
|
|
8306
|
+
this.logger.warn(`Checksum verification failed for PageID ${pageId} during recovery. Ignoring changes.`);
|
|
8110
8307
|
continue;
|
|
8111
8308
|
}
|
|
8112
8309
|
} catch (e) {
|
|
8113
|
-
|
|
8310
|
+
this.logger.warn(`Failed to verify checksum for PageID ${pageId} during recovery: ${e}. Ignoring changes.`);
|
|
8114
8311
|
continue;
|
|
8115
8312
|
}
|
|
8116
8313
|
promises.push(writePage(pageId, data));
|
|
@@ -8423,20 +8620,22 @@ var require_cjs = __commonJS({
|
|
|
8423
8620
|
* @param pageCacheCapacity 페이지 캐시 크기
|
|
8424
8621
|
* @param options 데이터플라이 옵션
|
|
8425
8622
|
*/
|
|
8426
|
-
constructor(fileHandle, pageSize, pageCacheCapacity, options) {
|
|
8623
|
+
constructor(fileHandle, pageSize, pageCacheCapacity, options, logger, walLogger) {
|
|
8427
8624
|
this.fileHandle = fileHandle;
|
|
8428
8625
|
this.pageSize = pageSize;
|
|
8429
8626
|
this.pageCacheCapacity = pageCacheCapacity;
|
|
8430
8627
|
this.options = options;
|
|
8431
8628
|
const walPath = options.wal;
|
|
8432
|
-
this.walManager = walPath ? new WALManager(walPath, pageSize) : null;
|
|
8629
|
+
this.walManager = walPath && walLogger ? new WALManager(walPath, pageSize, walLogger) : null;
|
|
8433
8630
|
this.pageManagerFactory = new PageManagerFactory();
|
|
8434
8631
|
this.pageStrategy = new PageMVCCStrategy(fileHandle, pageSize, pageCacheCapacity);
|
|
8632
|
+
this.logger = logger;
|
|
8435
8633
|
}
|
|
8436
8634
|
pageFactory = new PageManagerFactory();
|
|
8437
8635
|
walManager;
|
|
8438
8636
|
pageManagerFactory;
|
|
8439
8637
|
pageStrategy;
|
|
8638
|
+
logger;
|
|
8440
8639
|
/** 글로벌 동기화(체크포인트/커밋)를 위한 Mutex */
|
|
8441
8640
|
lockPromise = Promise.resolve();
|
|
8442
8641
|
/**
|
|
@@ -8461,7 +8660,9 @@ var require_cjs = __commonJS({
|
|
|
8461
8660
|
* Performs WAL recovery if necessary.
|
|
8462
8661
|
*/
|
|
8463
8662
|
async init() {
|
|
8663
|
+
this.logger.info("Initializing");
|
|
8464
8664
|
if (this.walManager) {
|
|
8665
|
+
this.logger.debug("WALManager found, starting recovery");
|
|
8465
8666
|
await this.walManager.recover(async (pageId, data) => {
|
|
8466
8667
|
await this.pageStrategy.write(pageId, data);
|
|
8467
8668
|
});
|
|
@@ -8633,6 +8834,7 @@ var require_cjs = __commonJS({
|
|
|
8633
8834
|
* @returns Created or reused page ID
|
|
8634
8835
|
*/
|
|
8635
8836
|
async appendNewPage(pageType = PageManager.CONSTANT.PAGE_TYPE_EMPTY, tx) {
|
|
8837
|
+
this.logger.debug(`Appending new page of type ${pageType}`);
|
|
8636
8838
|
await tx.__acquireWriteLock(0);
|
|
8637
8839
|
const metadata = await this.getMetadata(tx);
|
|
8638
8840
|
const metadataManager = this.pageFactory.getManager(metadata);
|
|
@@ -8736,6 +8938,7 @@ var require_cjs = __commonJS({
|
|
|
8736
8938
|
* @param tx Transaction
|
|
8737
8939
|
*/
|
|
8738
8940
|
async freeChain(startPageId, tx) {
|
|
8941
|
+
this.logger.debug(`Freeing chain starting at page ${startPageId}`);
|
|
8739
8942
|
let currentPageId = startPageId;
|
|
8740
8943
|
const visited = /* @__PURE__ */ new Set();
|
|
8741
8944
|
while (currentPageId !== -1 && currentPageId !== 0) {
|
|
@@ -8775,6 +8978,7 @@ var require_cjs = __commonJS({
|
|
|
8775
8978
|
*/
|
|
8776
8979
|
async commitToWAL(dirtyPages) {
|
|
8777
8980
|
if (this.walManager) {
|
|
8981
|
+
this.logger.debug(`Committing ${dirtyPages.size} pages to WAL`);
|
|
8778
8982
|
await this.walManager.prepareCommit(dirtyPages);
|
|
8779
8983
|
await this.walManager.finalizeCommit(true);
|
|
8780
8984
|
}
|
|
@@ -8786,6 +8990,7 @@ var require_cjs = __commonJS({
|
|
|
8786
8990
|
* 3. WAL 로그 파일 비우기 (Clear/Truncate)
|
|
8787
8991
|
*/
|
|
8788
8992
|
async checkpoint() {
|
|
8993
|
+
this.logger.info("Starting checkpoint");
|
|
8789
8994
|
await this.runGlobalLock(async () => {
|
|
8790
8995
|
await this.pageStrategy.flush();
|
|
8791
8996
|
await this.pageStrategy.sync();
|
|
@@ -8798,6 +9003,7 @@ var require_cjs = __commonJS({
|
|
|
8798
9003
|
* Closes the page file system.
|
|
8799
9004
|
*/
|
|
8800
9005
|
async close() {
|
|
9006
|
+
this.logger.info("Closing");
|
|
8801
9007
|
await this.checkpoint();
|
|
8802
9008
|
if (this.walManager) {
|
|
8803
9009
|
this.walManager.close();
|
|
@@ -9029,7 +9235,7 @@ var require_cjs = __commonJS({
|
|
|
9029
9235
|
}
|
|
9030
9236
|
};
|
|
9031
9237
|
var RowTableEngine = class {
|
|
9032
|
-
constructor(pfs, txContext, options) {
|
|
9238
|
+
constructor(pfs, txContext, options, logger) {
|
|
9033
9239
|
this.pfs = pfs;
|
|
9034
9240
|
this.txContext = txContext;
|
|
9035
9241
|
this.options = options;
|
|
@@ -9039,6 +9245,7 @@ var require_cjs = __commonJS({
|
|
|
9039
9245
|
this.overflowPageManager = this.factory.getManagerFromType(OverflowPageManager.CONSTANT.PAGE_TYPE_OVERFLOW);
|
|
9040
9246
|
this.rowManager = new Row();
|
|
9041
9247
|
this.keyManager = new KeyManager();
|
|
9248
|
+
this.logger = logger;
|
|
9042
9249
|
this.ridBuffer = new Uint8Array(Row.CONSTANT.SIZE_RID);
|
|
9043
9250
|
this.pageIdBuffer = new Uint8Array(DataPageManager.CONSTANT.SIZE_PAGE_ID);
|
|
9044
9251
|
this.maxBodySize = this.pfs.pageSize - DataPageManager.CONSTANT.SIZE_PAGE_HEADER;
|
|
@@ -9067,6 +9274,7 @@ var require_cjs = __commonJS({
|
|
|
9067
9274
|
maxBodySize;
|
|
9068
9275
|
ridBuffer;
|
|
9069
9276
|
pageIdBuffer;
|
|
9277
|
+
logger;
|
|
9070
9278
|
initialized = false;
|
|
9071
9279
|
/**
|
|
9072
9280
|
* Retrieves the BPTree transaction associated with the given transaction.
|
|
@@ -9101,6 +9309,7 @@ var require_cjs = __commonJS({
|
|
|
9101
9309
|
*/
|
|
9102
9310
|
async init() {
|
|
9103
9311
|
if (!this.initialized) {
|
|
9312
|
+
this.logger.info("Initializing B+ Tree");
|
|
9104
9313
|
await this.bptree.init();
|
|
9105
9314
|
this.initialized = true;
|
|
9106
9315
|
}
|
|
@@ -9148,6 +9357,7 @@ var require_cjs = __commonJS({
|
|
|
9148
9357
|
* @returns Metadata
|
|
9149
9358
|
*/
|
|
9150
9359
|
async getMetadata(tx) {
|
|
9360
|
+
this.logger.debug("Getting metadata");
|
|
9151
9361
|
if (!this.initialized) {
|
|
9152
9362
|
throw new Error("RowTableEngine instance is not initialized");
|
|
9153
9363
|
}
|
|
@@ -9173,6 +9383,7 @@ var require_cjs = __commonJS({
|
|
|
9173
9383
|
* @returns Array of PKs of the inserted data
|
|
9174
9384
|
*/
|
|
9175
9385
|
async insert(dataList, incrementRowCount, overflowForcly, tx) {
|
|
9386
|
+
this.logger.debug(`Inserting ${dataList.length} rows (overflowForcly: ${overflowForcly})`);
|
|
9176
9387
|
if (dataList.length === 0) {
|
|
9177
9388
|
return [];
|
|
9178
9389
|
}
|
|
@@ -9274,6 +9485,7 @@ var require_cjs = __commonJS({
|
|
|
9274
9485
|
* @param tx Transaction
|
|
9275
9486
|
*/
|
|
9276
9487
|
async update(pk, data, tx) {
|
|
9488
|
+
this.logger.debug(`Updating row with PK: ${pk}`);
|
|
9277
9489
|
await tx.__acquireWriteLock(0);
|
|
9278
9490
|
const rid = await this.getRidByPK(pk, tx);
|
|
9279
9491
|
if (rid === null) {
|
|
@@ -9359,6 +9571,7 @@ var require_cjs = __commonJS({
|
|
|
9359
9571
|
* @param tx Transaction
|
|
9360
9572
|
*/
|
|
9361
9573
|
async delete(pk, decrementRowCount, tx) {
|
|
9574
|
+
this.logger.debug(`Deleting row with PK: ${pk}`);
|
|
9362
9575
|
await tx.__acquireWriteLock(0);
|
|
9363
9576
|
const rid = await this.getRidByPK(pk, tx);
|
|
9364
9577
|
if (rid === null) {
|
|
@@ -9418,6 +9631,7 @@ var require_cjs = __commonJS({
|
|
|
9418
9631
|
* @returns Raw data of the row
|
|
9419
9632
|
*/
|
|
9420
9633
|
async selectByPK(pk, tx) {
|
|
9634
|
+
this.logger.debug(`Selecting row by PK: ${pk}`);
|
|
9421
9635
|
const rid = await this.getRidByPK(pk, tx);
|
|
9422
9636
|
if (rid === null) {
|
|
9423
9637
|
return null;
|
|
@@ -9432,6 +9646,7 @@ var require_cjs = __commonJS({
|
|
|
9432
9646
|
* @returns Array of raw data of the rows in the same order as input PKs
|
|
9433
9647
|
*/
|
|
9434
9648
|
async selectMany(pks, tx) {
|
|
9649
|
+
this.logger.debug(`Selecting many rows (${pks.length} PKs)`);
|
|
9435
9650
|
const collections = await this.collectItemsByPage(pks, tx);
|
|
9436
9651
|
return this.fetchRowsByRids(collections, pks.length, tx);
|
|
9437
9652
|
}
|
|
@@ -9810,25 +10025,99 @@ var require_cjs = __commonJS({
|
|
|
9810
10025
|
return this.storage.run(tx, callback);
|
|
9811
10026
|
}
|
|
9812
10027
|
};
|
|
10028
|
+
var Colors = {
|
|
10029
|
+
reset: "\x1B[0m",
|
|
10030
|
+
debug: "\x1B[36m",
|
|
10031
|
+
// Cyan
|
|
10032
|
+
info: "\x1B[32m",
|
|
10033
|
+
// Green
|
|
10034
|
+
warn: "\x1B[33m",
|
|
10035
|
+
// Yellow
|
|
10036
|
+
error: "\x1B[31m",
|
|
10037
|
+
// Red
|
|
10038
|
+
white: "\x1B[37m",
|
|
10039
|
+
// White
|
|
10040
|
+
grey: "\x1B[90m"
|
|
10041
|
+
// Grey
|
|
10042
|
+
};
|
|
10043
|
+
var LoggerManager = class {
|
|
10044
|
+
level;
|
|
10045
|
+
constructor(level = 2) {
|
|
10046
|
+
this.level = level;
|
|
10047
|
+
}
|
|
10048
|
+
setLevel(level) {
|
|
10049
|
+
this.level = level;
|
|
10050
|
+
}
|
|
10051
|
+
shouldLog(level) {
|
|
10052
|
+
if (this.level === 0) return false;
|
|
10053
|
+
return level >= this.level;
|
|
10054
|
+
}
|
|
10055
|
+
create(moduleName) {
|
|
10056
|
+
return new Logger(this, moduleName);
|
|
10057
|
+
}
|
|
10058
|
+
};
|
|
10059
|
+
var Logger = class {
|
|
10060
|
+
constructor(parent, moduleName) {
|
|
10061
|
+
this.parent = parent;
|
|
10062
|
+
this.moduleName = moduleName;
|
|
10063
|
+
}
|
|
10064
|
+
debug(message, ...args) {
|
|
10065
|
+
if (this.parent.shouldLog(
|
|
10066
|
+
1
|
|
10067
|
+
/* Debug */
|
|
10068
|
+
)) {
|
|
10069
|
+
console.debug(`${Colors.debug}[DEBUG] [${this.moduleName}]${Colors.reset} ${Colors.white}${message}${Colors.reset}`, ...args);
|
|
10070
|
+
}
|
|
10071
|
+
}
|
|
10072
|
+
info(message, ...args) {
|
|
10073
|
+
if (this.parent.shouldLog(
|
|
10074
|
+
2
|
|
10075
|
+
/* Info */
|
|
10076
|
+
)) {
|
|
10077
|
+
console.info(`${Colors.info}[INFO] [${this.moduleName}]${Colors.reset} ${Colors.white}${message}${Colors.reset}`, ...args);
|
|
10078
|
+
}
|
|
10079
|
+
}
|
|
10080
|
+
warn(message, ...args) {
|
|
10081
|
+
if (this.parent.shouldLog(
|
|
10082
|
+
3
|
|
10083
|
+
/* Warning */
|
|
10084
|
+
)) {
|
|
10085
|
+
console.warn(`${Colors.warn}[WARN] [${this.moduleName}]${Colors.reset} ${Colors.white}${message}${Colors.reset}`, ...args);
|
|
10086
|
+
}
|
|
10087
|
+
}
|
|
10088
|
+
error(message, ...args) {
|
|
10089
|
+
if (this.parent.shouldLog(
|
|
10090
|
+
4
|
|
10091
|
+
/* Error */
|
|
10092
|
+
)) {
|
|
10093
|
+
console.error(`${Colors.error}[ERROR] [${this.moduleName}]${Colors.reset} ${Colors.white}${message}${Colors.reset}`, ...args);
|
|
10094
|
+
}
|
|
10095
|
+
}
|
|
10096
|
+
};
|
|
9813
10097
|
var DataplyAPI2 = class {
|
|
9814
10098
|
constructor(file, options) {
|
|
9815
10099
|
this.file = file;
|
|
9816
10100
|
this.hook = useHookall(this);
|
|
9817
10101
|
this.options = this.verboseOptions(options);
|
|
10102
|
+
this.loggerManager = new LoggerManager(this.options.logLevel);
|
|
10103
|
+
this.logger = this.loggerManager.create("DataplyAPI");
|
|
9818
10104
|
this.isNewlyCreated = !import_node_fs3.default.existsSync(file);
|
|
9819
10105
|
this.fileHandle = this.createOrOpen(file, this.options);
|
|
9820
10106
|
this.pfs = new PageFileSystem(
|
|
9821
10107
|
this.fileHandle,
|
|
9822
10108
|
this.options.pageSize,
|
|
9823
10109
|
this.options.pageCacheCapacity,
|
|
9824
|
-
this.options
|
|
10110
|
+
this.options,
|
|
10111
|
+
this.loggerManager.create("PageFileSystem"),
|
|
10112
|
+
options.wal ? this.loggerManager.create("WALManager") : void 0
|
|
9825
10113
|
);
|
|
9826
10114
|
this.textCodec = new TextCodec();
|
|
9827
10115
|
this.txContext = new TransactionContext();
|
|
9828
10116
|
this.lockManager = new LockManager();
|
|
9829
|
-
this.rowTableEngine = new RowTableEngine(this.pfs, this.txContext, this.options);
|
|
10117
|
+
this.rowTableEngine = new RowTableEngine(this.pfs, this.txContext, this.options, this.loggerManager.create("RowTableEngine"));
|
|
9830
10118
|
this.initialized = false;
|
|
9831
10119
|
this.txIdCounter = 0;
|
|
10120
|
+
this.logger.debug(`DataplyAPI instance created with file: ${file}`);
|
|
9832
10121
|
}
|
|
9833
10122
|
/**
|
|
9834
10123
|
* These are not the same options that were used when the database was created.
|
|
@@ -9850,6 +10139,10 @@ var require_cjs = __commonJS({
|
|
|
9850
10139
|
txContext;
|
|
9851
10140
|
/** Hook */
|
|
9852
10141
|
hook;
|
|
10142
|
+
/** Base Logger */
|
|
10143
|
+
loggerManager;
|
|
10144
|
+
/** Logger module for DataplyAPI */
|
|
10145
|
+
logger;
|
|
9853
10146
|
/** Whether the database was initialized via `init()` */
|
|
9854
10147
|
initialized;
|
|
9855
10148
|
/** Whether the database was created this time. */
|
|
@@ -9864,6 +10157,7 @@ var require_cjs = __commonJS({
|
|
|
9864
10157
|
* @returns Whether the page file is a valid Dataply file
|
|
9865
10158
|
*/
|
|
9866
10159
|
verifyFormat(fileHandle) {
|
|
10160
|
+
this.logger.debug(`Verifying format for file handle: ${fileHandle}`);
|
|
9867
10161
|
const size = MetadataPageManager.CONSTANT.OFFSET_MAGIC_STRING + MetadataPageManager.CONSTANT.MAGIC_STRING.length;
|
|
9868
10162
|
const metadataPage = new Uint8Array(size);
|
|
9869
10163
|
import_node_fs3.default.readSync(fileHandle, metadataPage, 0, size, 0);
|
|
@@ -9883,7 +10177,9 @@ var require_cjs = __commonJS({
|
|
|
9883
10177
|
pageCacheCapacity: 1e4,
|
|
9884
10178
|
pagePreallocationCount: 1e3,
|
|
9885
10179
|
wal: null,
|
|
9886
|
-
walCheckpointThreshold: 1e3
|
|
10180
|
+
walCheckpointThreshold: 1e3,
|
|
10181
|
+
logLevel: 2
|
|
10182
|
+
/* Info */
|
|
9887
10183
|
}, options);
|
|
9888
10184
|
}
|
|
9889
10185
|
/**
|
|
@@ -9894,6 +10190,7 @@ var require_cjs = __commonJS({
|
|
|
9894
10190
|
* @param fileHandle File handle
|
|
9895
10191
|
*/
|
|
9896
10192
|
initializeFile(file, fileHandle, options) {
|
|
10193
|
+
this.logger.info(`Initializing new dataply file: ${file}`);
|
|
9897
10194
|
const metadataPageManager = new MetadataPageManager();
|
|
9898
10195
|
const bitmapPageManager = new BitmapPageManager();
|
|
9899
10196
|
const dataPageManager = new DataPageManager();
|
|
@@ -9943,6 +10240,7 @@ var require_cjs = __commonJS({
|
|
|
9943
10240
|
* @returns File handle
|
|
9944
10241
|
*/
|
|
9945
10242
|
createOrOpen(file, options) {
|
|
10243
|
+
this.logger.info(`Opening dataply file: ${file}`);
|
|
9946
10244
|
let fileHandle;
|
|
9947
10245
|
if (options.pageCacheCapacity < 100) {
|
|
9948
10246
|
throw new Error("Page cache capacity must be at least 100");
|
|
@@ -9978,6 +10276,7 @@ var require_cjs = __commonJS({
|
|
|
9978
10276
|
* If not called, the dataply instance cannot be used.
|
|
9979
10277
|
*/
|
|
9980
10278
|
async init() {
|
|
10279
|
+
this.logger.info("Initializing DataplyAPI");
|
|
9981
10280
|
if (this.initialized) {
|
|
9982
10281
|
return;
|
|
9983
10282
|
}
|
|
@@ -9997,6 +10296,7 @@ var require_cjs = __commonJS({
|
|
|
9997
10296
|
* @returns Transaction object
|
|
9998
10297
|
*/
|
|
9999
10298
|
createTransaction() {
|
|
10299
|
+
this.logger.debug(`Creating transaction: ${this.txIdCounter + 1}`);
|
|
10000
10300
|
return new Transaction4(
|
|
10001
10301
|
++this.txIdCounter,
|
|
10002
10302
|
this.txContext,
|
|
@@ -10021,6 +10321,7 @@ var require_cjs = __commonJS({
|
|
|
10021
10321
|
* @returns A release function
|
|
10022
10322
|
*/
|
|
10023
10323
|
acquireWriteLock() {
|
|
10324
|
+
this.logger.debug("Acquiring write lock");
|
|
10024
10325
|
const previous = this.writeQueue;
|
|
10025
10326
|
let release;
|
|
10026
10327
|
this.writeQueue = new Promise((resolve) => {
|
|
@@ -10038,6 +10339,7 @@ var require_cjs = __commonJS({
|
|
|
10038
10339
|
* @returns The result of the callback.
|
|
10039
10340
|
*/
|
|
10040
10341
|
async runWithDefaultWrite(callback, tx) {
|
|
10342
|
+
this.logger.debug("Running with default write transaction");
|
|
10041
10343
|
if (!tx) {
|
|
10042
10344
|
const release = await this.acquireWriteLock();
|
|
10043
10345
|
const internalTx = this.createTransaction();
|
|
@@ -10061,6 +10363,7 @@ var require_cjs = __commonJS({
|
|
|
10061
10363
|
return result;
|
|
10062
10364
|
}
|
|
10063
10365
|
async runWithDefault(callback, tx) {
|
|
10366
|
+
this.logger.debug("Running with default transaction");
|
|
10064
10367
|
const isInternalTx = !tx;
|
|
10065
10368
|
if (!tx) {
|
|
10066
10369
|
tx = this.createTransaction();
|
|
@@ -10088,6 +10391,7 @@ var require_cjs = __commonJS({
|
|
|
10088
10391
|
* @returns An AsyncGenerator that yields values from the callback.
|
|
10089
10392
|
*/
|
|
10090
10393
|
async *streamWithDefault(callback, tx) {
|
|
10394
|
+
this.logger.debug("Streaming with default transaction");
|
|
10091
10395
|
const isInternalTx = !tx;
|
|
10092
10396
|
if (!tx) {
|
|
10093
10397
|
tx = this.createTransaction();
|
|
@@ -10115,6 +10419,7 @@ var require_cjs = __commonJS({
|
|
|
10115
10419
|
* @returns Metadata of the dataply.
|
|
10116
10420
|
*/
|
|
10117
10421
|
async getMetadata(tx) {
|
|
10422
|
+
this.logger.debug("Getting metadata");
|
|
10118
10423
|
if (!this.initialized) {
|
|
10119
10424
|
throw new Error("Dataply instance is not initialized");
|
|
10120
10425
|
}
|
|
@@ -10128,6 +10433,7 @@ var require_cjs = __commonJS({
|
|
|
10128
10433
|
* @returns PK of the added data
|
|
10129
10434
|
*/
|
|
10130
10435
|
async insert(data, incrementRowCount, tx) {
|
|
10436
|
+
this.logger.debug("Inserting data");
|
|
10131
10437
|
if (!this.initialized) {
|
|
10132
10438
|
throw new Error("Dataply instance is not initialized");
|
|
10133
10439
|
}
|
|
@@ -10148,6 +10454,7 @@ var require_cjs = __commonJS({
|
|
|
10148
10454
|
* @returns PK of the added data
|
|
10149
10455
|
*/
|
|
10150
10456
|
async insertAsOverflow(data, incrementRowCount, tx) {
|
|
10457
|
+
this.logger.debug("Inserting data as overflow");
|
|
10151
10458
|
if (!this.initialized) {
|
|
10152
10459
|
throw new Error("Dataply instance is not initialized");
|
|
10153
10460
|
}
|
|
@@ -10169,6 +10476,7 @@ var require_cjs = __commonJS({
|
|
|
10169
10476
|
* @returns Array of PKs of the added data
|
|
10170
10477
|
*/
|
|
10171
10478
|
async insertBatch(dataList, incrementRowCount, tx) {
|
|
10479
|
+
this.logger.debug(`Inserting batch data: ${dataList.length} items`);
|
|
10172
10480
|
if (!this.initialized) {
|
|
10173
10481
|
throw new Error("Dataply instance is not initialized");
|
|
10174
10482
|
}
|
|
@@ -10187,6 +10495,7 @@ var require_cjs = __commonJS({
|
|
|
10187
10495
|
* @param tx Transaction
|
|
10188
10496
|
*/
|
|
10189
10497
|
async update(pk, data, tx) {
|
|
10498
|
+
this.logger.debug(`Updating data for PK: ${pk}`);
|
|
10190
10499
|
if (!this.initialized) {
|
|
10191
10500
|
throw new Error("Dataply instance is not initialized");
|
|
10192
10501
|
}
|
|
@@ -10204,6 +10513,7 @@ var require_cjs = __commonJS({
|
|
|
10204
10513
|
* @param tx Transaction
|
|
10205
10514
|
*/
|
|
10206
10515
|
async delete(pk, decrementRowCount, tx) {
|
|
10516
|
+
this.logger.debug(`Deleting data for PK: ${pk}`);
|
|
10207
10517
|
if (!this.initialized) {
|
|
10208
10518
|
throw new Error("Dataply instance is not initialized");
|
|
10209
10519
|
}
|
|
@@ -10213,6 +10523,7 @@ var require_cjs = __commonJS({
|
|
|
10213
10523
|
}, tx);
|
|
10214
10524
|
}
|
|
10215
10525
|
async select(pk, asRaw = false, tx) {
|
|
10526
|
+
this.logger.debug(`Selecting data for PK: ${pk}`);
|
|
10216
10527
|
if (!this.initialized) {
|
|
10217
10528
|
throw new Error("Dataply instance is not initialized");
|
|
10218
10529
|
}
|
|
@@ -10224,6 +10535,7 @@ var require_cjs = __commonJS({
|
|
|
10224
10535
|
}, tx);
|
|
10225
10536
|
}
|
|
10226
10537
|
async selectMany(pks, asRaw = false, tx) {
|
|
10538
|
+
this.logger.debug(`Selecting many data: ${pks.length} keys`);
|
|
10227
10539
|
if (!this.initialized) {
|
|
10228
10540
|
throw new Error("Dataply instance is not initialized");
|
|
10229
10541
|
}
|
|
@@ -10240,6 +10552,7 @@ var require_cjs = __commonJS({
|
|
|
10240
10552
|
* Closes the dataply file.
|
|
10241
10553
|
*/
|
|
10242
10554
|
async close() {
|
|
10555
|
+
this.logger.info("Closing DataplyAPI");
|
|
10243
10556
|
if (!this.initialized) {
|
|
10244
10557
|
throw new Error("Dataply instance is not initialized");
|
|
10245
10558
|
}
|
|
@@ -10860,9 +11173,10 @@ var BinaryHeap = class {
|
|
|
10860
11173
|
|
|
10861
11174
|
// src/core/QueryManager.ts
|
|
10862
11175
|
var QueryManager = class {
|
|
10863
|
-
constructor(api, optimizer) {
|
|
11176
|
+
constructor(api, optimizer, logger) {
|
|
10864
11177
|
this.api = api;
|
|
10865
11178
|
this.optimizer = optimizer;
|
|
11179
|
+
this.logger = logger;
|
|
10866
11180
|
}
|
|
10867
11181
|
operatorConverters = {
|
|
10868
11182
|
equal: "primaryEqual",
|
|
@@ -11174,18 +11488,23 @@ var QueryManager = class {
|
|
|
11174
11488
|
async countDocuments(query, tx) {
|
|
11175
11489
|
return this.api.runWithDefault(async (tx2) => {
|
|
11176
11490
|
const pks = await this.getKeys(query);
|
|
11491
|
+
this.logger.debug(`Counted ${pks.length} documents matching query`);
|
|
11177
11492
|
return pks.length;
|
|
11178
11493
|
}, tx);
|
|
11179
11494
|
}
|
|
11180
11495
|
selectDocuments(query, options = {}, tx) {
|
|
11181
11496
|
for (const field of Object.keys(query)) {
|
|
11182
11497
|
if (!this.api.indexedFields.has(field)) {
|
|
11183
|
-
|
|
11498
|
+
const errorMsg = `Query field "${field}" is not indexed. Available indexed fields: ${Array.from(this.api.indexedFields).join(", ")}`;
|
|
11499
|
+
this.logger.error(errorMsg);
|
|
11500
|
+
throw new Error(errorMsg);
|
|
11184
11501
|
}
|
|
11185
11502
|
}
|
|
11186
11503
|
const orderBy = options.orderBy;
|
|
11187
11504
|
if (orderBy !== void 0 && !this.api.indexedFields.has(orderBy)) {
|
|
11188
|
-
|
|
11505
|
+
const errorMsg = `orderBy field "${orderBy}" is not indexed. Available indexed fields: ${Array.from(this.api.indexedFields).join(", ")}`;
|
|
11506
|
+
this.logger.error(errorMsg);
|
|
11507
|
+
throw new Error(errorMsg);
|
|
11189
11508
|
}
|
|
11190
11509
|
const {
|
|
11191
11510
|
limit = Infinity,
|
|
@@ -11282,6 +11601,7 @@ var QueryManager = class {
|
|
|
11282
11601
|
others,
|
|
11283
11602
|
tx2
|
|
11284
11603
|
)) {
|
|
11604
|
+
self.logger.debug(`Yielding sorted document: ${doc._id}`);
|
|
11285
11605
|
if (skippedCount < offset) {
|
|
11286
11606
|
skippedCount++;
|
|
11287
11607
|
continue;
|
|
@@ -11381,8 +11701,9 @@ var DocumentSerializeStrategyAsync = class extends import_dataply2.SerializeStra
|
|
|
11381
11701
|
|
|
11382
11702
|
// src/core/IndexManager.ts
|
|
11383
11703
|
var IndexManager = class {
|
|
11384
|
-
constructor(api) {
|
|
11704
|
+
constructor(api, logger) {
|
|
11385
11705
|
this.api = api;
|
|
11706
|
+
this.logger = logger;
|
|
11386
11707
|
this.trees = /* @__PURE__ */ new Map();
|
|
11387
11708
|
this.indexedFields = /* @__PURE__ */ new Set(["_id"]);
|
|
11388
11709
|
}
|
|
@@ -11484,6 +11805,7 @@ var IndexManager = class {
|
|
|
11484
11805
|
* Register an index. If called before init(), queues it.
|
|
11485
11806
|
*/
|
|
11486
11807
|
async registerIndex(name, option, tx) {
|
|
11808
|
+
this.logger.debug(`Registering index "${name}" (type: ${option.type})`);
|
|
11487
11809
|
if (!this.api.isDocInitialized) {
|
|
11488
11810
|
this.pendingCreateIndices.set(name, option);
|
|
11489
11811
|
return;
|
|
@@ -11578,6 +11900,7 @@ var IndexManager = class {
|
|
|
11578
11900
|
* Backfill indices for newly created indices after data was inserted.
|
|
11579
11901
|
*/
|
|
11580
11902
|
async backfillIndices(tx) {
|
|
11903
|
+
this.logger.debug(`Starting backfill for fields: ${this.pendingBackfillFields.join(", ")}`);
|
|
11581
11904
|
return this.api.runWithDefaultWrite(async (tx2) => {
|
|
11582
11905
|
if (this.pendingBackfillFields.length === 0) {
|
|
11583
11906
|
return 0;
|
|
@@ -11587,16 +11910,14 @@ var IndexManager = class {
|
|
|
11587
11910
|
if (metadata.lastId === 0) {
|
|
11588
11911
|
return 0;
|
|
11589
11912
|
}
|
|
11590
|
-
|
|
11913
|
+
const bulkData = {};
|
|
11591
11914
|
for (const indexName of backfillTargets) {
|
|
11592
11915
|
const tree = this.trees.get(indexName);
|
|
11593
11916
|
if (tree && indexName !== "_id") {
|
|
11594
|
-
|
|
11917
|
+
bulkData[indexName] = [];
|
|
11595
11918
|
}
|
|
11596
11919
|
}
|
|
11597
11920
|
let backfilledCount = 0;
|
|
11598
|
-
let chunkCount = 0;
|
|
11599
|
-
const CHUNK_SIZE = 1e3;
|
|
11600
11921
|
const idTree = this.trees.get("_id");
|
|
11601
11922
|
if (!idTree) {
|
|
11602
11923
|
throw new Error("ID tree not found");
|
|
@@ -11610,63 +11931,45 @@ var IndexManager = class {
|
|
|
11610
11931
|
const flatDoc = this.api.flattenDocument(doc);
|
|
11611
11932
|
for (let i = 0, len = backfillTargets.length; i < len; i++) {
|
|
11612
11933
|
const indexName = backfillTargets[i];
|
|
11613
|
-
if (!(indexName in
|
|
11934
|
+
if (!(indexName in bulkData)) continue;
|
|
11614
11935
|
const config = this.registeredIndices.get(indexName);
|
|
11615
11936
|
if (!config) continue;
|
|
11616
|
-
const btx = indexTxMap[indexName];
|
|
11617
11937
|
if (config.type === "fts") {
|
|
11618
11938
|
const primaryField = this.getPrimaryField(config);
|
|
11619
11939
|
const v2 = flatDoc[primaryField];
|
|
11620
11940
|
if (v2 === void 0 || typeof v2 !== "string") continue;
|
|
11621
11941
|
const ftsConfig = this.getFtsConfig(config);
|
|
11622
11942
|
const tokens = ftsConfig ? tokenize(v2, ftsConfig) : [v2];
|
|
11623
|
-
|
|
11624
|
-
|
|
11625
|
-
const token = tokens[i2];
|
|
11943
|
+
for (let j = 0, tLen = tokens.length; j < tLen; j++) {
|
|
11944
|
+
const token = tokens[j];
|
|
11626
11945
|
const keyToInsert = this.getTokenKey(k2, token);
|
|
11627
11946
|
const entry = { k: k2, v: token };
|
|
11628
|
-
|
|
11947
|
+
bulkData[indexName].push([keyToInsert, entry]);
|
|
11629
11948
|
}
|
|
11630
|
-
await btx.batchInsert(batchInsertData);
|
|
11631
11949
|
} else {
|
|
11632
11950
|
const indexVal = this.getIndexValue(config, flatDoc);
|
|
11633
11951
|
if (indexVal === void 0) continue;
|
|
11634
11952
|
const entry = { k: k2, v: indexVal };
|
|
11635
|
-
|
|
11636
|
-
await btx.batchInsert(batchInsertData);
|
|
11953
|
+
bulkData[indexName].push([k2, entry]);
|
|
11637
11954
|
}
|
|
11638
11955
|
}
|
|
11639
11956
|
backfilledCount++;
|
|
11640
|
-
chunkCount++;
|
|
11641
|
-
if (chunkCount >= CHUNK_SIZE) {
|
|
11642
|
-
try {
|
|
11643
|
-
for (const btx of Object.values(indexTxMap)) {
|
|
11644
|
-
await btx.commit();
|
|
11645
|
-
}
|
|
11646
|
-
} catch (err) {
|
|
11647
|
-
for (const btx of Object.values(indexTxMap)) {
|
|
11648
|
-
await btx.rollback();
|
|
11649
|
-
}
|
|
11650
|
-
throw err;
|
|
11651
|
-
}
|
|
11652
|
-
for (const indexName of backfillTargets) {
|
|
11653
|
-
const tree = this.trees.get(indexName);
|
|
11654
|
-
if (tree && indexName !== "_id") {
|
|
11655
|
-
indexTxMap[indexName] = await tree.createTransaction();
|
|
11656
|
-
}
|
|
11657
|
-
}
|
|
11658
|
-
chunkCount = 0;
|
|
11659
|
-
}
|
|
11660
11957
|
}
|
|
11661
|
-
|
|
11958
|
+
for (const indexName of backfillTargets) {
|
|
11959
|
+
const tree = this.trees.get(indexName);
|
|
11960
|
+
if (!tree || indexName === "_id") continue;
|
|
11961
|
+
const entries = bulkData[indexName];
|
|
11962
|
+
if (!entries || entries.length === 0) continue;
|
|
11963
|
+
const treeTx = await tree.createTransaction();
|
|
11662
11964
|
try {
|
|
11663
|
-
|
|
11664
|
-
|
|
11965
|
+
await treeTx.bulkLoad(entries);
|
|
11966
|
+
const res = await treeTx.commit();
|
|
11967
|
+
if (!res.success) {
|
|
11968
|
+
await treeTx.rollback();
|
|
11969
|
+
throw res.error;
|
|
11665
11970
|
}
|
|
11666
11971
|
} catch (err) {
|
|
11667
|
-
|
|
11668
|
-
await btx.rollback();
|
|
11669
|
-
}
|
|
11972
|
+
await treeTx.rollback();
|
|
11670
11973
|
throw err;
|
|
11671
11974
|
}
|
|
11672
11975
|
}
|
|
@@ -11674,6 +11977,95 @@ var IndexManager = class {
|
|
|
11674
11977
|
return backfilledCount;
|
|
11675
11978
|
}, tx);
|
|
11676
11979
|
}
|
|
11980
|
+
/**
|
|
11981
|
+
* Rebuild specified indices by clearing existing tree data and rebuilding via bulkLoad.
|
|
11982
|
+
* If no index names are provided, all indices (except _id) are rebuilt.
|
|
11983
|
+
*/
|
|
11984
|
+
async rebuildIndices(indexNames, tx) {
|
|
11985
|
+
const targets = indexNames ?? [...this.registeredIndices.keys()].filter((n) => n !== "_id");
|
|
11986
|
+
for (const name of targets) {
|
|
11987
|
+
if (name === "_id") {
|
|
11988
|
+
throw new Error('Cannot rebuild the "_id" index.');
|
|
11989
|
+
}
|
|
11990
|
+
if (!this.registeredIndices.has(name)) {
|
|
11991
|
+
throw new Error(`Index "${name}" does not exist.`);
|
|
11992
|
+
}
|
|
11993
|
+
}
|
|
11994
|
+
if (targets.length === 0) return 0;
|
|
11995
|
+
this.logger.debug(`Starting rebuild for indices: ${targets.join(", ")}`);
|
|
11996
|
+
return this.api.runWithDefaultWrite(async (tx2) => {
|
|
11997
|
+
const metadata = await this.api.getDocumentInnerMetadata(tx2);
|
|
11998
|
+
if (metadata.lastId === 0) return 0;
|
|
11999
|
+
const bulkData = {};
|
|
12000
|
+
for (const indexName of targets) {
|
|
12001
|
+
bulkData[indexName] = [];
|
|
12002
|
+
}
|
|
12003
|
+
const idTree = this.trees.get("_id");
|
|
12004
|
+
if (!idTree) throw new Error("ID tree not found");
|
|
12005
|
+
let docCount = 0;
|
|
12006
|
+
const stream = idTree.whereStream({ primaryGte: { v: 0 } });
|
|
12007
|
+
for await (const [k2] of stream) {
|
|
12008
|
+
const doc = await this.api.getDocument(k2, tx2);
|
|
12009
|
+
if (!doc) continue;
|
|
12010
|
+
const flatDoc = this.api.flattenDocument(doc);
|
|
12011
|
+
for (let i = 0, len = targets.length; i < len; i++) {
|
|
12012
|
+
const indexName = targets[i];
|
|
12013
|
+
const config = this.registeredIndices.get(indexName);
|
|
12014
|
+
if (!config) continue;
|
|
12015
|
+
if (config.type === "fts") {
|
|
12016
|
+
const primaryField = this.getPrimaryField(config);
|
|
12017
|
+
const v2 = flatDoc[primaryField];
|
|
12018
|
+
if (v2 === void 0 || typeof v2 !== "string") continue;
|
|
12019
|
+
const ftsConfig = this.getFtsConfig(config);
|
|
12020
|
+
const tokens = ftsConfig ? tokenize(v2, ftsConfig) : [v2];
|
|
12021
|
+
for (let j = 0, tLen = tokens.length; j < tLen; j++) {
|
|
12022
|
+
const token = tokens[j];
|
|
12023
|
+
const keyToInsert = this.getTokenKey(k2, token);
|
|
12024
|
+
bulkData[indexName].push([keyToInsert, { k: k2, v: token }]);
|
|
12025
|
+
}
|
|
12026
|
+
} else {
|
|
12027
|
+
const indexVal = this.getIndexValue(config, flatDoc);
|
|
12028
|
+
if (indexVal === void 0) continue;
|
|
12029
|
+
bulkData[indexName].push([k2, { k: k2, v: indexVal }]);
|
|
12030
|
+
}
|
|
12031
|
+
}
|
|
12032
|
+
docCount++;
|
|
12033
|
+
}
|
|
12034
|
+
const perIndexCapacity = Math.floor(this.api.options.pageCacheCapacity / Object.keys(this.api.indices).length);
|
|
12035
|
+
for (const indexName of targets) {
|
|
12036
|
+
metadata.indices[indexName][0] = -1;
|
|
12037
|
+
await this.api.updateDocumentInnerMetadata(metadata, tx2);
|
|
12038
|
+
const tree = new import_dataply3.BPTreeAsync(
|
|
12039
|
+
new DocumentSerializeStrategyAsync(
|
|
12040
|
+
this.api.rowTableEngine.order,
|
|
12041
|
+
this.api,
|
|
12042
|
+
this.api.txContext,
|
|
12043
|
+
indexName
|
|
12044
|
+
),
|
|
12045
|
+
this.api.comparator,
|
|
12046
|
+
{ capacity: perIndexCapacity }
|
|
12047
|
+
);
|
|
12048
|
+
await tree.init();
|
|
12049
|
+
this.trees.set(indexName, tree);
|
|
12050
|
+
const entries = bulkData[indexName];
|
|
12051
|
+
if (entries.length > 0) {
|
|
12052
|
+
const treeTx = await tree.createTransaction();
|
|
12053
|
+
try {
|
|
12054
|
+
await treeTx.bulkLoad(entries);
|
|
12055
|
+
const res = await treeTx.commit();
|
|
12056
|
+
if (!res.success) {
|
|
12057
|
+
await treeTx.rollback();
|
|
12058
|
+
throw res.error;
|
|
12059
|
+
}
|
|
12060
|
+
} catch (err) {
|
|
12061
|
+
await treeTx.rollback();
|
|
12062
|
+
throw err;
|
|
12063
|
+
}
|
|
12064
|
+
}
|
|
12065
|
+
}
|
|
12066
|
+
return docCount;
|
|
12067
|
+
}, tx);
|
|
12068
|
+
}
|
|
11677
12069
|
/**
|
|
11678
12070
|
* Convert CreateIndexOption to IndexMetaConfig for metadata storage.
|
|
11679
12071
|
*/
|
|
@@ -11843,8 +12235,17 @@ var DeadlineChunker = class {
|
|
|
11843
12235
|
|
|
11844
12236
|
// src/core/MutationManager.ts
|
|
11845
12237
|
var MutationManager = class {
|
|
11846
|
-
constructor(api) {
|
|
12238
|
+
constructor(api, logger) {
|
|
11847
12239
|
this.api = api;
|
|
12240
|
+
this.logger = logger;
|
|
12241
|
+
}
|
|
12242
|
+
async isTreeEmpty(tree) {
|
|
12243
|
+
try {
|
|
12244
|
+
const root = await tree.getNode(tree.rootId);
|
|
12245
|
+
return root.leaf && root.values.length === 0;
|
|
12246
|
+
} catch {
|
|
12247
|
+
return true;
|
|
12248
|
+
}
|
|
11848
12249
|
}
|
|
11849
12250
|
async insertDocumentInternal(document, tx) {
|
|
11850
12251
|
const metadata = await this.api.getDocumentInnerMetadata(tx);
|
|
@@ -11945,18 +12346,26 @@ var MutationManager = class {
|
|
|
11945
12346
|
batchInsertData.push([item.pk, { k: item.pk, v: indexVal }]);
|
|
11946
12347
|
}
|
|
11947
12348
|
}
|
|
11948
|
-
const
|
|
11949
|
-
|
|
11950
|
-
|
|
11951
|
-
Math.max(initMaxSize, Math.floor(batchInsertData.length / 100 * 5))
|
|
11952
|
-
);
|
|
11953
|
-
const chunker = new DeadlineChunker(initChunkSize);
|
|
11954
|
-
await chunker.processInChunks(batchInsertData, async (chunk) => {
|
|
11955
|
-
const [error] = await catchPromise(treeTx.batchInsert(chunk));
|
|
12349
|
+
const isEmptyTree = await this.isTreeEmpty(tree);
|
|
12350
|
+
if (isEmptyTree) {
|
|
12351
|
+
const [error] = await catchPromise(treeTx.bulkLoad(batchInsertData));
|
|
11956
12352
|
if (error) {
|
|
11957
12353
|
throw error;
|
|
11958
12354
|
}
|
|
11959
|
-
}
|
|
12355
|
+
} else {
|
|
12356
|
+
const initMaxSize = 5e4;
|
|
12357
|
+
const initChunkSize = Math.min(
|
|
12358
|
+
initMaxSize,
|
|
12359
|
+
Math.max(initMaxSize, Math.floor(batchInsertData.length / 100 * 5))
|
|
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
|
+
});
|
|
12368
|
+
}
|
|
11960
12369
|
const res = await treeTx.commit();
|
|
11961
12370
|
if (!res.success) {
|
|
11962
12371
|
await treeTx.rollback();
|
|
@@ -12096,8 +12505,9 @@ var MutationManager = class {
|
|
|
12096
12505
|
|
|
12097
12506
|
// src/core/MetadataManager.ts
|
|
12098
12507
|
var MetadataManager = class {
|
|
12099
|
-
constructor(api) {
|
|
12508
|
+
constructor(api, logger) {
|
|
12100
12509
|
this.api = api;
|
|
12510
|
+
this.logger = logger;
|
|
12101
12511
|
}
|
|
12102
12512
|
async getDocumentMetadata(tx) {
|
|
12103
12513
|
const metadata = await this.api.getMetadata(tx);
|
|
@@ -12125,6 +12535,7 @@ var MetadataManager = class {
|
|
|
12125
12535
|
return JSON.parse(row);
|
|
12126
12536
|
}
|
|
12127
12537
|
async updateDocumentInnerMetadata(metadata, tx) {
|
|
12538
|
+
this.logger.debug(`Updating document inner metadata: version ${metadata.version}`);
|
|
12128
12539
|
await this.api.update(1, JSON.stringify(metadata), tx);
|
|
12129
12540
|
}
|
|
12130
12541
|
async migration(version, callback, tx) {
|
|
@@ -12134,6 +12545,7 @@ var MetadataManager = class {
|
|
|
12134
12545
|
if (currentVersion < version) {
|
|
12135
12546
|
await callback(tx2);
|
|
12136
12547
|
const freshMetadata = await this.getDocumentInnerMetadata(tx2);
|
|
12548
|
+
this.logger.info(`Migration applied successfully to schemeVersion ${version}`);
|
|
12137
12549
|
freshMetadata.schemeVersion = version;
|
|
12138
12550
|
freshMetadata.updatedAt = Date.now();
|
|
12139
12551
|
await this.updateDocumentInnerMetadata(freshMetadata, tx2);
|
|
@@ -12970,9 +13382,10 @@ var BuiltinAnalysisProviders = [
|
|
|
12970
13382
|
|
|
12971
13383
|
// src/core/AnalysisManager.ts
|
|
12972
13384
|
var AnalysisManager = class {
|
|
12973
|
-
constructor(api, schedule, sampleSize) {
|
|
13385
|
+
constructor(api, schedule, sampleSize, logger) {
|
|
12974
13386
|
this.api = api;
|
|
12975
13387
|
this.sampleSize = sampleSize;
|
|
13388
|
+
this.logger = logger;
|
|
12976
13389
|
this.cron = new E(schedule, async () => {
|
|
12977
13390
|
if (this.flushing) return;
|
|
12978
13391
|
await this.api.flushAnalysis();
|
|
@@ -13101,6 +13514,7 @@ var AnalysisManager = class {
|
|
|
13101
13514
|
if (this.flushing) {
|
|
13102
13515
|
throw new Error("Cannot flush analysis while analysis is already flushing.");
|
|
13103
13516
|
}
|
|
13517
|
+
this.logger.debug("Starting analysis data flush");
|
|
13104
13518
|
this.flushing = true;
|
|
13105
13519
|
for (const [name, provider] of this.providers) {
|
|
13106
13520
|
if (provider instanceof IntervalAnalysisProvider) {
|
|
@@ -13108,6 +13522,7 @@ var AnalysisManager = class {
|
|
|
13108
13522
|
}
|
|
13109
13523
|
}
|
|
13110
13524
|
this.flushing = false;
|
|
13525
|
+
this.logger.debug("Finished analysis data flush");
|
|
13111
13526
|
}
|
|
13112
13527
|
/**
|
|
13113
13528
|
* Get the analysis header row.
|
|
@@ -13235,32 +13650,39 @@ var DocumentDataplyAPI = class extends import_dataply4.DataplyAPI {
|
|
|
13235
13650
|
constructor(file, options) {
|
|
13236
13651
|
super(file, options);
|
|
13237
13652
|
this.optimizer = new Optimizer(this);
|
|
13238
|
-
this.queryManager = new QueryManager(this, this.optimizer);
|
|
13239
|
-
this.indexManager = new IndexManager(this);
|
|
13240
|
-
this.mutationManager = new MutationManager(this);
|
|
13241
|
-
this.metadataManager = new MetadataManager(this);
|
|
13653
|
+
this.queryManager = new QueryManager(this, this.optimizer, this.loggerManager.create("document-dataply:query"));
|
|
13654
|
+
this.indexManager = new IndexManager(this, this.loggerManager.create("document-dataply:index"));
|
|
13655
|
+
this.mutationManager = new MutationManager(this, this.loggerManager.create("document-dataply:mutation"));
|
|
13656
|
+
this.metadataManager = new MetadataManager(this, this.loggerManager.create("document-dataply:metadata"));
|
|
13242
13657
|
this.documentFormatter = new DocumentFormatter();
|
|
13243
13658
|
this.analysisManager = new AnalysisManager(
|
|
13244
13659
|
this,
|
|
13245
13660
|
options.analysisSchedule ?? "* */1 * * *",
|
|
13246
|
-
options.analysisSampleSize ?? 1e3
|
|
13661
|
+
options.analysisSampleSize ?? 1e3,
|
|
13662
|
+
this.loggerManager.create("document-dataply:analysis")
|
|
13247
13663
|
);
|
|
13248
13664
|
this.hook.onceAfter("close", async () => {
|
|
13665
|
+
this.logger.info("DocumentDataplyAPI closing");
|
|
13249
13666
|
this.analysisManager.close();
|
|
13250
13667
|
});
|
|
13251
13668
|
this.hook.onceAfter("init", async (tx, isNewlyCreated) => {
|
|
13669
|
+
this.logger.info(`Initializing document database. New creation: ${isNewlyCreated}`);
|
|
13252
13670
|
if (isNewlyCreated) {
|
|
13253
13671
|
await this.initializeDocumentFile(tx);
|
|
13672
|
+
this.logger.debug("Initialized document file format");
|
|
13254
13673
|
}
|
|
13255
13674
|
if (!await this.verifyDocumentFile(tx)) {
|
|
13675
|
+
this.logger.error("Document metadata verification failed");
|
|
13256
13676
|
throw new Error("Document metadata verification failed");
|
|
13257
13677
|
}
|
|
13258
13678
|
const metadata = await this.getDocumentInnerMetadata(tx);
|
|
13259
13679
|
await this.indexManager.initializeIndices(metadata, isNewlyCreated, tx);
|
|
13680
|
+
this.logger.debug(`Indices initialized. Total indices: ${Object.keys(metadata.indices).length}`);
|
|
13260
13681
|
this.analysisManager.registerBuiltinProviders();
|
|
13261
13682
|
await this.analysisManager.initializeProviders(tx);
|
|
13262
13683
|
this.analysisManager.triggerCron();
|
|
13263
13684
|
this._initialized = true;
|
|
13685
|
+
this.logger.info("Document database fully initialized");
|
|
13264
13686
|
return tx;
|
|
13265
13687
|
});
|
|
13266
13688
|
}
|
|
@@ -13318,6 +13740,16 @@ var DocumentDataplyAPI = class extends import_dataply4.DataplyAPI {
|
|
|
13318
13740
|
async backfillIndices(tx) {
|
|
13319
13741
|
return this.indexManager.backfillIndices(tx);
|
|
13320
13742
|
}
|
|
13743
|
+
/**
|
|
13744
|
+
* Rebuild specified indices by clearing existing tree data and rebuilding via bulkLoad.
|
|
13745
|
+
* If no index names are provided, all indices (except _id) are rebuilt.
|
|
13746
|
+
* @param indexNames Optional array of index names to rebuild
|
|
13747
|
+
* @param tx Optional transaction
|
|
13748
|
+
* @returns The number of documents processed
|
|
13749
|
+
*/
|
|
13750
|
+
async rebuildIndices(indexNames, tx) {
|
|
13751
|
+
return this.indexManager.rebuildIndices(indexNames, tx);
|
|
13752
|
+
}
|
|
13321
13753
|
/**
|
|
13322
13754
|
* Flush all interval analysis providers, forcing statistics to be recalculated.
|
|
13323
13755
|
* Call this after bulk inserts or periodically to keep statistics fresh.
|
|
@@ -13542,6 +13974,16 @@ var DocumentDataply = class _DocumentDataply {
|
|
|
13542
13974
|
await this.api.dropIndex(name, tx);
|
|
13543
13975
|
return this;
|
|
13544
13976
|
}
|
|
13977
|
+
/**
|
|
13978
|
+
* Rebuild specified indices by clearing existing data and reconstructing via bulkLoad.
|
|
13979
|
+
* If no index names are provided, rebuilds all indices except '_id'.
|
|
13980
|
+
* @param indexNames Optional array of index names to rebuild
|
|
13981
|
+
* @param tx Optional transaction
|
|
13982
|
+
* @returns The number of documents processed
|
|
13983
|
+
*/
|
|
13984
|
+
async rebuildIndices(indexNames, tx) {
|
|
13985
|
+
return this.api.rebuildIndices(indexNames, tx);
|
|
13986
|
+
}
|
|
13545
13987
|
/**
|
|
13546
13988
|
* Initialize the document database
|
|
13547
13989
|
*/
|