serializable-bptree 8.1.2 → 8.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -57,6 +57,42 @@ var StringComparator = class extends ValueComparator {
57
57
  // node_modules/mvcc-api/dist/esm/index.mjs
58
58
  var MVCCStrategy = class {
59
59
  };
60
+ var LRUMap = class {
61
+ cache = /* @__PURE__ */ new Map();
62
+ capacity;
63
+ constructor(capacity) {
64
+ this.capacity = capacity;
65
+ }
66
+ get(key) {
67
+ if (!this.cache.has(key)) return void 0;
68
+ const value = this.cache.get(key);
69
+ this.cache.delete(key);
70
+ this.cache.set(key, value);
71
+ return value;
72
+ }
73
+ set(key, value) {
74
+ if (this.cache.has(key)) {
75
+ this.cache.delete(key);
76
+ } else if (this.cache.size >= this.capacity) {
77
+ const oldestKey = this.cache.keys().next().value;
78
+ if (oldestKey !== void 0) this.cache.delete(oldestKey);
79
+ }
80
+ this.cache.set(key, value);
81
+ return this;
82
+ }
83
+ has(key) {
84
+ return this.cache.has(key);
85
+ }
86
+ delete(key) {
87
+ return this.cache.delete(key);
88
+ }
89
+ clear() {
90
+ this.cache.clear();
91
+ }
92
+ get size() {
93
+ return this.cache.size;
94
+ }
95
+ };
60
96
  var MVCCTransaction = class {
61
97
  committed;
62
98
  snapshotVersion;
@@ -64,11 +100,11 @@ var MVCCTransaction = class {
64
100
  writeBuffer;
65
101
  deleteBuffer;
66
102
  createdKeys;
67
- // create()로 생성된 키 추적
68
103
  deletedValues;
69
104
  // delete 시 삭제 전 값 저장
70
105
  originallyExisted;
71
106
  // 트랜잭션 시작 시점에 디스크에 존재했던 키 (deleted 결과 필터링용)
107
+ bufferHistory = /* @__PURE__ */ new Map();
72
108
  // Nested Transaction Properties
73
109
  parent;
74
110
  localVersion;
@@ -82,7 +118,8 @@ var MVCCTransaction = class {
82
118
  versionIndex = /* @__PURE__ */ new Map();
83
119
  deletedCache = /* @__PURE__ */ new Map();
84
120
  activeTransactions = /* @__PURE__ */ new Set();
85
- constructor(strategy, parent, snapshotVersion) {
121
+ diskCache;
122
+ constructor(strategy, options, parent, snapshotVersion) {
86
123
  this.snapshotVersion = snapshotVersion ?? 0;
87
124
  this.writeBuffer = /* @__PURE__ */ new Map();
88
125
  this.deleteBuffer = /* @__PURE__ */ new Set();
@@ -97,6 +134,7 @@ var MVCCTransaction = class {
97
134
  this.snapshotLocalVersion = parent.localVersion;
98
135
  this.strategy = void 0;
99
136
  this.root = parent.root;
137
+ this.diskCache = parent.diskCache;
100
138
  } else {
101
139
  if (!strategy) throw new Error("Root Transaction must get Strategy");
102
140
  this.strategy = strategy;
@@ -104,8 +142,13 @@ var MVCCTransaction = class {
104
142
  this.localVersion = 0;
105
143
  this.snapshotLocalVersion = 0;
106
144
  this.root = this;
145
+ this.diskCache = new LRUMap(options?.cacheCapacity ?? 1e3);
107
146
  }
108
147
  }
148
+ /**
149
+ * Checks if the transaction is a root transaction.
150
+ * @returns True if the transaction is a root transaction, false otherwise.
151
+ */
109
152
  isRoot() {
110
153
  return !this.parent;
111
154
  }
@@ -122,27 +165,61 @@ var MVCCTransaction = class {
122
165
  }
123
166
  return false;
124
167
  }
125
- // --- Internal buffer manipulation helpers ---
126
- _bufferCreate(key, value) {
127
- this.localVersion++;
168
+ /**
169
+ * Checks if a key was written in this transaction.
170
+ * @param key The key to check.
171
+ * @returns True if the key was written in this transaction, false otherwise.
172
+ */
173
+ isWrote(key) {
174
+ return this.writeBuffer.has(key);
175
+ }
176
+ /**
177
+ * Checks if a key was deleted in this transaction.
178
+ * @param key The key to check.
179
+ * @returns True if the key was deleted in this transaction, false otherwise.
180
+ */
181
+ isDeleted(key) {
182
+ return this.deleteBuffer.has(key);
183
+ }
184
+ _recordHistory(key) {
185
+ const existsInWriteBuffer = this.writeBuffer.has(key);
186
+ const existsInDeleteBuffer = this.deleteBuffer.has(key);
187
+ const currentVer = this.keyVersions.get(key);
188
+ if (currentVer !== void 0) {
189
+ if (!this.bufferHistory.has(key)) this.bufferHistory.set(key, []);
190
+ this.bufferHistory.get(key).push({
191
+ value: existsInWriteBuffer ? this.writeBuffer.get(key) : this.deletedValues.get(key) ?? null,
192
+ exists: existsInWriteBuffer || !existsInDeleteBuffer,
193
+ version: currentVer
194
+ });
195
+ }
196
+ }
197
+ _bufferCreate(key, value, version) {
198
+ if (version === void 0) this.localVersion++;
199
+ const targetVersion = version ?? this.localVersion;
200
+ this._recordHistory(key);
128
201
  this.writeBuffer.set(key, value);
129
202
  this.createdKeys.add(key);
130
203
  this.deleteBuffer.delete(key);
131
204
  this.originallyExisted.delete(key);
132
- this.keyVersions.set(key, this.localVersion);
205
+ this.keyVersions.set(key, targetVersion);
133
206
  }
134
- _bufferWrite(key, value) {
135
- this.localVersion++;
207
+ _bufferWrite(key, value, version) {
208
+ if (version === void 0) this.localVersion++;
209
+ const targetVersion = version ?? this.localVersion;
210
+ this._recordHistory(key);
136
211
  this.writeBuffer.set(key, value);
137
212
  this.deleteBuffer.delete(key);
138
- this.keyVersions.set(key, this.localVersion);
213
+ this.keyVersions.set(key, targetVersion);
139
214
  }
140
- _bufferDelete(key) {
141
- this.localVersion++;
215
+ _bufferDelete(key, version) {
216
+ if (version === void 0) this.localVersion++;
217
+ const targetVersion = version ?? this.localVersion;
218
+ this._recordHistory(key);
142
219
  this.deleteBuffer.add(key);
143
220
  this.writeBuffer.delete(key);
144
221
  this.createdKeys.delete(key);
145
- this.keyVersions.set(key, this.localVersion);
222
+ this.keyVersions.set(key, targetVersion);
146
223
  }
147
224
  /**
148
225
  * Returns the entries that will be created, updated, and deleted by this transaction.
@@ -166,7 +243,11 @@ var MVCCTransaction = class {
166
243
  deleted.push({ key, data });
167
244
  }
168
245
  }
169
- return { created, updated, deleted };
246
+ return {
247
+ created,
248
+ updated,
249
+ deleted
250
+ };
170
251
  }
171
252
  /**
172
253
  * Rolls back the transaction.
@@ -184,7 +265,12 @@ var MVCCTransaction = class {
184
265
  if (this.root !== this) {
185
266
  this.root.activeTransactions.delete(this);
186
267
  }
187
- return { success: true, created, updated, deleted };
268
+ return {
269
+ success: true,
270
+ created,
271
+ updated,
272
+ deleted
273
+ };
188
274
  }
189
275
  /**
190
276
  * Cleans up both deletedCache and versionIndex based on minActiveVersion.
@@ -219,7 +305,9 @@ var MVCCTransaction = class {
219
305
  break;
220
306
  }
221
307
  }
222
- if (latestInSnapshotIdx > 0) {
308
+ if (latestInSnapshotIdx === versions.length - 1) {
309
+ this.versionIndex.delete(key);
310
+ } else if (latestInSnapshotIdx > 0) {
223
311
  versions.splice(0, latestInSnapshotIdx);
224
312
  }
225
313
  }
@@ -268,7 +356,7 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
268
356
  createNested() {
269
357
  if (this.committed) throw new Error("Transaction already committed");
270
358
  const childVersion = this.isRoot() ? this.version : this.snapshotVersion;
271
- const child = new _SyncMVCCTransaction(void 0, this, childVersion);
359
+ const child = new _SyncMVCCTransaction(void 0, void 0, this, childVersion);
272
360
  this.root.activeTransactions.add(child);
273
361
  return child;
274
362
  }
@@ -276,27 +364,68 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
276
364
  if (this.committed) throw new Error("Transaction already committed");
277
365
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
278
366
  if (this.deleteBuffer.has(key)) return null;
279
- return this.root._diskRead(key, this.snapshotVersion);
367
+ if (this.parent) {
368
+ return this.parent._readSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
369
+ }
370
+ return this._diskRead(key, this.snapshotVersion);
280
371
  }
281
372
  exists(key) {
282
373
  if (this.committed) throw new Error("Transaction already committed");
283
374
  if (this.deleteBuffer.has(key)) return false;
284
375
  if (this.writeBuffer.has(key)) return true;
285
- return this.root._diskExists(key, this.snapshotVersion);
376
+ if (this.parent) {
377
+ return this.parent._existsSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
378
+ }
379
+ return this._diskExists(key, this.snapshotVersion);
380
+ }
381
+ _existsSnapshot(key, snapshotVersion, snapshotLocalVersion) {
382
+ if (this.writeBuffer.has(key)) {
383
+ const keyModVersion = this.keyVersions.get(key);
384
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
385
+ return true;
386
+ }
387
+ }
388
+ if (this.deleteBuffer.has(key)) {
389
+ const keyModVersion = this.keyVersions.get(key);
390
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
391
+ return false;
392
+ }
393
+ }
394
+ const history = this.bufferHistory.get(key);
395
+ if (history && snapshotLocalVersion !== void 0) {
396
+ for (let i = history.length - 1; i >= 0; i--) {
397
+ if (history[i].version <= snapshotLocalVersion) {
398
+ return history[i].exists;
399
+ }
400
+ }
401
+ }
402
+ if (this.parent) {
403
+ return this.parent._existsSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
404
+ } else {
405
+ return this._diskExists(key, snapshotVersion);
406
+ }
286
407
  }
287
408
  _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
288
409
  if (this.writeBuffer.has(key)) {
289
410
  const keyModVersion = this.keyVersions.get(key);
290
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
411
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
291
412
  return this.writeBuffer.get(key);
292
413
  }
293
414
  }
294
415
  if (this.deleteBuffer.has(key)) {
295
416
  const keyModVersion = this.keyVersions.get(key);
296
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
417
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
297
418
  return null;
298
419
  }
299
420
  }
421
+ const history = this.bufferHistory.get(key);
422
+ if (history && snapshotLocalVersion !== void 0) {
423
+ for (let i = history.length - 1; i >= 0; i--) {
424
+ if (history[i].version <= snapshotLocalVersion) {
425
+ return history[i].exists ? history[i].value : null;
426
+ }
427
+ }
428
+ }
300
429
  if (this.parent) {
301
430
  return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
302
431
  } else {
@@ -361,6 +490,7 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
361
490
  this.deletedValues.clear();
362
491
  this.originallyExisted.clear();
363
492
  this.keyVersions.clear();
493
+ this.bufferHistory.clear();
364
494
  this.localVersion = 0;
365
495
  this.snapshotVersion = this.version;
366
496
  }
@@ -401,32 +531,22 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
401
531
  };
402
532
  }
403
533
  }
404
- const newLocalVersion = this.localVersion + 1;
405
- for (const key of child.writeBuffer.keys()) {
406
- this.writeBuffer.set(key, child.writeBuffer.get(key));
407
- this.deleteBuffer.delete(key);
408
- this.keyVersions.set(key, newLocalVersion);
409
- if (child.createdKeys.has(key)) {
410
- this.createdKeys.add(key);
411
- }
534
+ const mergeVersion = ++this.localVersion;
535
+ for (const [key, value] of child.writeBuffer) {
536
+ const wasCreated = child.createdKeys.has(key);
537
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
538
+ else this._bufferWrite(key, value, mergeVersion);
412
539
  }
413
540
  for (const key of child.deleteBuffer) {
414
- this.deleteBuffer.add(key);
415
- this.writeBuffer.delete(key);
416
- this.createdKeys.delete(key);
417
- this.keyVersions.set(key, newLocalVersion);
418
541
  const deletedValue = child.deletedValues.get(key);
419
- if (deletedValue !== void 0) {
420
- this.deletedValues.set(key, deletedValue);
421
- }
422
- if (child.originallyExisted.has(key)) {
542
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
543
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
423
544
  this.originallyExisted.add(key);
424
545
  }
546
+ this._bufferDelete(key, mergeVersion);
425
547
  }
426
- this.localVersion = newLocalVersion;
427
548
  this.root.activeTransactions.delete(child);
428
549
  } else {
429
- const newVersion = this.version + 1;
430
550
  if (child !== this) {
431
551
  const modifiedKeys = /* @__PURE__ */ new Set([...child.writeBuffer.keys(), ...child.deleteBuffer]);
432
552
  for (const key of modifiedKeys) {
@@ -444,50 +564,57 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
444
564
  };
445
565
  }
446
566
  }
567
+ const lastModLocalVer = this.keyVersions.get(key);
568
+ if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
569
+ return {
570
+ error: `Commit conflict: Key '${key}' was modified by a newer transaction in the same session (Local v${lastModLocalVer})`,
571
+ conflict: {
572
+ key,
573
+ parent: this.read(key),
574
+ child: child.read(key)
575
+ }
576
+ };
577
+ }
447
578
  }
448
- }
449
- for (const [key, value] of child.writeBuffer) {
450
- this.writeBuffer.set(key, value);
451
- this.deleteBuffer.delete(key);
452
- if (child.createdKeys.has(key)) {
453
- this.createdKeys.add(key);
454
- }
455
- }
456
- for (const key of child.deleteBuffer) {
457
- this.deleteBuffer.add(key);
458
- this.writeBuffer.delete(key);
459
- this.createdKeys.delete(key);
460
- const deletedValue = child.deletedValues.get(key);
461
- if (deletedValue !== void 0) {
462
- this.deletedValues.set(key, deletedValue);
579
+ const mergeVersion = ++this.localVersion;
580
+ for (const [key, value] of child.writeBuffer) {
581
+ const wasCreated = child.createdKeys.has(key);
582
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
583
+ this.originallyExisted.add(key);
584
+ }
585
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
586
+ else this._bufferWrite(key, value, mergeVersion);
463
587
  }
464
- if (child.originallyExisted.has(key)) {
465
- this.originallyExisted.add(key);
588
+ for (const key of child.deleteBuffer) {
589
+ const deletedValue = child.deletedValues.get(key);
590
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
591
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
592
+ this.originallyExisted.add(key);
593
+ }
594
+ this._bufferDelete(key, mergeVersion);
466
595
  }
596
+ this.root.activeTransactions.delete(child);
597
+ } else {
598
+ const newVersion = this.version + 1;
599
+ for (const [key, value] of this.writeBuffer) this._diskWrite(key, value, newVersion);
600
+ for (const key of this.deleteBuffer) this._diskDelete(key, newVersion);
601
+ this.version = newVersion;
602
+ this._cleanupDeletedCache();
467
603
  }
468
- for (const [key, value] of child.writeBuffer) {
469
- this._diskWrite(key, value, newVersion);
470
- }
471
- for (const key of child.deleteBuffer) {
472
- this._diskDelete(key, newVersion);
473
- }
474
- this.version = newVersion;
475
- this.root.activeTransactions.delete(child);
476
- this._cleanupDeletedCache();
477
604
  }
478
605
  return null;
479
606
  }
480
- // --- Internal IO Helpers (Root Only) ---
481
607
  _diskWrite(key, value, version) {
482
608
  const strategy = this.strategy;
483
609
  if (!strategy) throw new Error("Root Transaction missing strategy");
484
- if (strategy.exists(key)) {
485
- const currentVal = strategy.read(key);
610
+ const rootAsAny = this.root;
611
+ if (this._diskExists(key, version)) {
612
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
486
613
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
487
- this.deletedCache.get(key).push({
488
- value: currentVal,
489
- deletedAtVersion: version
490
- });
614
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
615
+ rootAsAny.diskCache.set(key, value);
616
+ } else {
617
+ rootAsAny.diskCache.set(key, value);
491
618
  }
492
619
  strategy.write(key, value);
493
620
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -498,14 +625,19 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
498
625
  if (!strategy) throw new Error("Root Transaction missing strategy");
499
626
  const versions = this.versionIndex.get(key);
500
627
  if (!versions) {
501
- return strategy.exists(key) ? strategy.read(key) : null;
628
+ const rootAsAny = this.root;
629
+ if (this._diskExists(key, snapshotVersion)) {
630
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
631
+ rootAsAny.diskCache.set(key, val);
632
+ return val;
633
+ }
634
+ return null;
502
635
  }
503
636
  let targetVerObj = null;
504
637
  let nextVerObj = null;
505
638
  for (const v of versions) {
506
- if (v.version <= snapshotVersion) {
507
- targetVerObj = v;
508
- } else {
639
+ if (v.version <= snapshotVersion) targetVerObj = v;
640
+ else {
509
641
  nextVerObj = v;
510
642
  break;
511
643
  }
@@ -522,7 +654,14 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
522
654
  }
523
655
  if (!targetVerObj.exists) return null;
524
656
  if (!nextVerObj) {
525
- return strategy.read(key);
657
+ if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
658
+ if (this._diskExists(key, snapshotVersion)) {
659
+ const rootAsAny = this.root;
660
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
661
+ rootAsAny.diskCache.set(key, val);
662
+ return val;
663
+ }
664
+ return null;
526
665
  }
527
666
  const cached = this.deletedCache.get(key);
528
667
  if (cached) {
@@ -536,31 +675,44 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
536
675
  if (!strategy) throw new Error("Root Transaction missing strategy");
537
676
  const versions = this.versionIndex.get(key);
538
677
  if (!versions) {
539
- return strategy.exists(key);
678
+ const rootAsAny = this.root;
679
+ if (rootAsAny.diskCache.has(key)) return rootAsAny.diskCache.get(key) !== null;
680
+ const exists = strategy.exists(key);
681
+ if (!exists) rootAsAny.diskCache.set(key, null);
682
+ return exists;
540
683
  }
541
684
  let targetVerObj = null;
685
+ let nextVerObj = null;
542
686
  for (const v of versions) {
543
- if (v.version <= snapshotVersion) {
544
- targetVerObj = v;
545
- } else {
687
+ if (v.version <= snapshotVersion) targetVerObj = v;
688
+ else {
689
+ nextVerObj = v;
546
690
  break;
547
691
  }
548
692
  }
549
- if (!targetVerObj) return strategy.exists(key);
693
+ if (!targetVerObj) {
694
+ if (nextVerObj) {
695
+ const cached = this.deletedCache.get(key);
696
+ if (cached) {
697
+ const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
698
+ if (match) return true;
699
+ }
700
+ }
701
+ return false;
702
+ }
550
703
  return targetVerObj.exists;
551
704
  }
552
705
  _diskDelete(key, snapshotVersion) {
553
706
  const strategy = this.strategy;
554
707
  if (!strategy) throw new Error("Root Transaction missing strategy");
555
- if (strategy.exists(key)) {
556
- const currentVal = strategy.read(key);
708
+ const rootAsAny = this.root;
709
+ if (this._diskExists(key, snapshotVersion)) {
710
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
557
711
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
558
- this.deletedCache.get(key).push({
559
- value: currentVal,
560
- deletedAtVersion: snapshotVersion
561
- });
712
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
713
+ strategy.delete(key);
714
+ rootAsAny.diskCache.delete(key);
562
715
  }
563
- strategy.delete(key);
564
716
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
565
717
  this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });
566
718
  }
@@ -873,7 +1025,7 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
873
1025
  createNested() {
874
1026
  if (this.committed) throw new Error("Transaction already committed");
875
1027
  const childVersion = this.isRoot() ? this.version : this.snapshotVersion;
876
- const child = new _AsyncMVCCTransaction(void 0, this, childVersion);
1028
+ const child = new _AsyncMVCCTransaction(void 0, void 0, this, childVersion);
877
1029
  this.root.activeTransactions.add(child);
878
1030
  return child;
879
1031
  }
@@ -881,31 +1033,72 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
881
1033
  if (this.committed) throw new Error("Transaction already committed");
882
1034
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
883
1035
  if (this.deleteBuffer.has(key)) return null;
884
- return this.root._diskRead(key, this.snapshotVersion);
1036
+ if (this.parent) {
1037
+ return this.parent._readSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
1038
+ }
1039
+ return await this._diskRead(key, this.snapshotVersion);
885
1040
  }
886
1041
  async exists(key) {
887
1042
  if (this.committed) throw new Error("Transaction already committed");
888
1043
  if (this.deleteBuffer.has(key)) return false;
889
1044
  if (this.writeBuffer.has(key)) return true;
890
- return this.root._diskExists(key, this.snapshotVersion);
1045
+ if (this.parent) {
1046
+ return this.parent._existsSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
1047
+ }
1048
+ return await this._diskExists(key, this.snapshotVersion);
1049
+ }
1050
+ async _existsSnapshot(key, snapshotVersion, snapshotLocalVersion) {
1051
+ if (this.writeBuffer.has(key)) {
1052
+ const keyModVersion = this.keyVersions.get(key);
1053
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
1054
+ return true;
1055
+ }
1056
+ }
1057
+ if (this.deleteBuffer.has(key)) {
1058
+ const keyModVersion = this.keyVersions.get(key);
1059
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
1060
+ return false;
1061
+ }
1062
+ }
1063
+ const history = this.bufferHistory.get(key);
1064
+ if (history && snapshotLocalVersion !== void 0) {
1065
+ for (let i = history.length - 1; i >= 0; i--) {
1066
+ if (history[i].version <= snapshotLocalVersion) {
1067
+ return history[i].exists;
1068
+ }
1069
+ }
1070
+ }
1071
+ if (this.parent) {
1072
+ return this.parent._existsSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
1073
+ } else {
1074
+ return await this._diskExists(key, snapshotVersion);
1075
+ }
891
1076
  }
892
1077
  async _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
893
1078
  if (this.writeBuffer.has(key)) {
894
1079
  const keyModVersion = this.keyVersions.get(key);
895
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
1080
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
896
1081
  return this.writeBuffer.get(key);
897
1082
  }
898
1083
  }
899
1084
  if (this.deleteBuffer.has(key)) {
900
1085
  const keyModVersion = this.keyVersions.get(key);
901
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
1086
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
902
1087
  return null;
903
1088
  }
904
1089
  }
1090
+ const history = this.bufferHistory.get(key);
1091
+ if (history && snapshotLocalVersion !== void 0) {
1092
+ for (let i = history.length - 1; i >= 0; i--) {
1093
+ if (history[i].version <= snapshotLocalVersion) {
1094
+ return history[i].exists ? history[i].value : null;
1095
+ }
1096
+ }
1097
+ }
905
1098
  if (this.parent) {
906
1099
  return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
907
1100
  } else {
908
- return this._diskRead(key, snapshotVersion);
1101
+ return await this._diskRead(key, snapshotVersion);
909
1102
  }
910
1103
  }
911
1104
  async commit(label) {
@@ -966,6 +1159,7 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
966
1159
  this.deletedValues.clear();
967
1160
  this.originallyExisted.clear();
968
1161
  this.keyVersions.clear();
1162
+ this.bufferHistory.clear();
969
1163
  this.localVersion = 0;
970
1164
  this.snapshotVersion = this.version;
971
1165
  }
@@ -1007,33 +1201,23 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1007
1201
  };
1008
1202
  }
1009
1203
  }
1010
- const newLocalVersion = this.localVersion + 1;
1011
- for (const key of child.writeBuffer.keys()) {
1012
- this.writeBuffer.set(key, child.writeBuffer.get(key));
1013
- this.deleteBuffer.delete(key);
1014
- this.keyVersions.set(key, newLocalVersion);
1015
- if (child.createdKeys.has(key)) {
1016
- this.createdKeys.add(key);
1017
- }
1204
+ const mergeVersion = ++this.localVersion;
1205
+ for (const [key, value] of child.writeBuffer) {
1206
+ const wasCreated = child.createdKeys.has(key);
1207
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
1208
+ else this._bufferWrite(key, value, mergeVersion);
1018
1209
  }
1019
1210
  for (const key of child.deleteBuffer) {
1020
- this.deleteBuffer.add(key);
1021
- this.writeBuffer.delete(key);
1022
- this.createdKeys.delete(key);
1023
- this.keyVersions.set(key, newLocalVersion);
1024
1211
  const deletedValue = child.deletedValues.get(key);
1025
- if (deletedValue !== void 0) {
1026
- this.deletedValues.set(key, deletedValue);
1027
- }
1028
- if (child.originallyExisted.has(key)) {
1212
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
1213
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
1029
1214
  this.originallyExisted.add(key);
1030
1215
  }
1216
+ this._bufferDelete(key, mergeVersion);
1031
1217
  }
1032
- this.localVersion = newLocalVersion;
1033
1218
  this.root.activeTransactions.delete(child);
1034
1219
  return null;
1035
1220
  } else {
1036
- const newVersion = this.version + 1;
1037
1221
  if (child !== this) {
1038
1222
  const modifiedKeys = /* @__PURE__ */ new Set([...child.writeBuffer.keys(), ...child.deleteBuffer]);
1039
1223
  for (const key of modifiedKeys) {
@@ -1051,51 +1235,58 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1051
1235
  };
1052
1236
  }
1053
1237
  }
1238
+ const lastModLocalVer = this.keyVersions.get(key);
1239
+ if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
1240
+ return {
1241
+ error: `Commit conflict: Key '${key}' was modified by a newer transaction in the same session (Local v${lastModLocalVer})`,
1242
+ conflict: {
1243
+ key,
1244
+ parent: await this.read(key),
1245
+ child: await child.read(key)
1246
+ }
1247
+ };
1248
+ }
1054
1249
  }
1055
- }
1056
- for (const [key, value] of child.writeBuffer) {
1057
- this.writeBuffer.set(key, value);
1058
- this.deleteBuffer.delete(key);
1059
- if (child.createdKeys.has(key)) {
1060
- this.createdKeys.add(key);
1061
- }
1062
- }
1063
- for (const key of child.deleteBuffer) {
1064
- this.deleteBuffer.add(key);
1065
- this.writeBuffer.delete(key);
1066
- this.createdKeys.delete(key);
1067
- const deletedValue = child.deletedValues.get(key);
1068
- if (deletedValue !== void 0) {
1069
- this.deletedValues.set(key, deletedValue);
1250
+ const mergeVersion = ++this.localVersion;
1251
+ for (const [key, value] of child.writeBuffer) {
1252
+ const wasCreated = child.createdKeys.has(key);
1253
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
1254
+ this.originallyExisted.add(key);
1255
+ }
1256
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
1257
+ else this._bufferWrite(key, value, mergeVersion);
1070
1258
  }
1071
- if (child.originallyExisted.has(key)) {
1072
- this.originallyExisted.add(key);
1259
+ for (const key of child.deleteBuffer) {
1260
+ const deletedValue = child.deletedValues.get(key);
1261
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
1262
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
1263
+ this.originallyExisted.add(key);
1264
+ }
1265
+ this._bufferDelete(key, mergeVersion);
1073
1266
  }
1267
+ this.root.activeTransactions.delete(child);
1268
+ } else {
1269
+ const newVersion = this.version + 1;
1270
+ for (const [key, value] of this.writeBuffer) await this._diskWrite(key, value, newVersion);
1271
+ for (const key of this.deleteBuffer) await this._diskDelete(key, newVersion);
1272
+ this.version = newVersion;
1273
+ this._cleanupDeletedCache();
1074
1274
  }
1075
- for (const [key, value] of child.writeBuffer) {
1076
- await this._diskWrite(key, value, newVersion);
1077
- }
1078
- for (const key of child.deleteBuffer) {
1079
- await this._diskDelete(key, newVersion);
1080
- }
1081
- this.version = newVersion;
1082
- this.root.activeTransactions.delete(child);
1083
- this._cleanupDeletedCache();
1084
1275
  return null;
1085
1276
  }
1086
1277
  });
1087
1278
  }
1088
- // --- Internal IO Helpers (Root Only) ---
1089
1279
  async _diskWrite(key, value, version) {
1090
1280
  const strategy = this.strategy;
1091
1281
  if (!strategy) throw new Error("Root Transaction missing strategy");
1092
- if (await strategy.exists(key)) {
1093
- const currentVal = await strategy.read(key);
1282
+ const rootAsAny = this.root;
1283
+ if (await this._diskExists(key, version)) {
1284
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
1094
1285
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
1095
- this.deletedCache.get(key).push({
1096
- value: currentVal,
1097
- deletedAtVersion: version
1098
- });
1286
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
1287
+ rootAsAny.diskCache.set(key, value);
1288
+ } else {
1289
+ rootAsAny.diskCache.set(key, value);
1099
1290
  }
1100
1291
  await strategy.write(key, value);
1101
1292
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -1106,14 +1297,19 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1106
1297
  if (!strategy) throw new Error("Root Transaction missing strategy");
1107
1298
  const versions = this.versionIndex.get(key);
1108
1299
  if (!versions) {
1109
- return await strategy.exists(key) ? strategy.read(key) : null;
1300
+ const rootAsAny = this.root;
1301
+ if (await this._diskExists(key, snapshotVersion)) {
1302
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
1303
+ rootAsAny.diskCache.set(key, val);
1304
+ return val;
1305
+ }
1306
+ return null;
1110
1307
  }
1111
1308
  let targetVerObj = null;
1112
1309
  let nextVerObj = null;
1113
1310
  for (const v of versions) {
1114
- if (v.version <= snapshotVersion) {
1115
- targetVerObj = v;
1116
- } else {
1311
+ if (v.version <= snapshotVersion) targetVerObj = v;
1312
+ else {
1117
1313
  nextVerObj = v;
1118
1314
  break;
1119
1315
  }
@@ -1130,7 +1326,14 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1130
1326
  }
1131
1327
  if (!targetVerObj.exists) return null;
1132
1328
  if (!nextVerObj) {
1133
- return strategy.read(key);
1329
+ if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
1330
+ if (await this._diskExists(key, snapshotVersion)) {
1331
+ const rootAsAny = this.root;
1332
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
1333
+ rootAsAny.diskCache.set(key, val);
1334
+ return val;
1335
+ }
1336
+ return null;
1134
1337
  }
1135
1338
  const cached = this.deletedCache.get(key);
1136
1339
  if (cached) {
@@ -1144,393 +1347,89 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1144
1347
  if (!strategy) throw new Error("Root Transaction missing strategy");
1145
1348
  const versions = this.versionIndex.get(key);
1146
1349
  if (!versions) {
1147
- return strategy.exists(key);
1350
+ const rootAsAny = this.root;
1351
+ if (rootAsAny.diskCache.has(key)) return rootAsAny.diskCache.get(key) !== null;
1352
+ const exists = await strategy.exists(key);
1353
+ if (!exists) rootAsAny.diskCache.set(key, null);
1354
+ return exists;
1148
1355
  }
1149
1356
  let targetVerObj = null;
1357
+ let nextVerObj = null;
1150
1358
  for (const v of versions) {
1151
- if (v.version <= snapshotVersion) {
1152
- targetVerObj = v;
1153
- } else {
1359
+ if (v.version <= snapshotVersion) targetVerObj = v;
1360
+ else {
1361
+ nextVerObj = v;
1154
1362
  break;
1155
1363
  }
1156
1364
  }
1157
- if (!targetVerObj) return strategy.exists(key);
1365
+ if (!targetVerObj) {
1366
+ if (nextVerObj) {
1367
+ const cached = this.deletedCache.get(key);
1368
+ if (cached) {
1369
+ const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
1370
+ if (match) return true;
1371
+ }
1372
+ }
1373
+ return false;
1374
+ }
1158
1375
  return targetVerObj.exists;
1159
1376
  }
1160
1377
  async _diskDelete(key, snapshotVersion) {
1161
1378
  const strategy = this.strategy;
1162
1379
  if (!strategy) throw new Error("Root Transaction missing strategy");
1163
- if (await strategy.exists(key)) {
1164
- const currentVal = await strategy.read(key);
1380
+ const rootAsAny = this.root;
1381
+ if (await this._diskExists(key, snapshotVersion)) {
1382
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
1165
1383
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
1166
- this.deletedCache.get(key).push({
1167
- value: currentVal,
1168
- deletedAtVersion: snapshotVersion
1169
- });
1384
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
1385
+ await strategy.delete(key);
1386
+ rootAsAny.diskCache.delete(key);
1170
1387
  }
1171
- await strategy.delete(key);
1172
1388
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
1173
1389
  this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });
1174
1390
  }
1175
1391
  };
1176
1392
 
1177
- // node_modules/cache-entanglement/dist/esm/index.mjs
1178
- var LRUMap = class {
1179
- capacity;
1180
- map;
1181
- head = null;
1182
- tail = null;
1183
- /**
1184
- * Creates an instance of LRUMap.
1185
- * @param capacity The maximum number of items the cache can hold.
1186
- */
1187
- constructor(capacity) {
1188
- this.capacity = capacity;
1189
- this.map = /* @__PURE__ */ new Map();
1190
- }
1191
- /**
1192
- * Promotes a node to the head of the linked list (marks as most recently used).
1193
- * @param node The node to promote.
1194
- */
1195
- promote(node) {
1196
- this.extract(node);
1197
- this.prepend(node);
1198
- }
1199
- /**
1200
- * Disconnects a node from the doubly linked list.
1201
- * @param node The node to extract.
1202
- */
1203
- extract(node) {
1204
- if (node.prev) node.prev.next = node.next;
1205
- else this.head = node.next;
1206
- if (node.next) node.next.prev = node.prev;
1207
- else this.tail = node.prev;
1208
- node.prev = null;
1209
- node.next = null;
1210
- }
1211
- /**
1212
- * Inserts a node at the head of the doubly linked list.
1213
- * @param node The node to prepend.
1214
- */
1215
- prepend(node) {
1216
- node.next = this.head;
1217
- if (this.head) this.head.prev = node;
1218
- this.head = node;
1219
- if (!this.tail) this.tail = node;
1220
- }
1221
- /**
1222
- * Stores or updates a value by key.
1223
- * If the capacity is exceeded, the least recently used item (tail) is removed.
1224
- * @param key The key to store.
1225
- * @param value The value to store.
1226
- */
1227
- set(key, value) {
1228
- const existing = this.map.get(key);
1229
- if (existing) {
1230
- existing.value = value;
1231
- this.promote(existing);
1232
- return;
1233
- }
1234
- const newNode = { key, value, prev: null, next: null };
1235
- this.map.set(key, newNode);
1236
- this.prepend(newNode);
1237
- if (this.map.size > this.capacity && this.tail) {
1238
- this.map.delete(this.tail.key);
1239
- this.extract(this.tail);
1240
- }
1241
- }
1242
- /**
1243
- * Retrieves a value by key.
1244
- * Accessing the item moves it to the "most recently used" position.
1245
- * @param key The key to look for.
1246
- * @returns The value associated with the key, or undefined if not found.
1247
- */
1248
- get(key) {
1249
- const node = this.map.get(key);
1250
- if (!node) return void 0;
1251
- this.promote(node);
1252
- return node.value;
1253
- }
1254
- /**
1255
- * Checks if a key exists in the cache without changing its access order.
1256
- * @param key The key to check.
1257
- * @returns True if the key exists, false otherwise.
1258
- */
1259
- has(key) {
1260
- return this.map.has(key);
1261
- }
1262
- /**
1263
- * Removes a key and its associated value from the cache.
1264
- * @param key The key to remove.
1265
- * @returns True if the key was found and removed, false otherwise.
1266
- */
1267
- delete(key) {
1268
- const node = this.map.get(key);
1269
- if (!node) return false;
1270
- this.extract(node);
1271
- this.map.delete(key);
1272
- return true;
1273
- }
1274
- /**
1275
- * Returns an iterator of keys in the order of most recently used to least recently used.
1276
- * @returns An iterable iterator of keys.
1277
- */
1278
- *keys() {
1279
- let current = this.head;
1280
- while (current) {
1281
- yield current.key;
1282
- current = current.next;
1283
- }
1284
- }
1285
- /**
1286
- * Returns the current number of items in the cache.
1287
- */
1288
- get size() {
1289
- return this.map.size;
1290
- }
1291
- /**
1292
- * Clears all items from the cache.
1293
- */
1294
- clear() {
1295
- this.map.clear();
1296
- this.head = null;
1297
- this.tail = null;
1298
- }
1299
- };
1300
- var CacheEntanglement = class {
1301
- creation;
1302
- beforeUpdateHook;
1303
- capacity;
1304
- dependencies;
1305
- caches;
1306
- parameters;
1307
- assignments;
1308
- dependencyProperties;
1309
- updateRequirements;
1310
- constructor(creation, option) {
1311
- option = option ?? {};
1312
- const {
1313
- dependencies,
1314
- capacity,
1315
- beforeUpdateHook
1316
- } = option;
1317
- this.creation = creation;
1318
- this.beforeUpdateHook = beforeUpdateHook ?? (() => {
1319
- });
1320
- this.capacity = capacity ?? 100;
1321
- this.assignments = [];
1322
- this.caches = new LRUMap(this.capacity);
1323
- this.parameters = /* @__PURE__ */ new Map();
1324
- this.dependencies = dependencies ?? {};
1325
- this.dependencyProperties = Object.keys(this.dependencies);
1326
- this.updateRequirements = /* @__PURE__ */ new Set();
1327
- for (const name in this.dependencies) {
1328
- const dependency = this.dependencies[name];
1329
- if (!dependency.assignments.includes(this)) {
1330
- dependency.assignments.push(this);
1331
- }
1332
- }
1333
- }
1334
- bubbleUpdateSignal(key) {
1335
- this.updateRequirements.add(key);
1336
- for (let i = 0, len = this.assignments.length; i < len; i++) {
1337
- const t = this.assignments[i];
1338
- const instance = t;
1339
- for (const cacheKey of instance.caches.keys()) {
1340
- if (cacheKey === key || cacheKey.startsWith(`${key}/`)) {
1341
- instance.bubbleUpdateSignal(cacheKey);
1342
- }
1343
- }
1344
- }
1345
- }
1346
- dependencyKey(key) {
1347
- const i = key.lastIndexOf("/");
1348
- if (i === -1) {
1349
- return key;
1350
- }
1351
- return key.substring(0, i);
1352
- }
1353
- /**
1354
- * Returns all keys stored in the instance.
1355
- */
1356
- keys() {
1357
- return this.parameters.keys();
1358
- }
1359
- /**
1360
- * Deletes all cache values stored in the instance.
1361
- */
1362
- clear() {
1363
- for (const key of this.keys()) {
1364
- this.delete(key);
1365
- }
1366
- }
1367
- /**
1368
- * Checks if there is a cache value stored in the key within the instance.
1369
- * @param key The key to search.
1370
- */
1371
- exists(key) {
1372
- return this.parameters.has(key);
1373
- }
1374
- /**
1375
- * Checks if there is a cache value stored in the key within the instance.
1376
- * This method is an alias for `exists`.
1377
- * @param key The key to search.
1378
- */
1379
- has(key) {
1380
- return this.exists(key);
1381
- }
1382
- /**
1383
- * Deletes the cache value stored in the key within the instance.
1384
- * @param key The key to delete.
1385
- */
1386
- delete(key) {
1387
- this.caches.delete(key);
1388
- this.parameters.delete(key);
1389
- this.updateRequirements.delete(key);
1390
- for (let i = 0, len = this.assignments.length; i < len; i++) {
1391
- const t = this.assignments[i];
1392
- const instance = t;
1393
- for (const cacheKey of instance.keys()) {
1394
- if (cacheKey === key || cacheKey.startsWith(`${key}/`)) {
1395
- instance.delete(cacheKey);
1396
- }
1397
- }
1398
- }
1399
- }
1400
- };
1401
- var CacheData = class _CacheData {
1402
- static StructuredClone = globalThis.structuredClone.bind(globalThis);
1403
- _value;
1404
- constructor(value) {
1405
- this._value = value;
1406
- }
1407
- /**
1408
- * This is cached data.
1409
- * It was generated at the time of caching, so there is a risk of modification if it's an object due to shallow copying.
1410
- * Therefore, if it's not a primitive type, please avoid using this value directly and use the `clone` method to use a copied version of the data.
1411
- */
1412
- get raw() {
1413
- return this._value;
1414
- }
1415
- /**
1416
- * The method returns a copied value of the cached data.
1417
- * You can pass a function as a parameter to copy the value. This parameter function should return the copied value.
1418
- *
1419
- * If no parameter is passed, it defaults to using `structuredClone` function to copy the value.
1420
- * If you prefer shallow copying instead of deep copying,
1421
- * you can use the default options `array-shallow-copy`, `object-shallow-copy` and `deep-copy`,
1422
- * which are replaced with functions to shallow copy arrays and objects, respectively. This is a syntactic sugar.
1423
- * @param strategy The function that returns the copied value.
1424
- * If you want to perform a shallow copy, simply pass the strings `array-shallow-copy` or `object-shallow-copy` for easy use.
1425
- * The `array-shallow-copy` strategy performs a shallow copy of an array.
1426
- * The `object-shallow-copy` strategy performs a shallow copy of an object.
1427
- * The `deep-copy` strategy performs a deep copy of the value using `structuredClone`.
1428
- * The default is `deep-copy`.
1429
- */
1430
- clone(strategy = "deep-copy") {
1431
- if (strategy && typeof strategy !== "string") {
1432
- return strategy(this.raw);
1433
- }
1434
- switch (strategy) {
1435
- case "array-shallow-copy":
1436
- return [].concat(this.raw);
1437
- case "object-shallow-copy":
1438
- return Object.assign({}, this.raw);
1439
- case "deep-copy":
1440
- default:
1441
- return _CacheData.StructuredClone(this.raw);
1442
- }
1443
- }
1444
- };
1445
- var CacheEntanglementSync = class extends CacheEntanglement {
1446
- constructor(creation, option) {
1447
- super(creation, option);
1448
- }
1449
- recache(key) {
1450
- if (!this.parameters.has(key)) {
1451
- return;
1452
- }
1453
- if (!this.caches.has(key) || this.updateRequirements.has(key)) {
1454
- this.resolve(key, ...this.parameters.get(key));
1455
- }
1456
- return this.caches.get(key);
1457
- }
1458
- resolve(key, ...parameter) {
1459
- const resolved = {};
1460
- const dependencyKey = this.dependencyKey(key);
1461
- this.beforeUpdateHook(key, dependencyKey, ...parameter);
1462
- for (let i = 0, len = this.dependencyProperties.length; i < len; i++) {
1463
- const name = this.dependencyProperties[i];
1464
- const dependency = this.dependencies[name];
1465
- if (!dependency.exists(key) && !dependency.exists(dependencyKey)) {
1466
- throw new Error(`The key '${key}' or '${dependencyKey}' has not been assigned yet in dependency '${name.toString()}'.`, {
1467
- cause: {
1468
- from: this
1469
- }
1470
- });
1471
- }
1472
- const dependencyValue = dependency.recache(key) ?? dependency.recache(dependencyKey);
1473
- resolved[name] = dependencyValue;
1474
- }
1475
- const value = new CacheData(this.creation(key, resolved, ...parameter));
1476
- this.updateRequirements.delete(key);
1477
- this.parameters.set(key, parameter);
1478
- this.caches.set(key, value);
1479
- return value;
1480
- }
1481
- get(key) {
1482
- if (!this.parameters.has(key)) {
1483
- throw new Error(`Cache value not found: ${key}`);
1484
- }
1485
- return this.cache(key, ...this.parameters.get(key));
1486
- }
1487
- cache(key, ...parameter) {
1488
- if (!this.caches.has(key) || this.updateRequirements.has(key)) {
1489
- this.resolve(key, ...parameter);
1490
- }
1491
- return this.caches.get(key);
1492
- }
1493
- update(key, ...parameter) {
1494
- this.bubbleUpdateSignal(key);
1495
- this.resolve(key, ...parameter);
1496
- return this.caches.get(key);
1497
- }
1498
- };
1499
-
1500
- // src/base/BPTreeTransaction.ts
1501
- var BPTreeTransaction = class _BPTreeTransaction {
1502
- _cachedRegexp;
1503
- nodes;
1504
- deletedNodeBuffer = /* @__PURE__ */ new Map();
1505
- rootTx;
1506
- mvccRoot;
1507
- mvcc;
1508
- strategy;
1509
- comparator;
1510
- option;
1511
- order;
1512
- rootId;
1513
- verifierMap = {
1514
- gt: (nv, v) => this.comparator.isHigher(nv, v),
1515
- gte: (nv, v) => this.comparator.isHigher(nv, v) || this.comparator.isSame(nv, v),
1516
- lt: (nv, v) => this.comparator.isLower(nv, v),
1517
- lte: (nv, v) => this.comparator.isLower(nv, v) || this.comparator.isSame(nv, v),
1518
- equal: (nv, v) => this.comparator.isSame(nv, v),
1519
- notEqual: (nv, v) => this.comparator.isSame(nv, v) === false,
1520
- or: (nv, v) => this.ensureValues(v).some((v2) => this.comparator.isSame(nv, v2)),
1521
- primaryGt: (nv, v) => this.comparator.isPrimaryHigher(nv, v),
1522
- primaryGte: (nv, v) => this.comparator.isPrimaryHigher(nv, v) || this.comparator.isPrimarySame(nv, v),
1523
- primaryLt: (nv, v) => this.comparator.isPrimaryLower(nv, v),
1524
- primaryLte: (nv, v) => this.comparator.isPrimaryLower(nv, v) || this.comparator.isPrimarySame(nv, v),
1525
- primaryEqual: (nv, v) => this.comparator.isPrimarySame(nv, v),
1526
- primaryNotEqual: (nv, v) => this.comparator.isPrimarySame(nv, v) === false,
1527
- primaryOr: (nv, v) => this.ensureValues(v).some((v2) => this.comparator.isPrimarySame(nv, v2)),
1528
- like: (nv, v) => {
1529
- const nodeValue = this.comparator.match(nv);
1530
- const value = v;
1531
- const cache = this._cachedRegexp.cache(value);
1532
- const regexp = cache.raw;
1533
- return regexp.test(nodeValue);
1393
+ // src/base/BPTreeTransaction.ts
1394
+ var BPTreeTransaction = class _BPTreeTransaction {
1395
+ _cachedRegexp = /* @__PURE__ */ new Map();
1396
+ nodes = /* @__PURE__ */ new Map();
1397
+ deletedNodeBuffer = /* @__PURE__ */ new Map();
1398
+ rootTx;
1399
+ mvccRoot;
1400
+ mvcc;
1401
+ strategy;
1402
+ comparator;
1403
+ option;
1404
+ order;
1405
+ rootId;
1406
+ isInitialized = false;
1407
+ isDestroyed = false;
1408
+ verifierMap = {
1409
+ gt: (nv, v) => this.comparator.isHigher(nv, v),
1410
+ gte: (nv, v) => this.comparator.isHigher(nv, v) || this.comparator.isSame(nv, v),
1411
+ lt: (nv, v) => this.comparator.isLower(nv, v),
1412
+ lte: (nv, v) => this.comparator.isLower(nv, v) || this.comparator.isSame(nv, v),
1413
+ equal: (nv, v) => this.comparator.isSame(nv, v),
1414
+ notEqual: (nv, v) => this.comparator.isSame(nv, v) === false,
1415
+ or: (nv, v) => this.ensureValues(v).some((v2) => this.comparator.isSame(nv, v2)),
1416
+ primaryGt: (nv, v) => this.comparator.isPrimaryHigher(nv, v),
1417
+ primaryGte: (nv, v) => this.comparator.isPrimaryHigher(nv, v) || this.comparator.isPrimarySame(nv, v),
1418
+ primaryLt: (nv, v) => this.comparator.isPrimaryLower(nv, v),
1419
+ primaryLte: (nv, v) => this.comparator.isPrimaryLower(nv, v) || this.comparator.isPrimarySame(nv, v),
1420
+ primaryEqual: (nv, v) => this.comparator.isPrimarySame(nv, v),
1421
+ primaryNotEqual: (nv, v) => this.comparator.isPrimarySame(nv, v) === false,
1422
+ primaryOr: (nv, v) => this.ensureValues(v).some((v2) => this.comparator.isPrimarySame(nv, v2)),
1423
+ like: (nv, v) => {
1424
+ const nodeValue = this.comparator.match(nv);
1425
+ const value = v;
1426
+ if (!this._cachedRegexp.has(value)) {
1427
+ const pattern = value.replace(/%/g, ".*").replace(/_/g, ".");
1428
+ const regexp2 = new RegExp(`^${pattern}$`, "i");
1429
+ this._cachedRegexp.set(value, regexp2);
1430
+ }
1431
+ const regexp = this._cachedRegexp.get(value);
1432
+ return regexp.test(nodeValue);
1534
1433
  }
1535
1434
  };
1536
1435
  verifierStartNode = {
@@ -1701,6 +1600,9 @@ var BPTreeTransaction = class _BPTreeTransaction {
1701
1600
  }
1702
1601
  return true;
1703
1602
  }
1603
+ _cloneNode(node) {
1604
+ return JSON.parse(JSON.stringify(node));
1605
+ }
1704
1606
  /**
1705
1607
  * Selects the best driver key from a condition object.
1706
1608
  * The driver key determines the starting point and traversal direction for queries.
@@ -1733,17 +1635,6 @@ var BPTreeTransaction = class _BPTreeTransaction {
1733
1635
  this.strategy = strategy;
1734
1636
  this.comparator = comparator;
1735
1637
  this.option = option ?? {};
1736
- this.nodes = new LRUMap(this.option.capacity ?? 1e3);
1737
- this._cachedRegexp = this._createCachedRegexp();
1738
- }
1739
- _createCachedRegexp() {
1740
- return new CacheEntanglementSync((key) => {
1741
- const pattern = key.replace(/%/g, ".*").replace(/_/g, ".");
1742
- const regexp = new RegExp(`^${pattern}$`, "i");
1743
- return regexp;
1744
- }, {
1745
- capacity: this.option.capacity ?? 1e3
1746
- });
1747
1638
  }
1748
1639
  ensureValues(v) {
1749
1640
  if (!Array.isArray(v)) {
@@ -1774,13 +1665,25 @@ var BPTreeTransaction = class _BPTreeTransaction {
1774
1665
  getResultEntries() {
1775
1666
  return this.mvcc.getResultEntries();
1776
1667
  }
1668
+ _clearCache() {
1669
+ this._cachedRegexp.clear();
1670
+ }
1777
1671
  /**
1778
1672
  * Clears all cached nodes.
1779
1673
  * This method is useful for freeing up memory when the tree is no longer needed.
1780
1674
  */
1781
1675
  clear() {
1782
- this._cachedRegexp.clear();
1783
- this.nodes.clear();
1676
+ if (this.rootTx !== this) {
1677
+ throw new Error("Cannot call clear on a nested transaction");
1678
+ }
1679
+ this._clearInternal();
1680
+ }
1681
+ _clearInternal() {
1682
+ if (this.isDestroyed) {
1683
+ throw new Error("Transaction already destroyed");
1684
+ }
1685
+ this._clearCache();
1686
+ this.isDestroyed = true;
1784
1687
  }
1785
1688
  _binarySearchValues(values, target, usePrimary = false, upperBound = false) {
1786
1689
  let low = 0;
@@ -1816,9 +1719,6 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
1816
1719
  );
1817
1720
  }
1818
1721
  getNode(id) {
1819
- if (this.nodes.has(id)) {
1820
- return this.nodes.get(id);
1821
- }
1822
1722
  return this.mvcc.read(id);
1823
1723
  }
1824
1724
  /**
@@ -1836,23 +1736,22 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
1836
1736
  prev
1837
1737
  };
1838
1738
  this.mvcc.create(id, node);
1839
- this.nodes.set(id, node);
1840
1739
  return node;
1841
1740
  }
1842
1741
  _updateNode(node) {
1742
+ if (this.mvcc.isDeleted(node.id)) {
1743
+ return;
1744
+ }
1843
1745
  this.mvcc.write(node.id, node);
1844
- this.nodes.set(node.id, node);
1845
1746
  }
1846
1747
  _deleteNode(node) {
1748
+ if (this.mvcc.isDeleted(node.id)) {
1749
+ return;
1750
+ }
1847
1751
  this.mvcc.delete(node.id);
1848
- this.nodes.delete(node.id);
1849
1752
  }
1850
1753
  _readHead() {
1851
- if (this.nodes.has("__HEAD__")) {
1852
- return this.nodes.get("__HEAD__") ?? null;
1853
- }
1854
- const head = this.mvcc.read("__HEAD__");
1855
- return head ?? null;
1754
+ return this.mvcc.read("__HEAD__");
1856
1755
  }
1857
1756
  _writeHead(head) {
1858
1757
  if (!this.mvcc.exists("__HEAD__")) {
@@ -1860,41 +1759,45 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
1860
1759
  } else {
1861
1760
  this.mvcc.write("__HEAD__", head);
1862
1761
  }
1863
- this.nodes.set("__HEAD__", head);
1864
1762
  this.rootId = head.root;
1865
1763
  }
1866
1764
  _insertAtLeaf(node, key, value) {
1867
- if (node.values.length) {
1868
- for (let i = 0, len = node.values.length; i < len; i++) {
1869
- const nValue = node.values[i];
1765
+ let leaf = node;
1766
+ leaf = this._cloneNode(leaf);
1767
+ if (leaf.values.length) {
1768
+ for (let i = 0, len = leaf.values.length; i < len; i++) {
1769
+ const nValue = leaf.values[i];
1870
1770
  if (this.comparator.isSame(value, nValue)) {
1871
- const keys = node.keys[i];
1771
+ const keys = leaf.keys[i];
1872
1772
  if (keys.includes(key)) {
1873
1773
  break;
1874
1774
  }
1875
1775
  keys.push(key);
1876
- this._updateNode(node);
1877
- return;
1776
+ this._updateNode(leaf);
1777
+ return leaf;
1878
1778
  } else if (this.comparator.isLower(value, nValue)) {
1879
- node.values.splice(i, 0, value);
1880
- node.keys.splice(i, 0, [key]);
1881
- this._updateNode(node);
1882
- return;
1883
- } else if (i + 1 === node.values.length) {
1884
- node.values.push(value);
1885
- node.keys.push([key]);
1886
- this._updateNode(node);
1887
- return;
1779
+ leaf.values.splice(i, 0, value);
1780
+ leaf.keys.splice(i, 0, [key]);
1781
+ this._updateNode(leaf);
1782
+ return leaf;
1783
+ } else if (i + 1 === leaf.values.length) {
1784
+ leaf.values.push(value);
1785
+ leaf.keys.push([key]);
1786
+ this._updateNode(leaf);
1787
+ return leaf;
1888
1788
  }
1889
1789
  }
1890
1790
  } else {
1891
- node.values = [value];
1892
- node.keys = [[key]];
1893
- this._updateNode(node);
1894
- return;
1791
+ leaf.values = [value];
1792
+ leaf.keys = [[key]];
1793
+ this._updateNode(leaf);
1794
+ return leaf;
1895
1795
  }
1796
+ return leaf;
1896
1797
  }
1897
1798
  _insertInParent(node, value, pointer) {
1799
+ node = this._cloneNode(node);
1800
+ pointer = this._cloneNode(pointer);
1898
1801
  if (this.rootId === node.id) {
1899
1802
  const root = this._createNode(false, [node.id, pointer.id], [value]);
1900
1803
  this.rootId = root.id;
@@ -1913,7 +1816,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
1913
1816
  this._updateNode(pointer);
1914
1817
  return;
1915
1818
  }
1916
- const parentNode = this.getNode(node.parent);
1819
+ const parentNode = this._cloneNode(this.getNode(node.parent));
1917
1820
  const nodeIndex = parentNode.keys.indexOf(node.id);
1918
1821
  if (nodeIndex === -1) {
1919
1822
  throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
@@ -1929,7 +1832,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
1929
1832
  leftSibling.next = pointer.id;
1930
1833
  this._updateNode(leftSibling);
1931
1834
  if (oldNextId) {
1932
- const oldNext = this.getNode(oldNextId);
1835
+ const oldNext = this._cloneNode(this.getNode(oldNextId));
1933
1836
  oldNext.prev = pointer.id;
1934
1837
  this._updateNode(oldNext);
1935
1838
  }
@@ -1946,12 +1849,12 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
1946
1849
  parentNode.values = parentNode.values.slice(0, mid);
1947
1850
  parentNode.keys = parentNode.keys.slice(0, mid + 1);
1948
1851
  for (const k of parentNode.keys) {
1949
- const n = this.getNode(k);
1852
+ const n = this._cloneNode(this.getNode(k));
1950
1853
  n.parent = parentNode.id;
1951
1854
  this._updateNode(n);
1952
1855
  }
1953
1856
  for (const k of parentPointer.keys) {
1954
- const n = this.getNode(k);
1857
+ const n = this._cloneNode(this.getNode(k));
1955
1858
  n.parent = parentPointer.id;
1956
1859
  this._updateNode(n);
1957
1860
  }
@@ -2086,28 +1989,46 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2086
1989
  }
2087
1990
  }
2088
1991
  init() {
2089
- this.clear();
2090
- const head = this._readHead();
2091
- if (head === null) {
2092
- this.order = this.strategy.order;
2093
- const root = this._createNode(true, [], []);
2094
- this._writeHead({
2095
- root: root.id,
2096
- order: this.order,
2097
- data: this.strategy.head.data
2098
- });
2099
- } else {
2100
- const { root, order } = head;
2101
- this.strategy.head = head;
2102
- this.order = order;
2103
- this._writeHead({
2104
- root,
2105
- order: this.order,
2106
- data: this.strategy.head.data
2107
- });
1992
+ if (this.rootTx !== this) {
1993
+ throw new Error("Cannot call init on a nested transaction");
1994
+ }
1995
+ this._initInternal();
1996
+ }
1997
+ _initInternal() {
1998
+ if (this.isInitialized) {
1999
+ throw new Error("Transaction already initialized");
2000
+ }
2001
+ if (this.isDestroyed) {
2002
+ throw new Error("Transaction already destroyed");
2108
2003
  }
2109
- if (this.order < 3) {
2110
- throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
2004
+ this.isInitialized = true;
2005
+ try {
2006
+ this._clearCache();
2007
+ const head = this._readHead();
2008
+ if (head === null) {
2009
+ this.order = this.strategy.order;
2010
+ const root = this._createNode(true, [], []);
2011
+ this._writeHead({
2012
+ root: root.id,
2013
+ order: this.order,
2014
+ data: this.strategy.head.data
2015
+ });
2016
+ } else {
2017
+ const { root, order } = head;
2018
+ this.strategy.head = head;
2019
+ this.order = order;
2020
+ this._writeHead({
2021
+ root,
2022
+ order: this.order,
2023
+ data: this.strategy.head.data
2024
+ });
2025
+ }
2026
+ if (this.order < 3) {
2027
+ throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
2028
+ }
2029
+ } catch (e) {
2030
+ this.isInitialized = false;
2031
+ throw e;
2111
2032
  }
2112
2033
  }
2113
2034
  exists(key, value) {
@@ -2121,21 +2042,6 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2121
2042
  }
2122
2043
  return false;
2123
2044
  }
2124
- forceUpdate(id) {
2125
- if (id) {
2126
- this.nodes.delete(id);
2127
- this.getNode(id);
2128
- return 1;
2129
- }
2130
- const keys = Array.from(this.nodes.keys());
2131
- for (const key of keys) {
2132
- this.nodes.delete(key);
2133
- }
2134
- for (const key of keys) {
2135
- this.getNode(key);
2136
- }
2137
- return keys.length;
2138
- }
2139
2045
  get(key) {
2140
2046
  let node = this.leftestNode();
2141
2047
  while (true) {
@@ -2221,10 +2127,10 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2221
2127
  return map;
2222
2128
  }
2223
2129
  insert(key, value) {
2224
- const before = this.insertableNode(value);
2225
- this._insertAtLeaf(before, key, value);
2130
+ let before = this.insertableNode(value);
2131
+ before = this._insertAtLeaf(before, key, value);
2226
2132
  if (before.values.length === this.order) {
2227
- const after = this._createNode(
2133
+ let after = this._createNode(
2228
2134
  true,
2229
2135
  [],
2230
2136
  [],
@@ -2233,14 +2139,18 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2233
2139
  null
2234
2140
  );
2235
2141
  const mid = Math.ceil(this.order / 2) - 1;
2142
+ after = this._cloneNode(after);
2236
2143
  after.values = before.values.slice(mid + 1);
2237
2144
  after.keys = before.keys.slice(mid + 1);
2238
2145
  before.values = before.values.slice(0, mid + 1);
2239
2146
  before.keys = before.keys.slice(0, mid + 1);
2147
+ this._updateNode(before);
2148
+ this._updateNode(after);
2240
2149
  this._insertInParent(before, after.values[0], after);
2241
2150
  }
2242
2151
  }
2243
2152
  _deleteEntry(node, key) {
2153
+ node = this._cloneNode(node);
2244
2154
  if (!node.leaf) {
2245
2155
  let keyIndex = -1;
2246
2156
  for (let i = 0, len = node.keys.length; i < len; i++) {
@@ -2259,7 +2169,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2259
2169
  if (this.rootId === node.id && node.keys.length === 1 && !node.leaf) {
2260
2170
  const keys = node.keys;
2261
2171
  this._deleteNode(node);
2262
- const newRoot = this.getNode(keys[0]);
2172
+ const newRoot = this._cloneNode(this.getNode(keys[0]));
2263
2173
  newRoot.parent = null;
2264
2174
  this._updateNode(newRoot);
2265
2175
  this._writeHead({
@@ -2267,17 +2177,17 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2267
2177
  order: this.order,
2268
2178
  data: this.strategy.head.data
2269
2179
  });
2270
- return;
2180
+ return node;
2271
2181
  } else if (this.rootId === node.id) {
2272
2182
  this._writeHead({
2273
2183
  root: node.id,
2274
2184
  order: this.order,
2275
2185
  data: this.strategy.head.data
2276
2186
  });
2277
- return;
2187
+ return node;
2278
2188
  } else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
2279
2189
  if (node.parent === null) {
2280
- return;
2190
+ return node;
2281
2191
  }
2282
2192
  let isPredecessor = false;
2283
2193
  let parentNode = this.getNode(node.parent);
@@ -2289,11 +2199,11 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2289
2199
  const nKey = parentNode.keys[i];
2290
2200
  if (nKey === node.id) {
2291
2201
  if (i > 0) {
2292
- prevNode = this.getNode(parentNode.keys[i - 1]);
2202
+ prevNode = this._cloneNode(this.getNode(parentNode.keys[i - 1]));
2293
2203
  prevValue = parentNode.values[i - 1];
2294
2204
  }
2295
2205
  if (i < parentNode.keys.length - 1) {
2296
- nextNode = this.getNode(parentNode.keys[i + 1]);
2206
+ nextNode = this._cloneNode(this.getNode(parentNode.keys[i + 1]));
2297
2207
  postValue = parentNode.values[i];
2298
2208
  }
2299
2209
  }
@@ -2318,7 +2228,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2318
2228
  }
2319
2229
  }
2320
2230
  if (!pointer) {
2321
- return;
2231
+ return node;
2322
2232
  }
2323
2233
  if (node.values.length + pointer.values.length < this.order) {
2324
2234
  if (!isPredecessor) {
@@ -2332,7 +2242,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2332
2242
  } else {
2333
2243
  pointer.next = node.next;
2334
2244
  if (pointer.next) {
2335
- const n = this.getNode(pointer.next);
2245
+ const n = this._cloneNode(this.getNode(pointer.next));
2336
2246
  n.prev = pointer.id;
2337
2247
  this._updateNode(n);
2338
2248
  }
@@ -2341,14 +2251,14 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2341
2251
  if (!pointer.leaf) {
2342
2252
  const keys = pointer.keys;
2343
2253
  for (const key2 of keys) {
2344
- const node2 = this.getNode(key2);
2254
+ const node2 = this._cloneNode(this.getNode(key2));
2345
2255
  node2.parent = pointer.id;
2346
2256
  this._updateNode(node2);
2347
2257
  }
2348
2258
  }
2349
2259
  this._deleteNode(node);
2350
2260
  this._updateNode(pointer);
2351
- this._deleteEntry(this.getNode(node.parent), node.id);
2261
+ this._deleteEntry(this._cloneNode(this.getNode(node.parent)), node.id);
2352
2262
  } else {
2353
2263
  if (isPredecessor) {
2354
2264
  let pointerPm;
@@ -2358,7 +2268,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2358
2268
  pointerKm = pointer.values.splice(-1)[0];
2359
2269
  node.keys = [pointerPm, ...node.keys];
2360
2270
  node.values = [guess, ...node.values];
2361
- parentNode = this.getNode(node.parent);
2271
+ parentNode = this._cloneNode(this.getNode(node.parent));
2362
2272
  const nodeIndex = parentNode.keys.indexOf(node.id);
2363
2273
  if (nodeIndex > 0) {
2364
2274
  parentNode.values[nodeIndex - 1] = pointerKm;
@@ -2369,7 +2279,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2369
2279
  pointerKm = pointer.values.splice(-1)[0];
2370
2280
  node.keys = [pointerPm, ...node.keys];
2371
2281
  node.values = [pointerKm, ...node.values];
2372
- parentNode = this.getNode(node.parent);
2282
+ parentNode = this._cloneNode(this.getNode(node.parent));
2373
2283
  const nodeIndex = parentNode.keys.indexOf(node.id);
2374
2284
  if (nodeIndex > 0) {
2375
2285
  parentNode.values[nodeIndex - 1] = pointerKm;
@@ -2386,7 +2296,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2386
2296
  pointerK0 = pointer.values.splice(0, 1)[0];
2387
2297
  node.keys = [...node.keys, pointerP0];
2388
2298
  node.values = [...node.values, guess];
2389
- parentNode = this.getNode(node.parent);
2299
+ parentNode = this._cloneNode(this.getNode(node.parent));
2390
2300
  const pointerIndex = parentNode.keys.indexOf(pointer.id);
2391
2301
  if (pointerIndex > 0) {
2392
2302
  parentNode.values[pointerIndex - 1] = pointerK0;
@@ -2397,7 +2307,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2397
2307
  pointerK0 = pointer.values.splice(0, 1)[0];
2398
2308
  node.keys = [...node.keys, pointerP0];
2399
2309
  node.values = [...node.values, pointerK0];
2400
- parentNode = this.getNode(node.parent);
2310
+ parentNode = this._cloneNode(this.getNode(node.parent));
2401
2311
  const pointerIndex = parentNode.keys.indexOf(pointer.id);
2402
2312
  if (pointerIndex > 0) {
2403
2313
  parentNode.values[pointerIndex - 1] = pointer.values[0];
@@ -2409,21 +2319,21 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2409
2319
  }
2410
2320
  if (!pointer.leaf) {
2411
2321
  for (const key2 of pointer.keys) {
2412
- const n = this.getNode(key2);
2322
+ const n = this._cloneNode(this.getNode(key2));
2413
2323
  n.parent = pointer.id;
2414
2324
  this._updateNode(n);
2415
2325
  }
2416
2326
  }
2417
2327
  if (!node.leaf) {
2418
2328
  for (const key2 of node.keys) {
2419
- const n = this.getNode(key2);
2329
+ const n = this._cloneNode(this.getNode(key2));
2420
2330
  n.parent = node.id;
2421
2331
  this._updateNode(n);
2422
2332
  }
2423
2333
  }
2424
2334
  if (!parentNode.leaf) {
2425
2335
  for (const key2 of parentNode.keys) {
2426
- const n = this.getNode(key2);
2336
+ const n = this._cloneNode(this.getNode(key2));
2427
2337
  n.parent = parentNode.id;
2428
2338
  this._updateNode(n);
2429
2339
  }
@@ -2432,10 +2342,12 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2432
2342
  } else {
2433
2343
  this._updateNode(node);
2434
2344
  }
2345
+ return node;
2435
2346
  }
2436
2347
  delete(key, value) {
2437
2348
  let node = this.insertableNodeByPrimary(value);
2438
2349
  let found = false;
2350
+ node = this._cloneNode(node);
2439
2351
  while (true) {
2440
2352
  let i = node.values.length;
2441
2353
  while (i--) {
@@ -2450,7 +2362,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2450
2362
  node.values.splice(i, 1);
2451
2363
  }
2452
2364
  this._updateNode(node);
2453
- this._deleteEntry(node, key);
2365
+ node = this._deleteEntry(node, key);
2454
2366
  found = true;
2455
2367
  break;
2456
2368
  }
@@ -2485,20 +2397,14 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2485
2397
  commit(label) {
2486
2398
  let result = this.mvcc.commit(label);
2487
2399
  if (result.success) {
2488
- result = this.mvccRoot.commit(label);
2489
- if (result.success && this.rootTx !== this) {
2490
- this.rootTx.rootId = this.rootId;
2400
+ const isRootTx = this.rootTx !== this;
2401
+ if (isRootTx) {
2402
+ result = this.rootTx.commit(label);
2403
+ if (result.success) {
2404
+ this.rootTx.rootId = this.rootId;
2405
+ }
2491
2406
  }
2492
2407
  if (result.success) {
2493
- for (const r of result.created) {
2494
- this.nodes.set(r.key, r.data);
2495
- }
2496
- for (const r of result.updated) {
2497
- this.nodes.set(r.key, r.data);
2498
- }
2499
- for (const r of result.deleted) {
2500
- this.nodes.delete(r.key);
2501
- }
2502
2408
  }
2503
2409
  }
2504
2410
  return result;
@@ -2546,7 +2452,9 @@ var BPTreeMVCCStrategySync = class extends SyncMVCCStrategy {
2546
2452
  // src/BPTreeSync.ts
2547
2453
  var BPTreeSync = class extends BPTreeSyncTransaction {
2548
2454
  constructor(strategy, comparator, option) {
2549
- const mvccRoot = new SyncMVCCTransaction(new BPTreeMVCCStrategySync(strategy));
2455
+ const mvccRoot = new SyncMVCCTransaction(new BPTreeMVCCStrategySync(strategy), {
2456
+ cacheCapacity: option?.capacity ?? void 0
2457
+ });
2550
2458
  super(
2551
2459
  null,
2552
2460
  mvccRoot,
@@ -2570,7 +2478,7 @@ var BPTreeSync = class extends BPTreeSyncTransaction {
2570
2478
  this.comparator,
2571
2479
  this.option
2572
2480
  );
2573
- tx.init();
2481
+ tx._initInternal();
2574
2482
  return tx;
2575
2483
  }
2576
2484
  insert(key, value) {
@@ -2580,7 +2488,6 @@ var BPTreeSync = class extends BPTreeSyncTransaction {
2580
2488
  if (!result.success) {
2581
2489
  throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
2582
2490
  }
2583
- this.rootId = tx.getRootId();
2584
2491
  }
2585
2492
  delete(key, value) {
2586
2493
  const tx = this.createTransaction();
@@ -2589,394 +2496,673 @@ var BPTreeSync = class extends BPTreeSyncTransaction {
2589
2496
  if (!result.success) {
2590
2497
  throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
2591
2498
  }
2592
- this.rootId = tx.getRootId();
2593
2499
  }
2594
2500
  };
2595
2501
 
2596
- // src/transaction/BPTreeAsyncTransaction.ts
2597
- var BPTreeAsyncTransaction = class extends BPTreeTransaction {
2598
- constructor(rootTx, mvccRoot, mvcc, strategy, comparator, option) {
2599
- super(
2600
- rootTx,
2601
- mvccRoot,
2602
- mvcc,
2603
- strategy,
2604
- comparator,
2605
- option
2606
- );
2502
+ // node_modules/ryoiki/dist/esm/index.mjs
2503
+ var Ryoiki2 = class _Ryoiki2 {
2504
+ readings;
2505
+ writings;
2506
+ readQueue;
2507
+ writeQueue;
2508
+ static async CatchError(promise) {
2509
+ return await promise.then((v) => [void 0, v]).catch((err) => [err]);
2607
2510
  }
2608
- async getNode(id) {
2609
- if (this.nodes.has(id)) {
2610
- return this.nodes.get(id);
2511
+ static IsRangeOverlap(a, b) {
2512
+ const [start1, end1] = a;
2513
+ const [start2, end2] = b;
2514
+ if (end1 <= start2 || end2 <= start1) {
2515
+ return false;
2611
2516
  }
2612
- return await this.mvcc.read(id);
2517
+ return true;
2518
+ }
2519
+ static ERR_ALREADY_EXISTS(lockId) {
2520
+ return new Error(`The '${lockId}' task already existing in queue or running.`);
2521
+ }
2522
+ static ERR_NOT_EXISTS(lockId) {
2523
+ return new Error(`The '${lockId}' task not existing in task queue.`);
2524
+ }
2525
+ static ERR_TIMEOUT(lockId, timeout) {
2526
+ return new Error(`The task with ID '${lockId}' failed to acquire the lock within the timeout(${timeout}ms).`);
2613
2527
  }
2614
2528
  /**
2615
- * Create a new node with a unique ID.
2529
+ * Constructs a new instance of the Ryoiki class.
2616
2530
  */
2617
- async _createNode(leaf, keys, values, parent = null, next = null, prev = null) {
2618
- const id = await this.strategy.id(leaf);
2619
- const node = {
2620
- id,
2621
- keys,
2622
- values,
2623
- leaf,
2624
- parent,
2625
- next,
2626
- prev
2627
- };
2628
- await this.mvcc.create(id, node);
2629
- this.nodes.set(id, node);
2630
- return node;
2531
+ constructor() {
2532
+ this.readings = /* @__PURE__ */ new Map();
2533
+ this.writings = /* @__PURE__ */ new Map();
2534
+ this.readQueue = /* @__PURE__ */ new Map();
2535
+ this.writeQueue = /* @__PURE__ */ new Map();
2631
2536
  }
2632
- async _updateNode(node) {
2633
- await this.mvcc.write(node.id, node);
2634
- this.nodes.set(node.id, node);
2537
+ /**
2538
+ * Creates a range based on a start value and length.
2539
+ * @param start - The starting value of the range.
2540
+ * @param length - The length of the range.
2541
+ * @returns A range tuple [start, start + length].
2542
+ */
2543
+ range(start, length) {
2544
+ return [start, start + length];
2635
2545
  }
2636
- async _deleteNode(node) {
2637
- await this.mvcc.delete(node.id);
2638
- this.nodes.delete(node.id);
2546
+ rangeOverlapping(tasks, range) {
2547
+ return Array.from(tasks.values()).some((t) => _Ryoiki2.IsRangeOverlap(t.range, range));
2639
2548
  }
2640
- async _readHead() {
2641
- if (this.nodes.has("__HEAD__")) {
2642
- return this.nodes.get("__HEAD__") ?? null;
2643
- }
2644
- const head = await this.mvcc.read("__HEAD__");
2645
- return head ?? null;
2549
+ isSameRange(a, b) {
2550
+ const [a1, a2] = a;
2551
+ const [b1, b2] = b;
2552
+ return a1 === b1 && a2 === b2;
2646
2553
  }
2647
- async _writeHead(head) {
2648
- if (!await this.mvcc.exists("__HEAD__")) {
2649
- await this.mvcc.create("__HEAD__", head);
2650
- } else {
2651
- await this.mvcc.write("__HEAD__", head);
2554
+ fetchUnitAndRun(queue, workspaces) {
2555
+ for (const [id, unit] of queue) {
2556
+ if (!unit.condition()) {
2557
+ continue;
2558
+ }
2559
+ this._alloc(queue, workspaces, id);
2652
2560
  }
2653
- this.nodes.set("__HEAD__", head);
2654
- this.rootId = head.root;
2655
2561
  }
2656
- async _insertAtLeaf(node, key, value) {
2657
- if (node.values.length) {
2658
- for (let i = 0, len = node.values.length; i < len; i++) {
2659
- const nValue = node.values[i];
2660
- if (this.comparator.isSame(value, nValue)) {
2661
- const keys = node.keys[i];
2662
- if (keys.includes(key)) {
2663
- break;
2664
- }
2665
- keys.push(key);
2666
- await this._updateNode(node);
2667
- return;
2668
- } else if (this.comparator.isLower(value, nValue)) {
2669
- node.values.splice(i, 0, value);
2670
- node.keys.splice(i, 0, [key]);
2671
- await this._updateNode(node);
2672
- return;
2673
- } else if (i + 1 === node.values.length) {
2674
- node.values.push(value);
2675
- node.keys.push([key]);
2676
- await this._updateNode(node);
2677
- return;
2678
- }
2679
- }
2680
- } else {
2681
- node.values = [value];
2682
- node.keys = [[key]];
2683
- await this._updateNode(node);
2684
- return;
2685
- }
2686
- }
2687
- async _insertInParent(node, value, pointer) {
2688
- if (this.rootId === node.id) {
2689
- const root = await this._createNode(false, [node.id, pointer.id], [value]);
2690
- this.rootId = root.id;
2691
- node.parent = root.id;
2692
- pointer.parent = root.id;
2693
- if (pointer.leaf) {
2694
- node.next = pointer.id;
2695
- pointer.prev = node.id;
2696
- }
2697
- await this._writeHead({
2698
- root: root.id,
2699
- order: this.order,
2700
- data: this.strategy.head.data
2701
- });
2702
- await this._updateNode(node);
2703
- await this._updateNode(pointer);
2704
- return;
2705
- }
2706
- const parentNode = await this.getNode(node.parent);
2707
- const nodeIndex = parentNode.keys.indexOf(node.id);
2708
- if (nodeIndex === -1) {
2709
- throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
2710
- }
2711
- parentNode.values.splice(nodeIndex, 0, value);
2712
- parentNode.keys.splice(nodeIndex + 1, 0, pointer.id);
2713
- pointer.parent = parentNode.id;
2714
- if (pointer.leaf) {
2715
- const leftSibling = node;
2716
- const oldNextId = leftSibling.next;
2717
- pointer.prev = leftSibling.id;
2718
- pointer.next = oldNextId;
2719
- leftSibling.next = pointer.id;
2720
- await this._updateNode(leftSibling);
2721
- if (oldNextId) {
2722
- const oldNext = await this.getNode(oldNextId);
2723
- oldNext.prev = pointer.id;
2724
- await this._updateNode(oldNext);
2725
- }
2726
- }
2727
- await this._updateNode(parentNode);
2728
- await this._updateNode(pointer);
2729
- if (parentNode.keys.length > this.order) {
2730
- const parentPointer = await this._createNode(false, [], []);
2731
- parentPointer.parent = parentNode.parent;
2732
- const mid = Math.ceil(this.order / 2) - 1;
2733
- parentPointer.values = parentNode.values.slice(mid + 1);
2734
- parentPointer.keys = parentNode.keys.slice(mid + 1);
2735
- const midValue = parentNode.values[mid];
2736
- parentNode.values = parentNode.values.slice(0, mid);
2737
- parentNode.keys = parentNode.keys.slice(0, mid + 1);
2738
- for (const k of parentNode.keys) {
2739
- const n = await this.getNode(k);
2740
- n.parent = parentNode.id;
2741
- await this._updateNode(n);
2742
- }
2743
- for (const k of parentPointer.keys) {
2744
- const n = await this.getNode(k);
2745
- n.parent = parentPointer.id;
2746
- await this._updateNode(n);
2562
+ _handleOverload(args, handlers, argPatterns) {
2563
+ for (const [key, pattern] of Object.entries(argPatterns)) {
2564
+ if (this._matchArgs(args, pattern)) {
2565
+ return handlers[key](...args);
2747
2566
  }
2748
- await this._updateNode(parentNode);
2749
- await this._insertInParent(parentNode, midValue, parentPointer);
2750
- }
2751
- }
2752
- async insertableNode(value) {
2753
- let node = await this.getNode(this.rootId);
2754
- while (!node.leaf) {
2755
- const { index } = this._binarySearchValues(node.values, value, false, true);
2756
- node = await this.getNode(node.keys[index]);
2757
- }
2758
- return node;
2759
- }
2760
- async insertableNodeByPrimary(value) {
2761
- let node = await this.getNode(this.rootId);
2762
- while (!node.leaf) {
2763
- const { index } = this._binarySearchValues(node.values, value, true, false);
2764
- node = await this.getNode(node.keys[index]);
2765
- }
2766
- return node;
2767
- }
2768
- async insertableRightestNodeByPrimary(value) {
2769
- let node = await this.getNode(this.rootId);
2770
- while (!node.leaf) {
2771
- const { index } = this._binarySearchValues(node.values, value, true, true);
2772
- node = await this.getNode(node.keys[index]);
2773
2567
  }
2774
- return node;
2568
+ throw new Error("Invalid arguments");
2775
2569
  }
2776
- async insertableRightestEndNodeByPrimary(value) {
2777
- const node = await this.insertableRightestNodeByPrimary(value);
2778
- if (!node.next) {
2779
- return null;
2780
- }
2781
- return await this.getNode(node.next);
2570
+ _matchArgs(args, pattern) {
2571
+ return args.every((arg, index) => {
2572
+ const expectedType = pattern[index];
2573
+ if (expectedType === void 0) return typeof arg === "undefined";
2574
+ if (expectedType === Function) return typeof arg === "function";
2575
+ if (expectedType === Number) return typeof arg === "number";
2576
+ if (expectedType === Array) return Array.isArray(arg);
2577
+ return false;
2578
+ });
2782
2579
  }
2783
- async insertableEndNode(value, direction) {
2784
- const insertableNode = await this.insertableNode(value);
2785
- let key;
2786
- switch (direction) {
2787
- case -1:
2788
- key = "prev";
2789
- break;
2790
- case 1:
2791
- key = "next";
2792
- break;
2793
- default:
2794
- throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
2795
- }
2796
- const guessNode = insertableNode[key];
2797
- if (!guessNode) {
2798
- return null;
2799
- }
2800
- return await this.getNode(guessNode);
2580
+ _createRandomId() {
2581
+ const timestamp = Date.now().toString(36);
2582
+ const random = Math.random().toString(36).substring(2);
2583
+ return `${timestamp}${random}`;
2801
2584
  }
2802
- async leftestNode() {
2803
- let node = await this.getNode(this.rootId);
2804
- if (node === null) {
2805
- debugger;
2806
- }
2807
- while (!node.leaf) {
2808
- const keys = node.keys;
2809
- node = await this.getNode(keys[0]);
2585
+ _alloc(queue, workspaces, lockId) {
2586
+ const unit = queue.get(lockId);
2587
+ if (!unit) {
2588
+ throw _Ryoiki2.ERR_NOT_EXISTS(lockId);
2810
2589
  }
2811
- return node;
2590
+ workspaces.set(lockId, unit);
2591
+ queue.delete(lockId);
2592
+ unit.alloc();
2812
2593
  }
2813
- async rightestNode() {
2814
- let node = await this.getNode(this.rootId);
2815
- while (!node.leaf) {
2816
- const keys = node.keys;
2817
- node = await this.getNode(keys[keys.length - 1]);
2594
+ _free(workspaces, lockId) {
2595
+ const unit = workspaces.get(lockId);
2596
+ if (!unit) {
2597
+ throw _Ryoiki2.ERR_NOT_EXISTS(lockId);
2818
2598
  }
2819
- return node;
2599
+ workspaces.delete(lockId);
2600
+ unit.free();
2820
2601
  }
2821
- async *getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
2822
- let node = startNode;
2823
- let done = false;
2824
- let hasMatched = false;
2825
- let nextNodePromise = null;
2826
- while (!done) {
2827
- if (endNode && node.id === endNode.id) {
2828
- done = true;
2829
- break;
2830
- }
2831
- if (direction === 1) {
2832
- if (node.next && !done) {
2833
- nextNodePromise = this.getNode(node.next);
2834
- }
2835
- } else {
2836
- if (node.prev && !done) {
2837
- nextNodePromise = this.getNode(node.prev);
2838
- }
2602
+ _lock(queue, range, timeout, task, condition) {
2603
+ return new Promise((resolve, reject) => {
2604
+ let timeoutId = null;
2605
+ if (timeout >= 0) {
2606
+ timeoutId = setTimeout(() => {
2607
+ reject(_Ryoiki2.ERR_TIMEOUT(id, timeout));
2608
+ }, timeout);
2839
2609
  }
2840
- const len = node.values.length;
2841
- if (direction === 1) {
2842
- for (let i = 0; i < len; i++) {
2843
- const nValue = node.values[i];
2844
- const keys = node.keys[i];
2845
- if (comparator(nValue, value)) {
2846
- hasMatched = true;
2847
- for (let j = 0; j < keys.length; j++) {
2848
- yield [keys[j], nValue];
2849
- }
2850
- } else if (earlyTerminate && hasMatched) {
2851
- done = true;
2852
- break;
2853
- }
2854
- }
2855
- } else {
2856
- let i = len;
2857
- while (i--) {
2858
- const nValue = node.values[i];
2859
- const keys = node.keys[i];
2860
- if (comparator(nValue, value)) {
2861
- hasMatched = true;
2862
- let j = keys.length;
2863
- while (j--) {
2864
- yield [keys[j], nValue];
2865
- }
2866
- } else if (earlyTerminate && hasMatched) {
2867
- done = true;
2868
- break;
2869
- }
2610
+ const id = this._createRandomId();
2611
+ const alloc = async () => {
2612
+ if (timeoutId !== null) {
2613
+ clearTimeout(timeoutId);
2870
2614
  }
2871
- }
2872
- if (done) {
2873
- if (nextNodePromise) await nextNodePromise;
2615
+ const [err, v] = await _Ryoiki2.CatchError(task(id));
2616
+ if (err) reject(err);
2617
+ else resolve(v);
2618
+ };
2619
+ const fetch = () => {
2620
+ this.fetchUnitAndRun(this.readQueue, this.readings);
2621
+ this.fetchUnitAndRun(this.writeQueue, this.writings);
2622
+ };
2623
+ queue.set(id, { id, range, condition, alloc, free: fetch });
2624
+ fetch();
2625
+ });
2626
+ }
2627
+ _checkWorking(range, workspaces) {
2628
+ let isLocked = false;
2629
+ for (const lock of workspaces.values()) {
2630
+ if (_Ryoiki2.IsRangeOverlap(range, lock.range)) {
2631
+ isLocked = true;
2874
2632
  break;
2875
2633
  }
2876
- if (nextNodePromise) {
2877
- node = await nextNodePromise;
2878
- nextNodePromise = null;
2879
- } else {
2880
- done = true;
2881
- }
2882
2634
  }
2635
+ return isLocked;
2883
2636
  }
2884
- async init() {
2885
- this.clear();
2886
- const head = await this._readHead();
2887
- if (head === null) {
2888
- this.order = this.strategy.order;
2889
- const root = await this._createNode(true, [], []);
2890
- await this._writeHead({
2891
- root: root.id,
2892
- order: this.order,
2893
- data: this.strategy.head.data
2894
- });
2895
- } else {
2896
- const { root, order } = head;
2897
- this.strategy.head = head;
2898
- this.order = order;
2637
+ /**
2638
+ * Checks if there is any active read lock within the specified range.
2639
+ * @param range The range to check for active read locks.
2640
+ * @returns `true` if there is an active read lock within the range, `false` otherwise.
2641
+ */
2642
+ isReading(range) {
2643
+ return this._checkWorking(range, this.readings);
2644
+ }
2645
+ /**
2646
+ * Checks if there is any active write lock within the specified range.
2647
+ * @param range The range to check for active write locks.
2648
+ * @returns `true` if there is an active write lock within the range, `false` otherwise.
2649
+ */
2650
+ isWriting(range) {
2651
+ return this._checkWorking(range, this.writings);
2652
+ }
2653
+ /**
2654
+ * Checks if a read lock can be acquired within the specified range.
2655
+ * @param range The range to check for read lock availability.
2656
+ * @returns `true` if a read lock can be acquired, `false` otherwise.
2657
+ */
2658
+ canRead(range) {
2659
+ const writing = this.isWriting(range);
2660
+ return !writing;
2661
+ }
2662
+ /**
2663
+ * Checks if a write lock can be acquired within the specified range.
2664
+ * @param range The range to check for write lock availability.
2665
+ * @returns `true` if a write lock can be acquired, `false` otherwise.
2666
+ */
2667
+ canWrite(range) {
2668
+ const reading = this.isReading(range);
2669
+ const writing = this.isWriting(range);
2670
+ return !reading && !writing;
2671
+ }
2672
+ /**
2673
+ * Internal implementation of the read lock. Handles both overloads.
2674
+ * @template T - The return type of the task.
2675
+ * @param arg0 - Either a range or a task callback.
2676
+ * If a range is provided, the task is the second argument.
2677
+ * @param arg1 - The task to execute, required if a range is provided.
2678
+ * @param arg2 - The timeout for acquiring the lock.
2679
+ * If the lock cannot be acquired within this period, an error will be thrown.
2680
+ * If this value is not provided, no timeout will be set.
2681
+ * @returns A promise resolving to the result of the task execution.
2682
+ */
2683
+ readLock(arg0, arg1, arg2) {
2684
+ const [range, task, timeout] = this._handleOverload(
2685
+ [arg0, arg1, arg2],
2686
+ {
2687
+ rangeTask: (range2, task2) => [range2, task2, -1],
2688
+ rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
2689
+ task: (task2) => [[-Infinity, Infinity], task2, -1],
2690
+ taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
2691
+ },
2692
+ {
2693
+ task: [Function],
2694
+ taskTimeout: [Function, Number],
2695
+ rangeTask: [Array, Function],
2696
+ rangeTaskTimeout: [Array, Function, Number]
2697
+ }
2698
+ );
2699
+ return this._lock(
2700
+ this.readQueue,
2701
+ range,
2702
+ timeout,
2703
+ task,
2704
+ () => !this.rangeOverlapping(this.writings, range)
2705
+ );
2706
+ }
2707
+ /**
2708
+ * Internal implementation of the write lock. Handles both overloads.
2709
+ * @template T - The return type of the task.
2710
+ * @param arg0 - Either a range or a task callback.
2711
+ * If a range is provided, the task is the second argument.
2712
+ * @param arg1 - The task to execute, required if a range is provided.
2713
+ * @param arg2 - The timeout for acquiring the lock.
2714
+ * If the lock cannot be acquired within this period, an error will be thrown.
2715
+ * If this value is not provided, no timeout will be set.
2716
+ * @returns A promise resolving to the result of the task execution.
2717
+ */
2718
+ writeLock(arg0, arg1, arg2) {
2719
+ const [range, task, timeout] = this._handleOverload(
2720
+ [arg0, arg1, arg2],
2721
+ {
2722
+ rangeTask: (range2, task2) => [range2, task2, -1],
2723
+ rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
2724
+ task: (task2) => [[-Infinity, Infinity], task2, -1],
2725
+ taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
2726
+ },
2727
+ {
2728
+ task: [Function],
2729
+ taskTimeout: [Function, Number],
2730
+ rangeTask: [Array, Function],
2731
+ rangeTaskTimeout: [Array, Function, Number]
2732
+ }
2733
+ );
2734
+ return this._lock(
2735
+ this.writeQueue,
2736
+ range,
2737
+ timeout,
2738
+ task,
2739
+ () => {
2740
+ return !this.rangeOverlapping(this.writings, range) && !this.rangeOverlapping(this.readings, range);
2741
+ }
2742
+ );
2743
+ }
2744
+ /**
2745
+ * Releases a read lock by its lock ID.
2746
+ * @param lockId - The unique identifier for the lock to release.
2747
+ */
2748
+ readUnlock(lockId) {
2749
+ this._free(this.readings, lockId);
2750
+ }
2751
+ /**
2752
+ * Releases a write lock by its lock ID.
2753
+ * @param lockId - The unique identifier for the lock to release.
2754
+ */
2755
+ writeUnlock(lockId) {
2756
+ this._free(this.writings, lockId);
2757
+ }
2758
+ };
2759
+
2760
+ // src/transaction/BPTreeAsyncTransaction.ts
2761
+ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
2762
+ lock;
2763
+ constructor(rootTx, mvccRoot, mvcc, strategy, comparator, option) {
2764
+ super(
2765
+ rootTx,
2766
+ mvccRoot,
2767
+ mvcc,
2768
+ strategy,
2769
+ comparator,
2770
+ option
2771
+ );
2772
+ this.lock = new Ryoiki2();
2773
+ }
2774
+ async writeLock(id, fn) {
2775
+ let lockId;
2776
+ return this.lock.writeLock([id, id + 0.1], async (_lockId) => {
2777
+ lockId = _lockId;
2778
+ return fn();
2779
+ }).finally(() => {
2780
+ this.lock.writeUnlock(lockId);
2781
+ });
2782
+ }
2783
+ async getNode(id) {
2784
+ return await this.mvcc.read(id);
2785
+ }
2786
+ /**
2787
+ * Create a new node with a unique ID.
2788
+ */
2789
+ async _createNode(leaf, keys, values, parent = null, next = null, prev = null) {
2790
+ const id = await this.strategy.id(leaf);
2791
+ const node = {
2792
+ id,
2793
+ keys,
2794
+ values,
2795
+ leaf,
2796
+ parent,
2797
+ next,
2798
+ prev
2799
+ };
2800
+ const head = await this._readHead();
2801
+ if (head) {
2899
2802
  await this._writeHead({
2900
- root,
2901
- order: this.order,
2803
+ root: head.root,
2804
+ order: head.order,
2902
2805
  data: this.strategy.head.data
2903
2806
  });
2904
2807
  }
2905
- if (this.order < 3) {
2906
- throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
2907
- }
2808
+ await this.mvcc.create(id, node);
2809
+ return node;
2908
2810
  }
2909
- async exists(key, value) {
2910
- const node = await this.insertableNode(value);
2911
- const { index, found } = this._binarySearchValues(node.values, value);
2912
- if (found) {
2913
- const keys = node.keys[index];
2914
- if (keys.includes(key)) {
2915
- return true;
2916
- }
2811
+ async _updateNode(node) {
2812
+ if (this.mvcc.isDeleted(node.id)) {
2813
+ return;
2917
2814
  }
2918
- return false;
2815
+ await this.mvcc.write(node.id, this._cloneNode(node));
2919
2816
  }
2920
- async forceUpdate(id) {
2921
- if (id) {
2922
- this.nodes.delete(id);
2923
- await this.getNode(id);
2924
- return 1;
2925
- }
2926
- const keys = Array.from(this.nodes.keys());
2927
- for (const key of keys) {
2928
- this.nodes.delete(key);
2817
+ async _deleteNode(node) {
2818
+ if (this.mvcc.isDeleted(node.id)) {
2819
+ return;
2929
2820
  }
2930
- for (const key of keys) {
2931
- await this.getNode(key);
2821
+ await this.mvcc.delete(node.id);
2822
+ }
2823
+ async _readHead() {
2824
+ return await this.mvcc.read("__HEAD__");
2825
+ }
2826
+ async _writeHead(head) {
2827
+ if (!await this.mvcc.exists("__HEAD__")) {
2828
+ await this.mvcc.create("__HEAD__", this._cloneNode(head));
2829
+ } else {
2830
+ await this.mvcc.write("__HEAD__", this._cloneNode(head));
2932
2831
  }
2933
- return keys.length;
2832
+ this.rootId = head.root;
2934
2833
  }
2935
- async get(key) {
2936
- let node = await this.leftestNode();
2937
- while (true) {
2938
- for (let i = 0, len = node.values.length; i < len; i++) {
2939
- const keys = node.keys[i];
2940
- for (let j = 0, kLen = keys.length; j < kLen; j++) {
2941
- if (keys[j] === key) {
2942
- return node.values[i];
2834
+ async _insertAtLeaf(node, key, value) {
2835
+ let leaf = node;
2836
+ leaf = this._cloneNode(leaf);
2837
+ if (leaf.values.length) {
2838
+ for (let i = 0, len = leaf.values.length; i < len; i++) {
2839
+ const nValue = leaf.values[i];
2840
+ if (this.comparator.isSame(value, nValue)) {
2841
+ const keys = leaf.keys[i];
2842
+ if (keys.includes(key)) {
2843
+ break;
2943
2844
  }
2845
+ keys.push(key);
2846
+ await this._updateNode(leaf);
2847
+ return leaf;
2848
+ } else if (this.comparator.isLower(value, nValue)) {
2849
+ leaf.values.splice(i, 0, value);
2850
+ leaf.keys.splice(i, 0, [key]);
2851
+ await this._updateNode(leaf);
2852
+ return leaf;
2853
+ } else if (i + 1 === leaf.values.length) {
2854
+ leaf.values.push(value);
2855
+ leaf.keys.push([key]);
2856
+ await this._updateNode(leaf);
2857
+ return leaf;
2944
2858
  }
2945
2859
  }
2946
- if (!node.next) break;
2947
- node = await this.getNode(node.next);
2860
+ } else {
2861
+ leaf.values = [value];
2862
+ leaf.keys = [[key]];
2863
+ await this._updateNode(leaf);
2864
+ return leaf;
2948
2865
  }
2949
- return void 0;
2866
+ return leaf;
2950
2867
  }
2951
- async *keysStream(condition, filterValues, limit, order = "asc") {
2952
- const stream = this.whereStream(condition, limit, order);
2953
- const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
2954
- for await (const [key] of stream) {
2955
- if (intersection && !intersection.has(key)) {
2956
- continue;
2868
+ async _insertInParent(node, value, pointer) {
2869
+ node = this._cloneNode(node);
2870
+ pointer = this._cloneNode(pointer);
2871
+ if (this.rootId === node.id) {
2872
+ const root = await this._createNode(false, [node.id, pointer.id], [value]);
2873
+ this.rootId = root.id;
2874
+ node.parent = root.id;
2875
+ pointer.parent = root.id;
2876
+ if (pointer.leaf) {
2877
+ node.next = pointer.id;
2878
+ pointer.prev = node.id;
2957
2879
  }
2958
- yield key;
2880
+ await this._writeHead({
2881
+ root: root.id,
2882
+ order: this.order,
2883
+ data: this.strategy.head.data
2884
+ });
2885
+ await this._updateNode(node);
2886
+ await this._updateNode(pointer);
2887
+ return;
2959
2888
  }
2960
- }
2961
- async *whereStream(condition, limit, order = "asc") {
2962
- const driverKey = this.getDriverKey(condition);
2963
- if (!driverKey) return;
2964
- const value = condition[driverKey];
2965
- let startNode = await this.verifierStartNode[driverKey](value);
2966
- let endNode = await this.verifierEndNode[driverKey](value);
2967
- let direction = this.verifierDirection[driverKey];
2968
- const comparator = this.verifierMap[driverKey];
2969
- const earlyTerminate = this.verifierEarlyTerminate[driverKey];
2970
- if (order === "desc") {
2971
- startNode = endNode ?? await this.rightestNode();
2972
- endNode = null;
2973
- direction *= -1;
2889
+ const parentNode = this._cloneNode(await this.getNode(node.parent));
2890
+ const nodeIndex = parentNode.keys.indexOf(node.id);
2891
+ if (nodeIndex === -1) {
2892
+ throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
2974
2893
  }
2975
- const generator = this.getPairsGenerator(
2976
- value,
2977
- startNode,
2978
- endNode,
2979
- comparator,
2894
+ parentNode.values.splice(nodeIndex, 0, value);
2895
+ parentNode.keys.splice(nodeIndex + 1, 0, pointer.id);
2896
+ pointer.parent = parentNode.id;
2897
+ if (pointer.leaf) {
2898
+ const leftSibling = node;
2899
+ const oldNextId = leftSibling.next;
2900
+ pointer.prev = leftSibling.id;
2901
+ pointer.next = oldNextId;
2902
+ leftSibling.next = pointer.id;
2903
+ await this._updateNode(leftSibling);
2904
+ if (oldNextId) {
2905
+ const oldNext = this._cloneNode(await this.getNode(oldNextId));
2906
+ oldNext.prev = pointer.id;
2907
+ await this._updateNode(oldNext);
2908
+ }
2909
+ }
2910
+ await this._updateNode(parentNode);
2911
+ await this._updateNode(pointer);
2912
+ if (parentNode.keys.length > this.order) {
2913
+ const parentPointer = await this._createNode(false, [], []);
2914
+ parentPointer.parent = parentNode.parent;
2915
+ const mid = Math.ceil(this.order / 2) - 1;
2916
+ parentPointer.values = parentNode.values.slice(mid + 1);
2917
+ parentPointer.keys = parentNode.keys.slice(mid + 1);
2918
+ const midValue = parentNode.values[mid];
2919
+ parentNode.values = parentNode.values.slice(0, mid);
2920
+ parentNode.keys = parentNode.keys.slice(0, mid + 1);
2921
+ for (const k of parentNode.keys) {
2922
+ const n = this._cloneNode(await this.getNode(k));
2923
+ n.parent = parentNode.id;
2924
+ await this._updateNode(n);
2925
+ }
2926
+ for (const k of parentPointer.keys) {
2927
+ const n = this._cloneNode(await this.getNode(k));
2928
+ n.parent = parentPointer.id;
2929
+ await this._updateNode(n);
2930
+ }
2931
+ await this._updateNode(parentNode);
2932
+ await this._insertInParent(parentNode, midValue, parentPointer);
2933
+ }
2934
+ }
2935
+ async insertableNode(value) {
2936
+ let node = await this.getNode(this.rootId);
2937
+ while (!node.leaf) {
2938
+ const { index } = this._binarySearchValues(node.values, value, false, true);
2939
+ node = await this.getNode(node.keys[index]);
2940
+ }
2941
+ return node;
2942
+ }
2943
+ async insertableNodeByPrimary(value) {
2944
+ let node = await this.getNode(this.rootId);
2945
+ while (!node.leaf) {
2946
+ const { index } = this._binarySearchValues(node.values, value, true, false);
2947
+ node = await this.getNode(node.keys[index]);
2948
+ }
2949
+ return node;
2950
+ }
2951
+ async insertableRightestNodeByPrimary(value) {
2952
+ let node = await this.getNode(this.rootId);
2953
+ while (!node.leaf) {
2954
+ const { index } = this._binarySearchValues(node.values, value, true, true);
2955
+ node = await this.getNode(node.keys[index]);
2956
+ }
2957
+ return node;
2958
+ }
2959
+ async insertableRightestEndNodeByPrimary(value) {
2960
+ const node = await this.insertableRightestNodeByPrimary(value);
2961
+ if (!node.next) {
2962
+ return null;
2963
+ }
2964
+ return await this.getNode(node.next);
2965
+ }
2966
+ async insertableEndNode(value, direction) {
2967
+ const insertableNode = await this.insertableNode(value);
2968
+ let key;
2969
+ switch (direction) {
2970
+ case -1:
2971
+ key = "prev";
2972
+ break;
2973
+ case 1:
2974
+ key = "next";
2975
+ break;
2976
+ default:
2977
+ throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
2978
+ }
2979
+ const guessNode = insertableNode[key];
2980
+ if (!guessNode) {
2981
+ return null;
2982
+ }
2983
+ return await this.getNode(guessNode);
2984
+ }
2985
+ async leftestNode() {
2986
+ let node = await this.getNode(this.rootId);
2987
+ if (node === null) {
2988
+ debugger;
2989
+ }
2990
+ while (!node.leaf) {
2991
+ const keys = node.keys;
2992
+ node = await this.getNode(keys[0]);
2993
+ }
2994
+ return node;
2995
+ }
2996
+ async rightestNode() {
2997
+ let node = await this.getNode(this.rootId);
2998
+ while (!node.leaf) {
2999
+ const keys = node.keys;
3000
+ node = await this.getNode(keys[keys.length - 1]);
3001
+ }
3002
+ return node;
3003
+ }
3004
+ async *getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
3005
+ let node = startNode;
3006
+ let done = false;
3007
+ let hasMatched = false;
3008
+ let nextNodePromise = null;
3009
+ while (!done) {
3010
+ if (endNode && node.id === endNode.id) {
3011
+ done = true;
3012
+ break;
3013
+ }
3014
+ if (direction === 1) {
3015
+ if (node.next && !done) {
3016
+ nextNodePromise = this.getNode(node.next);
3017
+ }
3018
+ } else {
3019
+ if (node.prev && !done) {
3020
+ nextNodePromise = this.getNode(node.prev);
3021
+ }
3022
+ }
3023
+ const len = node.values.length;
3024
+ if (direction === 1) {
3025
+ for (let i = 0; i < len; i++) {
3026
+ const nValue = node.values[i];
3027
+ const keys = node.keys[i];
3028
+ if (comparator(nValue, value)) {
3029
+ hasMatched = true;
3030
+ for (let j = 0; j < keys.length; j++) {
3031
+ yield [keys[j], nValue];
3032
+ }
3033
+ } else if (earlyTerminate && hasMatched) {
3034
+ done = true;
3035
+ break;
3036
+ }
3037
+ }
3038
+ } else {
3039
+ let i = len;
3040
+ while (i--) {
3041
+ const nValue = node.values[i];
3042
+ const keys = node.keys[i];
3043
+ if (comparator(nValue, value)) {
3044
+ hasMatched = true;
3045
+ let j = keys.length;
3046
+ while (j--) {
3047
+ yield [keys[j], nValue];
3048
+ }
3049
+ } else if (earlyTerminate && hasMatched) {
3050
+ done = true;
3051
+ break;
3052
+ }
3053
+ }
3054
+ }
3055
+ if (done) {
3056
+ if (nextNodePromise) await nextNodePromise;
3057
+ break;
3058
+ }
3059
+ if (nextNodePromise) {
3060
+ node = await nextNodePromise;
3061
+ nextNodePromise = null;
3062
+ } else {
3063
+ done = true;
3064
+ }
3065
+ }
3066
+ }
3067
+ async init() {
3068
+ if (this.rootTx !== this) {
3069
+ throw new Error("Cannot call init on a nested transaction");
3070
+ }
3071
+ return await this._initInternal();
3072
+ }
3073
+ async _initInternal() {
3074
+ if (this.isInitialized) {
3075
+ throw new Error("Transaction already initialized");
3076
+ }
3077
+ if (this.isDestroyed) {
3078
+ throw new Error("Transaction already destroyed");
3079
+ }
3080
+ this.isInitialized = true;
3081
+ try {
3082
+ this._clearCache();
3083
+ const head = await this._readHead();
3084
+ if (head === null) {
3085
+ this.order = this.strategy.order;
3086
+ const root = await this._createNode(true, [], []);
3087
+ await this._writeHead({
3088
+ root: root.id,
3089
+ order: this.order,
3090
+ data: this.strategy.head.data
3091
+ });
3092
+ } else {
3093
+ const { root, order } = head;
3094
+ this.strategy.head = head;
3095
+ this.order = order;
3096
+ await this._writeHead({
3097
+ root,
3098
+ order: this.order,
3099
+ data: this.strategy.head.data
3100
+ });
3101
+ }
3102
+ if (this.order < 3) {
3103
+ throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
3104
+ }
3105
+ } catch (e) {
3106
+ this.isInitialized = false;
3107
+ throw e;
3108
+ }
3109
+ }
3110
+ async exists(key, value) {
3111
+ const node = await this.insertableNode(value);
3112
+ const { index, found } = this._binarySearchValues(node.values, value);
3113
+ if (found) {
3114
+ const keys = node.keys[index];
3115
+ if (keys.includes(key)) {
3116
+ return true;
3117
+ }
3118
+ }
3119
+ return false;
3120
+ }
3121
+ async get(key) {
3122
+ let node = await this.leftestNode();
3123
+ while (true) {
3124
+ for (let i = 0, len = node.values.length; i < len; i++) {
3125
+ const keys = node.keys[i];
3126
+ for (let j = 0, kLen = keys.length; j < kLen; j++) {
3127
+ if (keys[j] === key) {
3128
+ return node.values[i];
3129
+ }
3130
+ }
3131
+ }
3132
+ if (!node.next) break;
3133
+ node = await this.getNode(node.next);
3134
+ }
3135
+ return void 0;
3136
+ }
3137
+ async *keysStream(condition, filterValues, limit, order = "asc") {
3138
+ const stream = this.whereStream(condition, limit, order);
3139
+ const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
3140
+ for await (const [key] of stream) {
3141
+ if (intersection && !intersection.has(key)) {
3142
+ continue;
3143
+ }
3144
+ yield key;
3145
+ }
3146
+ }
3147
+ async *whereStream(condition, limit, order = "asc") {
3148
+ const driverKey = this.getDriverKey(condition);
3149
+ if (!driverKey) return;
3150
+ const value = condition[driverKey];
3151
+ let startNode = await this.verifierStartNode[driverKey](value);
3152
+ let endNode = await this.verifierEndNode[driverKey](value);
3153
+ let direction = this.verifierDirection[driverKey];
3154
+ const comparator = this.verifierMap[driverKey];
3155
+ const earlyTerminate = this.verifierEarlyTerminate[driverKey];
3156
+ if (order === "desc") {
3157
+ startNode = endNode ?? await this.rightestNode();
3158
+ endNode = null;
3159
+ direction *= -1;
3160
+ }
3161
+ const generator = this.getPairsGenerator(
3162
+ value,
3163
+ startNode,
3164
+ endNode,
3165
+ comparator,
2980
3166
  direction,
2981
3167
  earlyTerminate
2982
3168
  );
@@ -3017,26 +3203,32 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3017
3203
  return map;
3018
3204
  }
3019
3205
  async insert(key, value) {
3020
- const before = await this.insertableNode(value);
3021
- await this._insertAtLeaf(before, key, value);
3022
- if (before.values.length === this.order) {
3023
- const after = await this._createNode(
3024
- true,
3025
- [],
3026
- [],
3027
- before.parent,
3028
- null,
3029
- null
3030
- );
3031
- const mid = Math.ceil(this.order / 2) - 1;
3032
- after.values = before.values.slice(mid + 1);
3033
- after.keys = before.keys.slice(mid + 1);
3034
- before.values = before.values.slice(0, mid + 1);
3035
- before.keys = before.keys.slice(0, mid + 1);
3036
- await this._insertInParent(before, after.values[0], after);
3037
- }
3206
+ return this.writeLock(0, async () => {
3207
+ let before = await this.insertableNode(value);
3208
+ before = await this._insertAtLeaf(before, key, value);
3209
+ if (before.values.length === this.order) {
3210
+ let after = await this._createNode(
3211
+ true,
3212
+ [],
3213
+ [],
3214
+ before.parent,
3215
+ null,
3216
+ null
3217
+ );
3218
+ const mid = Math.ceil(this.order / 2) - 1;
3219
+ after = this._cloneNode(after);
3220
+ after.values = before.values.slice(mid + 1);
3221
+ after.keys = before.keys.slice(mid + 1);
3222
+ before.values = before.values.slice(0, mid + 1);
3223
+ before.keys = before.keys.slice(0, mid + 1);
3224
+ await this._updateNode(before);
3225
+ await this._updateNode(after);
3226
+ await this._insertInParent(before, after.values[0], after);
3227
+ }
3228
+ });
3038
3229
  }
3039
3230
  async _deleteEntry(node, key) {
3231
+ node = this._cloneNode(node);
3040
3232
  if (!node.leaf) {
3041
3233
  let keyIndex = -1;
3042
3234
  for (let i = 0, len = node.keys.length; i < len; i++) {
@@ -3055,7 +3247,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3055
3247
  if (this.rootId === node.id && node.keys.length === 1 && !node.leaf) {
3056
3248
  const keys = node.keys;
3057
3249
  this._deleteNode(node);
3058
- const newRoot = await this.getNode(keys[0]);
3250
+ const newRoot = this._cloneNode(await this.getNode(keys[0]));
3059
3251
  newRoot.parent = null;
3060
3252
  await this._updateNode(newRoot);
3061
3253
  await this._writeHead({
@@ -3063,14 +3255,17 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3063
3255
  order: this.order,
3064
3256
  data: this.strategy.head.data
3065
3257
  });
3066
- return;
3258
+ return node;
3067
3259
  } else if (this.rootId === node.id) {
3068
- const root = await this.getNode(this.rootId);
3069
- await this._updateNode(root);
3070
- return;
3260
+ await this._writeHead({
3261
+ root: node.id,
3262
+ order: this.order,
3263
+ data: this.strategy.head.data
3264
+ });
3265
+ return node;
3071
3266
  } else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
3072
3267
  if (node.parent === null) {
3073
- return;
3268
+ return node;
3074
3269
  }
3075
3270
  let isPredecessor = false;
3076
3271
  let parentNode = await this.getNode(node.parent);
@@ -3082,11 +3277,11 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3082
3277
  const nKey = parentNode.keys[i];
3083
3278
  if (nKey === node.id) {
3084
3279
  if (i > 0) {
3085
- prevNode = await this.getNode(parentNode.keys[i - 1]);
3280
+ prevNode = this._cloneNode(await this.getNode(parentNode.keys[i - 1]));
3086
3281
  prevValue = parentNode.values[i - 1];
3087
3282
  }
3088
3283
  if (i < parentNode.keys.length - 1) {
3089
- nextNode = await this.getNode(parentNode.keys[i + 1]);
3284
+ nextNode = this._cloneNode(await this.getNode(parentNode.keys[i + 1]));
3090
3285
  postValue = parentNode.values[i];
3091
3286
  }
3092
3287
  }
@@ -3111,7 +3306,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3111
3306
  }
3112
3307
  }
3113
3308
  if (!pointer) {
3114
- return;
3309
+ return node;
3115
3310
  }
3116
3311
  if (node.values.length + pointer.values.length < this.order) {
3117
3312
  if (!isPredecessor) {
@@ -3125,7 +3320,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3125
3320
  } else {
3126
3321
  pointer.next = node.next;
3127
3322
  if (pointer.next) {
3128
- const n = await this.getNode(pointer.next);
3323
+ const n = this._cloneNode(await this.getNode(pointer.next));
3129
3324
  n.prev = pointer.id;
3130
3325
  await this._updateNode(n);
3131
3326
  }
@@ -3134,14 +3329,14 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3134
3329
  if (!pointer.leaf) {
3135
3330
  const keys = pointer.keys;
3136
3331
  for (const key2 of keys) {
3137
- const node2 = await this.getNode(key2);
3332
+ const node2 = this._cloneNode(await this.getNode(key2));
3138
3333
  node2.parent = pointer.id;
3139
3334
  await this._updateNode(node2);
3140
3335
  }
3141
3336
  }
3142
3337
  this._deleteNode(node);
3143
3338
  await this._updateNode(pointer);
3144
- await this._deleteEntry(await this.getNode(node.parent), node.id);
3339
+ await this._deleteEntry(this._cloneNode(await this.getNode(node.parent)), node.id);
3145
3340
  } else {
3146
3341
  if (isPredecessor) {
3147
3342
  let pointerPm;
@@ -3151,7 +3346,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3151
3346
  pointerKm = pointer.values.splice(-1)[0];
3152
3347
  node.keys = [pointerPm, ...node.keys];
3153
3348
  node.values = [guess, ...node.values];
3154
- parentNode = await this.getNode(node.parent);
3349
+ parentNode = this._cloneNode(await this.getNode(node.parent));
3155
3350
  const nodeIndex = parentNode.keys.indexOf(node.id);
3156
3351
  if (nodeIndex > 0) {
3157
3352
  parentNode.values[nodeIndex - 1] = pointerKm;
@@ -3162,7 +3357,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3162
3357
  pointerKm = pointer.values.splice(-1)[0];
3163
3358
  node.keys = [pointerPm, ...node.keys];
3164
3359
  node.values = [pointerKm, ...node.values];
3165
- parentNode = await this.getNode(node.parent);
3360
+ parentNode = this._cloneNode(await this.getNode(node.parent));
3166
3361
  const nodeIndex = parentNode.keys.indexOf(node.id);
3167
3362
  if (nodeIndex > 0) {
3168
3363
  parentNode.values[nodeIndex - 1] = pointerKm;
@@ -3179,7 +3374,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3179
3374
  pointerK0 = pointer.values.splice(0, 1)[0];
3180
3375
  node.keys = [...node.keys, pointerP0];
3181
3376
  node.values = [...node.values, guess];
3182
- parentNode = await this.getNode(node.parent);
3377
+ parentNode = this._cloneNode(await this.getNode(node.parent));
3183
3378
  const pointerIndex = parentNode.keys.indexOf(pointer.id);
3184
3379
  if (pointerIndex > 0) {
3185
3380
  parentNode.values[pointerIndex - 1] = pointerK0;
@@ -3190,7 +3385,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3190
3385
  pointerK0 = pointer.values.splice(0, 1)[0];
3191
3386
  node.keys = [...node.keys, pointerP0];
3192
3387
  node.values = [...node.values, pointerK0];
3193
- parentNode = await this.getNode(node.parent);
3388
+ parentNode = this._cloneNode(await this.getNode(node.parent));
3194
3389
  const pointerIndex = parentNode.keys.indexOf(pointer.id);
3195
3390
  if (pointerIndex > 0) {
3196
3391
  parentNode.values[pointerIndex - 1] = pointer.values[0];
@@ -3202,21 +3397,21 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3202
3397
  }
3203
3398
  if (!pointer.leaf) {
3204
3399
  for (const key2 of pointer.keys) {
3205
- const n = await this.getNode(key2);
3400
+ const n = this._cloneNode(await this.getNode(key2));
3206
3401
  n.parent = pointer.id;
3207
3402
  await this._updateNode(n);
3208
3403
  }
3209
3404
  }
3210
3405
  if (!node.leaf) {
3211
3406
  for (const key2 of node.keys) {
3212
- const n = await this.getNode(key2);
3407
+ const n = this._cloneNode(await this.getNode(key2));
3213
3408
  n.parent = node.id;
3214
3409
  await this._updateNode(n);
3215
3410
  }
3216
3411
  }
3217
3412
  if (!parentNode.leaf) {
3218
3413
  for (const key2 of parentNode.keys) {
3219
- const n = await this.getNode(key2);
3414
+ const n = this._cloneNode(await this.getNode(key2));
3220
3415
  n.parent = parentNode.id;
3221
3416
  await this._updateNode(n);
3222
3417
  }
@@ -3225,37 +3420,42 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3225
3420
  } else {
3226
3421
  await this._updateNode(node);
3227
3422
  }
3423
+ await this._updateNode(node);
3424
+ return node;
3228
3425
  }
3229
3426
  async delete(key, value) {
3230
- let node = await this.insertableNodeByPrimary(value);
3231
- let found = false;
3232
- while (true) {
3233
- let i = node.values.length;
3234
- while (i--) {
3235
- const nValue = node.values[i];
3236
- if (this.comparator.isSame(value, nValue)) {
3237
- const keys = node.keys[i];
3238
- const keyIndex = keys.indexOf(key);
3239
- if (keyIndex !== -1) {
3240
- keys.splice(keyIndex, 1);
3241
- if (keys.length === 0) {
3242
- node.keys.splice(i, 1);
3243
- node.values.splice(i, 1);
3427
+ return this.writeLock(0, async () => {
3428
+ let node = await this.insertableNodeByPrimary(value);
3429
+ let found = false;
3430
+ node = this._cloneNode(node);
3431
+ while (true) {
3432
+ let i = node.values.length;
3433
+ while (i--) {
3434
+ const nValue = node.values[i];
3435
+ if (this.comparator.isSame(value, nValue)) {
3436
+ const keys = node.keys[i];
3437
+ const keyIndex = keys.indexOf(key);
3438
+ if (keyIndex !== -1) {
3439
+ keys.splice(keyIndex, 1);
3440
+ if (keys.length === 0) {
3441
+ node.keys.splice(i, 1);
3442
+ node.values.splice(i, 1);
3443
+ }
3444
+ await this._updateNode(node);
3445
+ node = await this._deleteEntry(node, key);
3446
+ found = true;
3447
+ break;
3244
3448
  }
3245
- await this._updateNode(node);
3246
- await this._deleteEntry(node, key);
3247
- found = true;
3248
- break;
3249
3449
  }
3250
3450
  }
3451
+ if (found) break;
3452
+ if (node.next) {
3453
+ node = await this.getNode(node.next);
3454
+ continue;
3455
+ }
3456
+ break;
3251
3457
  }
3252
- if (found) break;
3253
- if (node.next) {
3254
- node = await this.getNode(node.next);
3255
- continue;
3256
- }
3257
- break;
3258
- }
3458
+ });
3259
3459
  }
3260
3460
  async getHeadData() {
3261
3461
  const head = await this._readHead();
@@ -3266,447 +3466,185 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3266
3466
  }
3267
3467
  async setHeadData(data) {
3268
3468
  const head = await this._readHead();
3269
- if (head === null) {
3270
- throw new Error("Head not found");
3271
- }
3272
- await this._writeHead({
3273
- root: head.root,
3274
- order: head.order,
3275
- data
3276
- });
3277
- }
3278
- async commit(label) {
3279
- let result = await this.mvcc.commit(label);
3280
- if (result.success) {
3281
- result = await this.mvccRoot.commit(label);
3282
- if (result.success && this.rootTx !== this) {
3283
- this.rootTx.rootId = this.rootId;
3284
- }
3285
- if (result.success) {
3286
- for (const r of result.created) {
3287
- this.nodes.set(r.key, r.data);
3288
- }
3289
- for (const r of result.updated) {
3290
- this.nodes.set(r.key, r.data);
3291
- }
3292
- for (const r of result.deleted) {
3293
- this.nodes.delete(r.key);
3294
- }
3295
- }
3296
- }
3297
- return result;
3298
- }
3299
- rollback() {
3300
- return this.mvcc.rollback();
3301
- }
3302
- };
3303
-
3304
- // src/transaction/BPTreeMVCCStrategyAsync.ts
3305
- var BPTreeMVCCStrategyAsync = class extends AsyncMVCCStrategy {
3306
- constructor(strategy) {
3307
- super();
3308
- this.strategy = strategy;
3309
- }
3310
- async read(key) {
3311
- if (key === "__HEAD__") {
3312
- return await this.strategy.readHead();
3313
- }
3314
- return await this.strategy.read(key);
3315
- }
3316
- async write(key, value) {
3317
- if (key === "__HEAD__") {
3318
- await this.strategy.writeHead(value);
3319
- } else {
3320
- await this.strategy.write(key, value);
3321
- }
3322
- }
3323
- async delete(key) {
3324
- await this.strategy.delete(key);
3325
- }
3326
- async exists(key) {
3327
- if (key === "__HEAD__") {
3328
- return await this.strategy.readHead() !== null;
3329
- }
3330
- try {
3331
- const node = await this.strategy.read(key);
3332
- return node !== null && node !== void 0;
3333
- } catch {
3334
- return false;
3335
- }
3336
- }
3337
- };
3338
-
3339
- // src/BPTreeAsync.ts
3340
- var BPTreeAsync = class extends BPTreeAsyncTransaction {
3341
- constructor(strategy, comparator, option) {
3342
- const mvccRoot = new AsyncMVCCTransaction(new BPTreeMVCCStrategyAsync(strategy));
3343
- super(
3344
- null,
3345
- mvccRoot,
3346
- mvccRoot,
3347
- strategy,
3348
- comparator,
3349
- option
3350
- );
3351
- }
3352
- /**
3353
- * Creates a new asynchronous transaction.
3354
- * @returns A new BPTreeAsyncTransaction.
3355
- */
3356
- async createTransaction() {
3357
- const nestedTx = await this.mvcc.createNested();
3358
- const tx = new BPTreeAsyncTransaction(
3359
- this,
3360
- this.mvcc,
3361
- nestedTx,
3362
- this.strategy,
3363
- this.comparator,
3364
- this.option
3365
- );
3366
- await tx.init();
3367
- return tx;
3368
- }
3369
- async insert(key, value) {
3370
- const tx = await this.createTransaction();
3371
- await tx.insert(key, value);
3372
- const result = await tx.commit();
3373
- if (!result.success) {
3374
- throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
3375
- }
3376
- this.rootId = tx.getRootId();
3377
- }
3378
- async delete(key, value) {
3379
- const tx = await this.createTransaction();
3380
- await tx.delete(key, value);
3381
- const result = await tx.commit();
3382
- if (!result.success) {
3383
- throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
3384
- }
3385
- this.rootId = tx.getRootId();
3386
- }
3387
- };
3388
-
3389
- // src/base/SerializeStrategy.ts
3390
- var SerializeStrategy = class {
3391
- order;
3392
- head;
3393
- constructor(order) {
3394
- this.order = order;
3395
- this.head = {
3396
- order,
3397
- root: null,
3398
- data: {}
3399
- };
3400
- }
3401
- };
3402
-
3403
- // src/SerializeStrategySync.ts
3404
- var SerializeStrategySync = class extends SerializeStrategy {
3405
- getHeadData(key, defaultValue) {
3406
- if (!Object.hasOwn(this.head.data, key)) {
3407
- this.setHeadData(key, defaultValue);
3408
- }
3409
- return this.head.data[key];
3410
- }
3411
- setHeadData(key, data) {
3412
- this.head.data[key] = data;
3413
- this.writeHead(this.head);
3414
- }
3415
- autoIncrement(key, defaultValue) {
3416
- const current = this.getHeadData(key, defaultValue);
3417
- const next = current + 1;
3418
- this.setHeadData(key, next);
3419
- return current;
3420
- }
3421
- };
3422
- var InMemoryStoreStrategySync = class extends SerializeStrategySync {
3423
- node;
3424
- constructor(order) {
3425
- super(order);
3426
- this.node = {};
3427
- }
3428
- id(isLeaf) {
3429
- return this.autoIncrement("index", 1).toString();
3430
- }
3431
- read(id) {
3432
- if (!Object.hasOwn(this.node, id)) {
3433
- throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
3434
- }
3435
- const node = this.node[id];
3436
- return JSON.parse(JSON.stringify(node));
3437
- }
3438
- write(id, node) {
3439
- this.node[id] = node;
3440
- }
3441
- delete(id) {
3442
- delete this.node[id];
3443
- }
3444
- readHead() {
3445
- if (this.head.root === null) {
3446
- return null;
3447
- }
3448
- return this.head;
3449
- }
3450
- writeHead(head) {
3451
- this.head = head;
3452
- }
3453
- };
3454
-
3455
- // node_modules/ryoiki/dist/esm/index.mjs
3456
- var Ryoiki2 = class _Ryoiki2 {
3457
- readings;
3458
- writings;
3459
- readQueue;
3460
- writeQueue;
3461
- static async CatchError(promise) {
3462
- return await promise.then((v) => [void 0, v]).catch((err) => [err]);
3463
- }
3464
- static IsRangeOverlap(a, b) {
3465
- const [start1, end1] = a;
3466
- const [start2, end2] = b;
3467
- if (end1 <= start2 || end2 <= start1) {
3468
- return false;
3469
- }
3470
- return true;
3471
- }
3472
- static ERR_ALREADY_EXISTS(lockId) {
3473
- return new Error(`The '${lockId}' task already existing in queue or running.`);
3474
- }
3475
- static ERR_NOT_EXISTS(lockId) {
3476
- return new Error(`The '${lockId}' task not existing in task queue.`);
3477
- }
3478
- static ERR_TIMEOUT(lockId, timeout) {
3479
- return new Error(`The task with ID '${lockId}' failed to acquire the lock within the timeout(${timeout}ms).`);
3480
- }
3481
- /**
3482
- * Constructs a new instance of the Ryoiki class.
3483
- */
3484
- constructor() {
3485
- this.readings = /* @__PURE__ */ new Map();
3486
- this.writings = /* @__PURE__ */ new Map();
3487
- this.readQueue = /* @__PURE__ */ new Map();
3488
- this.writeQueue = /* @__PURE__ */ new Map();
3489
- }
3490
- /**
3491
- * Creates a range based on a start value and length.
3492
- * @param start - The starting value of the range.
3493
- * @param length - The length of the range.
3494
- * @returns A range tuple [start, start + length].
3495
- */
3496
- range(start, length) {
3497
- return [start, start + length];
3498
- }
3499
- rangeOverlapping(tasks, range) {
3500
- return Array.from(tasks.values()).some((t) => _Ryoiki2.IsRangeOverlap(t.range, range));
3501
- }
3502
- isSameRange(a, b) {
3503
- const [a1, a2] = a;
3504
- const [b1, b2] = b;
3505
- return a1 === b1 && a2 === b2;
3506
- }
3507
- fetchUnitAndRun(queue, workspaces) {
3508
- for (const [id, unit] of queue) {
3509
- if (!unit.condition()) {
3510
- continue;
3511
- }
3512
- this._alloc(queue, workspaces, id);
3513
- }
3514
- }
3515
- _handleOverload(args, handlers, argPatterns) {
3516
- for (const [key, pattern] of Object.entries(argPatterns)) {
3517
- if (this._matchArgs(args, pattern)) {
3518
- return handlers[key](...args);
3519
- }
3520
- }
3521
- throw new Error("Invalid arguments");
3522
- }
3523
- _matchArgs(args, pattern) {
3524
- return args.every((arg, index) => {
3525
- const expectedType = pattern[index];
3526
- if (expectedType === void 0) return typeof arg === "undefined";
3527
- if (expectedType === Function) return typeof arg === "function";
3528
- if (expectedType === Number) return typeof arg === "number";
3529
- if (expectedType === Array) return Array.isArray(arg);
3530
- return false;
3531
- });
3532
- }
3533
- _createRandomId() {
3534
- const timestamp = Date.now().toString(36);
3535
- const random = Math.random().toString(36).substring(2);
3536
- return `${timestamp}${random}`;
3537
- }
3538
- _alloc(queue, workspaces, lockId) {
3539
- const unit = queue.get(lockId);
3540
- if (!unit) {
3541
- throw _Ryoiki2.ERR_NOT_EXISTS(lockId);
3542
- }
3543
- workspaces.set(lockId, unit);
3544
- queue.delete(lockId);
3545
- unit.alloc();
3546
- }
3547
- _free(workspaces, lockId) {
3548
- const unit = workspaces.get(lockId);
3549
- if (!unit) {
3550
- throw _Ryoiki2.ERR_NOT_EXISTS(lockId);
3551
- }
3552
- workspaces.delete(lockId);
3553
- unit.free();
3554
- }
3555
- _lock(queue, range, timeout, task, condition) {
3556
- return new Promise((resolve, reject) => {
3557
- let timeoutId = null;
3558
- if (timeout >= 0) {
3559
- timeoutId = setTimeout(() => {
3560
- reject(_Ryoiki2.ERR_TIMEOUT(id, timeout));
3561
- }, timeout);
3562
- }
3563
- const id = this._createRandomId();
3564
- const alloc = async () => {
3565
- if (timeoutId !== null) {
3566
- clearTimeout(timeoutId);
3567
- }
3568
- const [err, v] = await _Ryoiki2.CatchError(task(id));
3569
- if (err) reject(err);
3570
- else resolve(v);
3571
- };
3572
- const fetch = () => {
3573
- this.fetchUnitAndRun(this.readQueue, this.readings);
3574
- this.fetchUnitAndRun(this.writeQueue, this.writings);
3575
- };
3576
- queue.set(id, { id, range, condition, alloc, free: fetch });
3577
- fetch();
3469
+ if (head === null) {
3470
+ throw new Error("Head not found");
3471
+ }
3472
+ await this._writeHead({
3473
+ root: head.root,
3474
+ order: head.order,
3475
+ data
3578
3476
  });
3579
3477
  }
3580
- _checkWorking(range, workspaces) {
3581
- let isLocked = false;
3582
- for (const lock of workspaces.values()) {
3583
- if (_Ryoiki2.IsRangeOverlap(range, lock.range)) {
3584
- isLocked = true;
3585
- break;
3478
+ async commit(label) {
3479
+ let result = await this.mvcc.commit(label);
3480
+ if (result.success) {
3481
+ const isRootTx = this.rootTx === this;
3482
+ if (!isRootTx) {
3483
+ result = await this.rootTx.commit(label);
3484
+ if (result.success) {
3485
+ this.rootTx.rootId = this.rootId;
3486
+ }
3586
3487
  }
3587
3488
  }
3588
- return isLocked;
3489
+ return result;
3589
3490
  }
3590
- /**
3591
- * Checks if there is any active read lock within the specified range.
3592
- * @param range The range to check for active read locks.
3593
- * @returns `true` if there is an active read lock within the range, `false` otherwise.
3594
- */
3595
- isReading(range) {
3596
- return this._checkWorking(range, this.readings);
3491
+ async rollback() {
3492
+ return this.mvcc.rollback();
3597
3493
  }
3598
- /**
3599
- * Checks if there is any active write lock within the specified range.
3600
- * @param range The range to check for active write locks.
3601
- * @returns `true` if there is an active write lock within the range, `false` otherwise.
3602
- */
3603
- isWriting(range) {
3604
- return this._checkWorking(range, this.writings);
3494
+ };
3495
+
3496
+ // src/transaction/BPTreeMVCCStrategyAsync.ts
3497
+ var BPTreeMVCCStrategyAsync = class extends AsyncMVCCStrategy {
3498
+ constructor(strategy) {
3499
+ super();
3500
+ this.strategy = strategy;
3605
3501
  }
3606
- /**
3607
- * Checks if a read lock can be acquired within the specified range.
3608
- * @param range The range to check for read lock availability.
3609
- * @returns `true` if a read lock can be acquired, `false` otherwise.
3610
- */
3611
- canRead(range) {
3612
- const writing = this.isWriting(range);
3613
- return !writing;
3502
+ async read(key) {
3503
+ if (key === "__HEAD__") {
3504
+ return await this.strategy.readHead();
3505
+ }
3506
+ return await this.strategy.read(key);
3614
3507
  }
3615
- /**
3616
- * Checks if a write lock can be acquired within the specified range.
3617
- * @param range The range to check for write lock availability.
3618
- * @returns `true` if a write lock can be acquired, `false` otherwise.
3619
- */
3620
- canWrite(range) {
3621
- const reading = this.isReading(range);
3622
- const writing = this.isWriting(range);
3623
- return !reading && !writing;
3508
+ async write(key, value) {
3509
+ if (key === "__HEAD__") {
3510
+ await this.strategy.writeHead(value);
3511
+ } else {
3512
+ await this.strategy.write(key, value);
3513
+ }
3624
3514
  }
3625
- /**
3626
- * Internal implementation of the read lock. Handles both overloads.
3627
- * @template T - The return type of the task.
3628
- * @param arg0 - Either a range or a task callback.
3629
- * If a range is provided, the task is the second argument.
3630
- * @param arg1 - The task to execute, required if a range is provided.
3631
- * @param arg2 - The timeout for acquiring the lock.
3632
- * If the lock cannot be acquired within this period, an error will be thrown.
3633
- * If this value is not provided, no timeout will be set.
3634
- * @returns A promise resolving to the result of the task execution.
3635
- */
3636
- readLock(arg0, arg1, arg2) {
3637
- const [range, task, timeout] = this._handleOverload(
3638
- [arg0, arg1, arg2],
3639
- {
3640
- rangeTask: (range2, task2) => [range2, task2, -1],
3641
- rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
3642
- task: (task2) => [[-Infinity, Infinity], task2, -1],
3643
- taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
3644
- },
3645
- {
3646
- task: [Function],
3647
- taskTimeout: [Function, Number],
3648
- rangeTask: [Array, Function],
3649
- rangeTaskTimeout: [Array, Function, Number]
3650
- }
3651
- );
3652
- return this._lock(
3653
- this.readQueue,
3654
- range,
3655
- timeout,
3656
- task,
3657
- () => !this.rangeOverlapping(this.writings, range)
3515
+ async delete(key) {
3516
+ await this.strategy.delete(key);
3517
+ }
3518
+ async exists(key) {
3519
+ if (key === "__HEAD__") {
3520
+ return await this.strategy.readHead() !== null;
3521
+ }
3522
+ try {
3523
+ const node = await this.strategy.read(key);
3524
+ return node !== null && node !== void 0;
3525
+ } catch {
3526
+ return false;
3527
+ }
3528
+ }
3529
+ };
3530
+
3531
+ // src/BPTreeAsync.ts
3532
+ var BPTreeAsync = class extends BPTreeAsyncTransaction {
3533
+ constructor(strategy, comparator, option) {
3534
+ const mvccRoot = new AsyncMVCCTransaction(new BPTreeMVCCStrategyAsync(strategy), {
3535
+ cacheCapacity: option?.capacity ?? void 0
3536
+ });
3537
+ super(
3538
+ null,
3539
+ mvccRoot,
3540
+ mvccRoot,
3541
+ strategy,
3542
+ comparator,
3543
+ option
3658
3544
  );
3659
3545
  }
3660
3546
  /**
3661
- * Internal implementation of the write lock. Handles both overloads.
3662
- * @template T - The return type of the task.
3663
- * @param arg0 - Either a range or a task callback.
3664
- * If a range is provided, the task is the second argument.
3665
- * @param arg1 - The task to execute, required if a range is provided.
3666
- * @param arg2 - The timeout for acquiring the lock.
3667
- * If the lock cannot be acquired within this period, an error will be thrown.
3668
- * If this value is not provided, no timeout will be set.
3669
- * @returns A promise resolving to the result of the task execution.
3547
+ * Creates a new asynchronous transaction.
3548
+ * @returns A new BPTreeAsyncTransaction.
3670
3549
  */
3671
- writeLock(arg0, arg1, arg2) {
3672
- const [range, task, timeout] = this._handleOverload(
3673
- [arg0, arg1, arg2],
3674
- {
3675
- rangeTask: (range2, task2) => [range2, task2, -1],
3676
- rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
3677
- task: (task2) => [[-Infinity, Infinity], task2, -1],
3678
- taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
3679
- },
3680
- {
3681
- task: [Function],
3682
- taskTimeout: [Function, Number],
3683
- rangeTask: [Array, Function],
3684
- rangeTaskTimeout: [Array, Function, Number]
3685
- }
3550
+ async createTransaction() {
3551
+ const nestedTx = this.mvcc.createNested();
3552
+ const tx = new BPTreeAsyncTransaction(
3553
+ this,
3554
+ this.mvcc,
3555
+ nestedTx,
3556
+ this.strategy,
3557
+ this.comparator,
3558
+ this.option
3686
3559
  );
3687
- return this._lock(
3688
- this.writeQueue,
3689
- range,
3690
- timeout,
3691
- task,
3692
- () => {
3693
- return !this.rangeOverlapping(this.writings, range) && !this.rangeOverlapping(this.readings, range);
3560
+ await tx._initInternal();
3561
+ return tx;
3562
+ }
3563
+ async insert(key, value) {
3564
+ return this.writeLock(1, async () => {
3565
+ const tx = await this.createTransaction();
3566
+ await tx.insert(key, value);
3567
+ const result = await tx.commit();
3568
+ if (!result.success) {
3569
+ throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
3694
3570
  }
3695
- );
3571
+ });
3696
3572
  }
3697
- /**
3698
- * Releases a read lock by its lock ID.
3699
- * @param lockId - The unique identifier for the lock to release.
3700
- */
3701
- readUnlock(lockId) {
3702
- this._free(this.readings, lockId);
3573
+ async delete(key, value) {
3574
+ return this.writeLock(1, async () => {
3575
+ const tx = await this.createTransaction();
3576
+ await tx.delete(key, value);
3577
+ const result = await tx.commit();
3578
+ if (!result.success) {
3579
+ throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
3580
+ }
3581
+ });
3703
3582
  }
3704
- /**
3705
- * Releases a write lock by its lock ID.
3706
- * @param lockId - The unique identifier for the lock to release.
3707
- */
3708
- writeUnlock(lockId) {
3709
- this._free(this.writings, lockId);
3583
+ };
3584
+
3585
+ // src/base/SerializeStrategy.ts
3586
+ var SerializeStrategy = class {
3587
+ order;
3588
+ head;
3589
+ constructor(order) {
3590
+ this.order = order;
3591
+ this.head = {
3592
+ order,
3593
+ root: null,
3594
+ data: {}
3595
+ };
3596
+ }
3597
+ };
3598
+
3599
+ // src/SerializeStrategySync.ts
3600
+ var SerializeStrategySync = class extends SerializeStrategy {
3601
+ getHeadData(key, defaultValue) {
3602
+ if (!Object.hasOwn(this.head.data, key)) {
3603
+ this.setHeadData(key, defaultValue);
3604
+ }
3605
+ return this.head.data[key];
3606
+ }
3607
+ setHeadData(key, data) {
3608
+ this.head.data[key] = data;
3609
+ this.writeHead(this.head);
3610
+ }
3611
+ autoIncrement(key, defaultValue) {
3612
+ const current = this.getHeadData(key, defaultValue);
3613
+ const next = current + 1;
3614
+ this.setHeadData(key, next);
3615
+ return current;
3616
+ }
3617
+ };
3618
+ var InMemoryStoreStrategySync = class extends SerializeStrategySync {
3619
+ node;
3620
+ constructor(order) {
3621
+ super(order);
3622
+ this.node = {};
3623
+ }
3624
+ id(isLeaf) {
3625
+ return this.autoIncrement("index", 1).toString();
3626
+ }
3627
+ read(id) {
3628
+ if (!Object.hasOwn(this.node, id)) {
3629
+ throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
3630
+ }
3631
+ const node = this.node[id];
3632
+ return JSON.parse(JSON.stringify(node));
3633
+ }
3634
+ write(id, node) {
3635
+ this.node[id] = node;
3636
+ }
3637
+ delete(id) {
3638
+ delete this.node[id];
3639
+ }
3640
+ readHead() {
3641
+ if (this.head.root === null) {
3642
+ return null;
3643
+ }
3644
+ return this.head;
3645
+ }
3646
+ writeHead(head) {
3647
+ this.head = head;
3710
3648
  }
3711
3649
  };
3712
3650