dataply 0.0.22-alpha.0 → 0.0.22-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cjs/index.js +1125 -970
  2. package/package.json +4 -4
package/dist/cjs/index.js CHANGED
@@ -38,7 +38,7 @@ __export(src_exports, {
38
38
  BPTreeSyncTransaction: () => BPTreeSyncTransaction,
39
39
  BitmapPageManager: () => BitmapPageManager,
40
40
  CacheEntanglementAsync: () => CacheEntanglementAsync,
41
- CacheEntanglementSync: () => CacheEntanglementSync2,
41
+ CacheEntanglementSync: () => CacheEntanglementSync,
42
42
  DataPageManager: () => DataPageManager,
43
43
  Dataply: () => Dataply,
44
44
  DataplyAPI: () => DataplyAPI,
@@ -125,6 +125,42 @@ var StringComparator = class extends ValueComparator {
125
125
  };
126
126
  var MVCCStrategy = class {
127
127
  };
128
+ var LRUMap = class {
129
+ cache = /* @__PURE__ */ new Map();
130
+ capacity;
131
+ constructor(capacity) {
132
+ this.capacity = capacity;
133
+ }
134
+ get(key) {
135
+ if (!this.cache.has(key)) return void 0;
136
+ const value = this.cache.get(key);
137
+ this.cache.delete(key);
138
+ this.cache.set(key, value);
139
+ return value;
140
+ }
141
+ set(key, value) {
142
+ if (this.cache.has(key)) {
143
+ this.cache.delete(key);
144
+ } else if (this.cache.size >= this.capacity) {
145
+ const oldestKey = this.cache.keys().next().value;
146
+ if (oldestKey !== void 0) this.cache.delete(oldestKey);
147
+ }
148
+ this.cache.set(key, value);
149
+ return this;
150
+ }
151
+ has(key) {
152
+ return this.cache.has(key);
153
+ }
154
+ delete(key) {
155
+ return this.cache.delete(key);
156
+ }
157
+ clear() {
158
+ this.cache.clear();
159
+ }
160
+ get size() {
161
+ return this.cache.size;
162
+ }
163
+ };
128
164
  var MVCCTransaction = class {
129
165
  committed;
130
166
  snapshotVersion;
@@ -132,7 +168,6 @@ var MVCCTransaction = class {
132
168
  writeBuffer;
133
169
  deleteBuffer;
134
170
  createdKeys;
135
- // create()로 생성된 키 추적
136
171
  deletedValues;
137
172
  // delete 시 삭제 전 값 저장
138
173
  originallyExisted;
@@ -151,7 +186,8 @@ var MVCCTransaction = class {
151
186
  versionIndex = /* @__PURE__ */ new Map();
152
187
  deletedCache = /* @__PURE__ */ new Map();
153
188
  activeTransactions = /* @__PURE__ */ new Set();
154
- constructor(strategy, parent, snapshotVersion) {
189
+ diskCache;
190
+ constructor(strategy, options, parent, snapshotVersion) {
155
191
  this.snapshotVersion = snapshotVersion ?? 0;
156
192
  this.writeBuffer = /* @__PURE__ */ new Map();
157
193
  this.deleteBuffer = /* @__PURE__ */ new Set();
@@ -166,6 +202,7 @@ var MVCCTransaction = class {
166
202
  this.snapshotLocalVersion = parent.localVersion;
167
203
  this.strategy = void 0;
168
204
  this.root = parent.root;
205
+ this.diskCache = parent.diskCache;
169
206
  } else {
170
207
  if (!strategy) throw new Error("Root Transaction must get Strategy");
171
208
  this.strategy = strategy;
@@ -173,8 +210,13 @@ var MVCCTransaction = class {
173
210
  this.localVersion = 0;
174
211
  this.snapshotLocalVersion = 0;
175
212
  this.root = this;
213
+ this.diskCache = new LRUMap(options?.cacheCapacity ?? 1e3);
176
214
  }
177
215
  }
216
+ /**
217
+ * Checks if the transaction is a root transaction.
218
+ * @returns True if the transaction is a root transaction, false otherwise.
219
+ */
178
220
  isRoot() {
179
221
  return !this.parent;
180
222
  }
@@ -191,7 +233,22 @@ var MVCCTransaction = class {
191
233
  }
192
234
  return false;
193
235
  }
194
- // --- Internal buffer manipulation helpers ---
236
+ /**
237
+ * Checks if a key was written in this transaction.
238
+ * @param key The key to check.
239
+ * @returns True if the key was written in this transaction, false otherwise.
240
+ */
241
+ isWrote(key) {
242
+ return this.writeBuffer.has(key);
243
+ }
244
+ /**
245
+ * Checks if a key was deleted in this transaction.
246
+ * @param key The key to check.
247
+ * @returns True if the key was deleted in this transaction, false otherwise.
248
+ */
249
+ isDeleted(key) {
250
+ return this.deleteBuffer.has(key);
251
+ }
195
252
  _recordHistory(key) {
196
253
  const existsInWriteBuffer = this.writeBuffer.has(key);
197
254
  const existsInDeleteBuffer = this.deleteBuffer.has(key);
@@ -205,6 +262,41 @@ var MVCCTransaction = class {
205
262
  });
206
263
  }
207
264
  }
265
+ /**
266
+ * BINARY SEARCH HELPER: Finds the index of the last element in the array
267
+ * where item[key] <= target. Assumes the array is sorted by 'key' ascending.
268
+ */
269
+ _findLastLE(array, target, property) {
270
+ let left = 0;
271
+ let right = array.length - 1;
272
+ let result = -1;
273
+ while (left <= right) {
274
+ const mid = left + right >> 1;
275
+ if (array[mid][property] <= target) {
276
+ result = mid;
277
+ left = mid + 1;
278
+ } else {
279
+ right = mid - 1;
280
+ }
281
+ }
282
+ return result;
283
+ }
284
+ /**
285
+ * BINARY SEARCH HELPER: Finds the index of the element in the array
286
+ * where item[key] === target. Assumes the array is sorted by 'key' ascending.
287
+ */
288
+ _findExact(array, target, property) {
289
+ let left = 0;
290
+ let right = array.length - 1;
291
+ while (left <= right) {
292
+ const mid = left + right >> 1;
293
+ const val = array[mid][property];
294
+ if (val === target) return mid;
295
+ if (val < target) left = mid + 1;
296
+ else right = mid - 1;
297
+ }
298
+ return -1;
299
+ }
208
300
  _bufferCreate(key, value, version) {
209
301
  if (version === void 0) this.localVersion++;
210
302
  const targetVersion = version ?? this.localVersion;
@@ -254,7 +346,11 @@ var MVCCTransaction = class {
254
346
  deleted.push({ key, data });
255
347
  }
256
348
  }
257
- return { created, updated, deleted };
349
+ return {
350
+ created,
351
+ updated,
352
+ deleted
353
+ };
258
354
  }
259
355
  /**
260
356
  * Rolls back the transaction.
@@ -272,7 +368,12 @@ var MVCCTransaction = class {
272
368
  if (this.root !== this) {
273
369
  this.root.activeTransactions.delete(this);
274
370
  }
275
- return { success: true, created, updated, deleted };
371
+ return {
372
+ success: true,
373
+ created,
374
+ updated,
375
+ deleted
376
+ };
276
377
  }
277
378
  /**
278
379
  * Cleans up both deletedCache and versionIndex based on minActiveVersion.
@@ -358,7 +459,7 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
358
459
  createNested() {
359
460
  if (this.committed) throw new Error("Transaction already committed");
360
461
  const childVersion = this.isRoot() ? this.version : this.snapshotVersion;
361
- const child = new _SyncMVCCTransaction(void 0, this, childVersion);
462
+ const child = new _SyncMVCCTransaction(void 0, void 0, this, childVersion);
362
463
  this.root.activeTransactions.add(child);
363
464
  return child;
364
465
  }
@@ -381,78 +482,114 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
381
482
  return this._diskExists(key, this.snapshotVersion);
382
483
  }
383
484
  _existsSnapshot(key, snapshotVersion, snapshotLocalVersion) {
384
- if (this.writeBuffer.has(key)) {
385
- const keyModVersion = this.keyVersions.get(key);
386
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
387
- return true;
388
- }
389
- }
390
- if (this.deleteBuffer.has(key)) {
391
- const keyModVersion = this.keyVersions.get(key);
392
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
393
- return false;
394
- }
395
- }
396
- const history = this.bufferHistory.get(key);
397
- if (history && snapshotLocalVersion !== void 0) {
398
- for (let i = history.length - 1; i >= 0; i--) {
399
- if (history[i].version <= snapshotLocalVersion) {
400
- return history[i].exists;
401
- }
485
+ let current = this;
486
+ let slVer = snapshotLocalVersion;
487
+ while (current) {
488
+ if (current.writeBuffer.has(key)) {
489
+ const keyModVersion = current.keyVersions.get(key);
490
+ if (slVer === void 0 || keyModVersion <= slVer) return true;
491
+ }
492
+ if (current.deleteBuffer.has(key)) {
493
+ const keyModVersion = current.keyVersions.get(key);
494
+ if (slVer === void 0 || keyModVersion <= slVer) return false;
495
+ }
496
+ const history = current.bufferHistory.get(key);
497
+ if (history && slVer !== void 0) {
498
+ const idx = current._findLastLE(history, slVer, "version");
499
+ if (idx >= 0) return history[idx].exists;
500
+ }
501
+ if (current.parent) {
502
+ slVer = current.snapshotLocalVersion;
503
+ current = current.parent;
504
+ } else {
505
+ return current._diskExists(key, snapshotVersion);
402
506
  }
403
507
  }
404
- if (this.parent) {
405
- return this.parent._existsSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
406
- } else {
407
- return this._diskExists(key, snapshotVersion);
408
- }
508
+ return false;
409
509
  }
410
510
  _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
411
- if (this.writeBuffer.has(key)) {
412
- const keyModVersion = this.keyVersions.get(key);
413
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
414
- return this.writeBuffer.get(key);
511
+ let current = this;
512
+ let slVer = snapshotLocalVersion;
513
+ while (current) {
514
+ if (current.writeBuffer.has(key)) {
515
+ const keyModVersion = current.keyVersions.get(key);
516
+ if (slVer === void 0 || keyModVersion <= slVer) {
517
+ return current.writeBuffer.get(key);
518
+ }
415
519
  }
416
- }
417
- if (this.deleteBuffer.has(key)) {
418
- const keyModVersion = this.keyVersions.get(key);
419
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
420
- return null;
520
+ if (current.deleteBuffer.has(key)) {
521
+ const keyModVersion = current.keyVersions.get(key);
522
+ if (slVer === void 0 || keyModVersion <= slVer) {
523
+ return null;
524
+ }
421
525
  }
422
- }
423
- const history = this.bufferHistory.get(key);
424
- if (history && snapshotLocalVersion !== void 0) {
425
- for (let i = history.length - 1; i >= 0; i--) {
426
- if (history[i].version <= snapshotLocalVersion) {
427
- return history[i].exists ? history[i].value : null;
526
+ const history = current.bufferHistory.get(key);
527
+ if (history && slVer !== void 0) {
528
+ const idx = current._findLastLE(history, slVer, "version");
529
+ if (idx >= 0) {
530
+ return history[idx].exists ? history[idx].value : null;
428
531
  }
429
532
  }
533
+ if (current.parent) {
534
+ slVer = current.snapshotLocalVersion;
535
+ current = current.parent;
536
+ } else {
537
+ return current._diskRead(key, snapshotVersion);
538
+ }
430
539
  }
431
- if (this.parent) {
432
- return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
433
- } else {
434
- return this._diskRead(key, snapshotVersion);
435
- }
540
+ return null;
436
541
  }
437
542
  commit(label) {
438
543
  const { created, updated, deleted } = this.getResultEntries();
439
544
  if (this.committed) {
440
- return { label, success: false, error: "Transaction already committed", conflict: void 0, created, updated, deleted };
545
+ return {
546
+ label,
547
+ success: false,
548
+ error: "Transaction already committed",
549
+ conflict: void 0,
550
+ created,
551
+ updated,
552
+ deleted
553
+ };
441
554
  }
442
555
  if (this.hasCommittedAncestor()) {
443
- return { label, success: false, error: "Ancestor transaction already committed", conflict: void 0, created, updated, deleted };
556
+ return {
557
+ label,
558
+ success: false,
559
+ error: "Ancestor transaction already committed",
560
+ conflict: void 0,
561
+ created,
562
+ updated,
563
+ deleted
564
+ };
444
565
  }
445
566
  if (this.parent) {
446
567
  const failure = this.parent._merge(this);
447
568
  if (failure) {
448
- return { label, success: false, error: failure.error, conflict: failure.conflict, created, updated, deleted };
569
+ return {
570
+ label,
571
+ success: false,
572
+ error: failure.error,
573
+ conflict: failure.conflict,
574
+ created,
575
+ updated,
576
+ deleted
577
+ };
449
578
  }
450
579
  this.committed = true;
451
580
  } else {
452
581
  if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
453
582
  const failure = this._merge(this);
454
583
  if (failure) {
455
- return { label, success: false, error: failure.error, conflict: failure.conflict, created: [], updated: [], deleted: [] };
584
+ return {
585
+ label,
586
+ success: false,
587
+ error: failure.error,
588
+ conflict: failure.conflict,
589
+ created: [],
590
+ updated: [],
591
+ deleted: []
592
+ };
456
593
  }
457
594
  this.writeBuffer.clear();
458
595
  this.deleteBuffer.clear();
@@ -465,7 +602,13 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
465
602
  this.snapshotVersion = this.version;
466
603
  }
467
604
  }
468
- return { label, success: true, created, updated, deleted };
605
+ return {
606
+ label,
607
+ success: true,
608
+ created,
609
+ updated,
610
+ deleted
611
+ };
469
612
  }
470
613
  _merge(child) {
471
614
  if (this.parent) {
@@ -474,7 +617,11 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
474
617
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
475
618
  return {
476
619
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
477
- conflict: { key, parent: this.read(key), child: child.read(key) }
620
+ conflict: {
621
+ key,
622
+ parent: this.read(key),
623
+ child: child.read(key)
624
+ }
478
625
  };
479
626
  }
480
627
  }
@@ -483,7 +630,11 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
483
630
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
484
631
  return {
485
632
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
486
- conflict: { key, parent: this.read(key), child: child.read(key) }
633
+ conflict: {
634
+ key,
635
+ parent: this.read(key),
636
+ child: child.read(key)
637
+ }
487
638
  };
488
639
  }
489
640
  }
@@ -512,7 +663,11 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
512
663
  if (lastVer > child.snapshotVersion) {
513
664
  return {
514
665
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (v${lastVer})`,
515
- conflict: { key, parent: this.read(key), child: child.read(key) }
666
+ conflict: {
667
+ key,
668
+ parent: this.read(key),
669
+ child: child.read(key)
670
+ }
516
671
  };
517
672
  }
518
673
  }
@@ -520,7 +675,11 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
520
675
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
521
676
  return {
522
677
  error: `Commit conflict: Key '${key}' was modified by a newer transaction in the same session (Local v${lastModLocalVer})`,
523
- conflict: { key, parent: this.read(key), child: child.read(key) }
678
+ conflict: {
679
+ key,
680
+ parent: this.read(key),
681
+ child: child.read(key)
682
+ }
524
683
  };
525
684
  }
526
685
  }
@@ -555,10 +714,14 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
555
714
  _diskWrite(key, value, version) {
556
715
  const strategy = this.strategy;
557
716
  if (!strategy) throw new Error("Root Transaction missing strategy");
558
- if (strategy.exists(key)) {
559
- const currentVal = strategy.read(key);
717
+ const rootAsAny = this.root;
718
+ if (this._diskExists(key, version)) {
719
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
560
720
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
561
721
  this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
722
+ rootAsAny.diskCache.set(key, value);
723
+ } else {
724
+ rootAsAny.diskCache.set(key, value);
562
725
  }
563
726
  strategy.write(key, value);
564
727
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -569,23 +732,25 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
569
732
  if (!strategy) throw new Error("Root Transaction missing strategy");
570
733
  const versions = this.versionIndex.get(key);
571
734
  if (!versions) {
572
- return strategy.exists(key) ? strategy.read(key) : null;
735
+ const rootAsAny = this.root;
736
+ if (this._diskExists(key, snapshotVersion)) {
737
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
738
+ rootAsAny.diskCache.set(key, val);
739
+ return val;
740
+ }
741
+ return null;
573
742
  }
574
743
  let targetVerObj = null;
575
744
  let nextVerObj = null;
576
- for (const v of versions) {
577
- if (v.version <= snapshotVersion) targetVerObj = v;
578
- else {
579
- nextVerObj = v;
580
- break;
581
- }
582
- }
745
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
746
+ if (idx >= 0) targetVerObj = versions[idx];
747
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
583
748
  if (!targetVerObj) {
584
749
  if (nextVerObj) {
585
750
  const cached2 = this.deletedCache.get(key);
586
751
  if (cached2) {
587
- const match = cached2.find((c) => c.deletedAtVersion === nextVerObj.version);
588
- if (match) return match.value;
752
+ const cIdx = this._findExact(cached2, nextVerObj.version, "deletedAtVersion");
753
+ if (cIdx >= 0) return cached2[cIdx].value;
589
754
  }
590
755
  }
591
756
  return null;
@@ -593,12 +758,18 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
593
758
  if (!targetVerObj.exists) return null;
594
759
  if (!nextVerObj) {
595
760
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
596
- return strategy.read(key);
761
+ if (this._diskExists(key, snapshotVersion)) {
762
+ const rootAsAny = this.root;
763
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
764
+ rootAsAny.diskCache.set(key, val);
765
+ return val;
766
+ }
767
+ return null;
597
768
  }
598
769
  const cached = this.deletedCache.get(key);
599
770
  if (cached) {
600
- const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
601
- if (match) return match.value;
771
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
772
+ if (cIdx >= 0) return cached[cIdx].value;
602
773
  }
603
774
  return null;
604
775
  }
@@ -607,23 +778,23 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
607
778
  if (!strategy) throw new Error("Root Transaction missing strategy");
608
779
  const versions = this.versionIndex.get(key);
609
780
  if (!versions) {
610
- return strategy.exists(key);
781
+ const rootAsAny = this.root;
782
+ if (rootAsAny.diskCache.has(key)) return rootAsAny.diskCache.get(key) !== null;
783
+ const exists = strategy.exists(key);
784
+ if (!exists) rootAsAny.diskCache.set(key, null);
785
+ return exists;
611
786
  }
612
787
  let targetVerObj = null;
613
788
  let nextVerObj = null;
614
- for (const v of versions) {
615
- if (v.version <= snapshotVersion) targetVerObj = v;
616
- else {
617
- nextVerObj = v;
618
- break;
619
- }
620
- }
789
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
790
+ if (idx >= 0) targetVerObj = versions[idx];
791
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
621
792
  if (!targetVerObj) {
622
793
  if (nextVerObj) {
623
794
  const cached = this.deletedCache.get(key);
624
795
  if (cached) {
625
- const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
626
- if (match) return true;
796
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
797
+ if (cIdx >= 0) return true;
627
798
  }
628
799
  }
629
800
  return false;
@@ -633,11 +804,13 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
633
804
  _diskDelete(key, snapshotVersion) {
634
805
  const strategy = this.strategy;
635
806
  if (!strategy) throw new Error("Root Transaction missing strategy");
636
- if (strategy.exists(key)) {
637
- const currentVal = strategy.read(key);
807
+ const rootAsAny = this.root;
808
+ if (this._diskExists(key, snapshotVersion)) {
809
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
638
810
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
639
811
  this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
640
812
  strategy.delete(key);
813
+ rootAsAny.diskCache.delete(key);
641
814
  }
642
815
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
643
816
  this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });
@@ -951,7 +1124,7 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
951
1124
  createNested() {
952
1125
  if (this.committed) throw new Error("Transaction already committed");
953
1126
  const childVersion = this.isRoot() ? this.version : this.snapshotVersion;
954
- const child = new _AsyncMVCCTransaction(void 0, this, childVersion);
1127
+ const child = new _AsyncMVCCTransaction(void 0, void 0, this, childVersion);
955
1128
  this.root.activeTransactions.add(child);
956
1129
  return child;
957
1130
  }
@@ -974,78 +1147,114 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
974
1147
  return await this._diskExists(key, this.snapshotVersion);
975
1148
  }
976
1149
  async _existsSnapshot(key, snapshotVersion, snapshotLocalVersion) {
977
- if (this.writeBuffer.has(key)) {
978
- const keyModVersion = this.keyVersions.get(key);
979
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
980
- return true;
981
- }
982
- }
983
- if (this.deleteBuffer.has(key)) {
984
- const keyModVersion = this.keyVersions.get(key);
985
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
986
- return false;
987
- }
988
- }
989
- const history = this.bufferHistory.get(key);
990
- if (history && snapshotLocalVersion !== void 0) {
991
- for (let i = history.length - 1; i >= 0; i--) {
992
- if (history[i].version <= snapshotLocalVersion) {
993
- return history[i].exists;
994
- }
1150
+ let current = this;
1151
+ let slVer = snapshotLocalVersion;
1152
+ while (current) {
1153
+ if (current.writeBuffer.has(key)) {
1154
+ const keyModVersion = current.keyVersions.get(key);
1155
+ if (slVer === void 0 || keyModVersion <= slVer) return true;
1156
+ }
1157
+ if (current.deleteBuffer.has(key)) {
1158
+ const keyModVersion = current.keyVersions.get(key);
1159
+ if (slVer === void 0 || keyModVersion <= slVer) return false;
1160
+ }
1161
+ const history = current.bufferHistory.get(key);
1162
+ if (history && slVer !== void 0) {
1163
+ const idx = current._findLastLE(history, slVer, "version");
1164
+ if (idx >= 0) return history[idx].exists;
1165
+ }
1166
+ if (current.parent) {
1167
+ slVer = current.snapshotLocalVersion;
1168
+ current = current.parent;
1169
+ } else {
1170
+ return await current._diskExists(key, snapshotVersion);
995
1171
  }
996
1172
  }
997
- if (this.parent) {
998
- return this.parent._existsSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
999
- } else {
1000
- return await this._diskExists(key, snapshotVersion);
1001
- }
1173
+ return false;
1002
1174
  }
1003
1175
  async _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
1004
- if (this.writeBuffer.has(key)) {
1005
- const keyModVersion = this.keyVersions.get(key);
1006
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
1007
- return this.writeBuffer.get(key);
1176
+ let current = this;
1177
+ let slVer = snapshotLocalVersion;
1178
+ while (current) {
1179
+ if (current.writeBuffer.has(key)) {
1180
+ const keyModVersion = current.keyVersions.get(key);
1181
+ if (slVer === void 0 || keyModVersion <= slVer) {
1182
+ return current.writeBuffer.get(key);
1183
+ }
1008
1184
  }
1009
- }
1010
- if (this.deleteBuffer.has(key)) {
1011
- const keyModVersion = this.keyVersions.get(key);
1012
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
1013
- return null;
1185
+ if (current.deleteBuffer.has(key)) {
1186
+ const keyModVersion = current.keyVersions.get(key);
1187
+ if (slVer === void 0 || keyModVersion <= slVer) {
1188
+ return null;
1189
+ }
1014
1190
  }
1015
- }
1016
- const history = this.bufferHistory.get(key);
1017
- if (history && snapshotLocalVersion !== void 0) {
1018
- for (let i = history.length - 1; i >= 0; i--) {
1019
- if (history[i].version <= snapshotLocalVersion) {
1020
- return history[i].exists ? history[i].value : null;
1191
+ const history = current.bufferHistory.get(key);
1192
+ if (history && slVer !== void 0) {
1193
+ const idx = current._findLastLE(history, slVer, "version");
1194
+ if (idx >= 0) {
1195
+ return history[idx].exists ? history[idx].value : null;
1021
1196
  }
1022
1197
  }
1198
+ if (current.parent) {
1199
+ slVer = current.snapshotLocalVersion;
1200
+ current = current.parent;
1201
+ } else {
1202
+ return await current._diskRead(key, snapshotVersion);
1203
+ }
1023
1204
  }
1024
- if (this.parent) {
1025
- return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
1026
- } else {
1027
- return await this._diskRead(key, snapshotVersion);
1028
- }
1205
+ return null;
1029
1206
  }
1030
1207
  async commit(label) {
1031
1208
  const { created, updated, deleted } = this.getResultEntries();
1032
1209
  if (this.committed) {
1033
- return { label, success: false, error: "Transaction already committed", conflict: void 0, created, updated, deleted };
1210
+ return {
1211
+ label,
1212
+ success: false,
1213
+ error: "Transaction already committed",
1214
+ conflict: void 0,
1215
+ created,
1216
+ updated,
1217
+ deleted
1218
+ };
1034
1219
  }
1035
1220
  if (this.hasCommittedAncestor()) {
1036
- return { label, success: false, error: "Ancestor transaction already committed", conflict: void 0, created, updated, deleted };
1221
+ return {
1222
+ label,
1223
+ success: false,
1224
+ error: "Ancestor transaction already committed",
1225
+ conflict: void 0,
1226
+ created,
1227
+ updated,
1228
+ deleted
1229
+ };
1037
1230
  }
1038
1231
  if (this.parent) {
1039
1232
  const failure = await this.parent._merge(this);
1040
1233
  if (failure) {
1041
- return { label, success: false, error: failure.error, conflict: failure.conflict, created, updated, deleted };
1234
+ return {
1235
+ label,
1236
+ success: false,
1237
+ error: failure.error,
1238
+ conflict: failure.conflict,
1239
+ created,
1240
+ updated,
1241
+ deleted
1242
+ };
1042
1243
  }
1043
1244
  this.committed = true;
1044
1245
  } else {
1045
1246
  if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
1046
1247
  const failure = await this._merge(this);
1047
1248
  if (failure) {
1048
- return { label, success: false, error: failure.error, conflict: failure.conflict, created: [], updated: [], deleted: [] };
1249
+ return {
1250
+ label,
1251
+ success: false,
1252
+ error: failure.error,
1253
+ conflict: failure.conflict,
1254
+ created: [],
1255
+ updated: [],
1256
+ deleted: []
1257
+ };
1049
1258
  }
1050
1259
  this.writeBuffer.clear();
1051
1260
  this.deleteBuffer.clear();
@@ -1058,7 +1267,13 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1058
1267
  this.snapshotVersion = this.version;
1059
1268
  }
1060
1269
  }
1061
- return { label, success: true, created, updated, deleted };
1270
+ return {
1271
+ label,
1272
+ success: true,
1273
+ created,
1274
+ updated,
1275
+ deleted
1276
+ };
1062
1277
  }
1063
1278
  async _merge(child) {
1064
1279
  return this.writeLock(async () => {
@@ -1068,7 +1283,11 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1068
1283
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
1069
1284
  return {
1070
1285
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
1071
- conflict: { key, parent: await this.read(key), child: await child.read(key) }
1286
+ conflict: {
1287
+ key,
1288
+ parent: await this.read(key),
1289
+ child: await child.read(key)
1290
+ }
1072
1291
  };
1073
1292
  }
1074
1293
  }
@@ -1077,7 +1296,11 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1077
1296
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
1078
1297
  return {
1079
1298
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
1080
- conflict: { key, parent: await this.read(key), child: await child.read(key) }
1299
+ conflict: {
1300
+ key,
1301
+ parent: await this.read(key),
1302
+ child: await child.read(key)
1303
+ }
1081
1304
  };
1082
1305
  }
1083
1306
  }
@@ -1107,7 +1330,11 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1107
1330
  if (lastVer > child.snapshotVersion) {
1108
1331
  return {
1109
1332
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (v${lastVer})`,
1110
- conflict: { key, parent: await this.read(key), child: await child.read(key) }
1333
+ conflict: {
1334
+ key,
1335
+ parent: await this.read(key),
1336
+ child: await child.read(key)
1337
+ }
1111
1338
  };
1112
1339
  }
1113
1340
  }
@@ -1115,7 +1342,11 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1115
1342
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
1116
1343
  return {
1117
1344
  error: `Commit conflict: Key '${key}' was modified by a newer transaction in the same session (Local v${lastModLocalVer})`,
1118
- conflict: { key, parent: await this.read(key), child: await child.read(key) }
1345
+ conflict: {
1346
+ key,
1347
+ parent: await this.read(key),
1348
+ child: await child.read(key)
1349
+ }
1119
1350
  };
1120
1351
  }
1121
1352
  }
@@ -1151,10 +1382,14 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1151
1382
  async _diskWrite(key, value, version) {
1152
1383
  const strategy = this.strategy;
1153
1384
  if (!strategy) throw new Error("Root Transaction missing strategy");
1154
- if (await strategy.exists(key)) {
1155
- const currentVal = await strategy.read(key);
1385
+ const rootAsAny = this.root;
1386
+ if (await this._diskExists(key, version)) {
1387
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
1156
1388
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
1157
1389
  this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
1390
+ rootAsAny.diskCache.set(key, value);
1391
+ } else {
1392
+ rootAsAny.diskCache.set(key, value);
1158
1393
  }
1159
1394
  await strategy.write(key, value);
1160
1395
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -1165,23 +1400,25 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1165
1400
  if (!strategy) throw new Error("Root Transaction missing strategy");
1166
1401
  const versions = this.versionIndex.get(key);
1167
1402
  if (!versions) {
1168
- return await strategy.exists(key) ? await strategy.read(key) : null;
1403
+ const rootAsAny = this.root;
1404
+ if (await this._diskExists(key, snapshotVersion)) {
1405
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
1406
+ rootAsAny.diskCache.set(key, val);
1407
+ return val;
1408
+ }
1409
+ return null;
1169
1410
  }
1170
1411
  let targetVerObj = null;
1171
1412
  let nextVerObj = null;
1172
- for (const v of versions) {
1173
- if (v.version <= snapshotVersion) targetVerObj = v;
1174
- else {
1175
- nextVerObj = v;
1176
- break;
1177
- }
1178
- }
1413
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
1414
+ if (idx >= 0) targetVerObj = versions[idx];
1415
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
1179
1416
  if (!targetVerObj) {
1180
1417
  if (nextVerObj) {
1181
1418
  const cached2 = this.deletedCache.get(key);
1182
1419
  if (cached2) {
1183
- const match = cached2.find((c) => c.deletedAtVersion === nextVerObj.version);
1184
- if (match) return match.value;
1420
+ const cIdx = this._findExact(cached2, nextVerObj.version, "deletedAtVersion");
1421
+ if (cIdx >= 0) return cached2[cIdx].value;
1185
1422
  }
1186
1423
  }
1187
1424
  return null;
@@ -1189,12 +1426,18 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1189
1426
  if (!targetVerObj.exists) return null;
1190
1427
  if (!nextVerObj) {
1191
1428
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
1192
- return strategy.read(key);
1429
+ if (await this._diskExists(key, snapshotVersion)) {
1430
+ const rootAsAny = this.root;
1431
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
1432
+ rootAsAny.diskCache.set(key, val);
1433
+ return val;
1434
+ }
1435
+ return null;
1193
1436
  }
1194
1437
  const cached = this.deletedCache.get(key);
1195
1438
  if (cached) {
1196
- const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
1197
- if (match) return match.value;
1439
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
1440
+ if (cIdx >= 0) return cached[cIdx].value;
1198
1441
  }
1199
1442
  return null;
1200
1443
  }
@@ -1203,366 +1446,47 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1203
1446
  if (!strategy) throw new Error("Root Transaction missing strategy");
1204
1447
  const versions = this.versionIndex.get(key);
1205
1448
  if (!versions) {
1206
- return await strategy.exists(key);
1449
+ const rootAsAny = this.root;
1450
+ if (rootAsAny.diskCache.has(key)) return rootAsAny.diskCache.get(key) !== null;
1451
+ const exists = await strategy.exists(key);
1452
+ if (!exists) rootAsAny.diskCache.set(key, null);
1453
+ return exists;
1207
1454
  }
1208
1455
  let targetVerObj = null;
1209
1456
  let nextVerObj = null;
1210
- for (const v of versions) {
1211
- if (v.version <= snapshotVersion) targetVerObj = v;
1212
- else {
1213
- nextVerObj = v;
1214
- break;
1215
- }
1216
- }
1457
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
1458
+ if (idx >= 0) targetVerObj = versions[idx];
1459
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
1217
1460
  if (!targetVerObj) {
1218
1461
  if (nextVerObj) {
1219
1462
  const cached = this.deletedCache.get(key);
1220
1463
  if (cached) {
1221
- const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
1222
- if (match) return true;
1223
- }
1224
- }
1225
- return false;
1226
- }
1227
- return targetVerObj.exists;
1228
- }
1229
- async _diskDelete(key, snapshotVersion) {
1230
- const strategy = this.strategy;
1231
- if (!strategy) throw new Error("Root Transaction missing strategy");
1232
- if (await strategy.exists(key)) {
1233
- const currentVal = await strategy.read(key);
1234
- if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
1235
- this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
1236
- await strategy.delete(key);
1237
- }
1238
- if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
1239
- this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });
1240
- }
1241
- };
1242
- var LRUMap = class {
1243
- capacity;
1244
- map;
1245
- head = null;
1246
- tail = null;
1247
- /**
1248
- * Creates an instance of LRUMap.
1249
- * @param capacity The maximum number of items the cache can hold.
1250
- */
1251
- constructor(capacity) {
1252
- this.capacity = capacity;
1253
- this.map = /* @__PURE__ */ new Map();
1254
- }
1255
- /**
1256
- * Promotes a node to the head of the linked list (marks as most recently used).
1257
- * @param node The node to promote.
1258
- */
1259
- promote(node) {
1260
- this.extract(node);
1261
- this.prepend(node);
1262
- }
1263
- /**
1264
- * Disconnects a node from the doubly linked list.
1265
- * @param node The node to extract.
1266
- */
1267
- extract(node) {
1268
- if (node.prev) node.prev.next = node.next;
1269
- else this.head = node.next;
1270
- if (node.next) node.next.prev = node.prev;
1271
- else this.tail = node.prev;
1272
- node.prev = null;
1273
- node.next = null;
1274
- }
1275
- /**
1276
- * Inserts a node at the head of the doubly linked list.
1277
- * @param node The node to prepend.
1278
- */
1279
- prepend(node) {
1280
- node.next = this.head;
1281
- if (this.head) this.head.prev = node;
1282
- this.head = node;
1283
- if (!this.tail) this.tail = node;
1284
- }
1285
- /**
1286
- * Stores or updates a value by key.
1287
- * If the capacity is exceeded, the least recently used item (tail) is removed.
1288
- * @param key The key to store.
1289
- * @param value The value to store.
1290
- */
1291
- set(key, value) {
1292
- const existing = this.map.get(key);
1293
- if (existing) {
1294
- existing.value = value;
1295
- this.promote(existing);
1296
- return;
1297
- }
1298
- const newNode = { key, value, prev: null, next: null };
1299
- this.map.set(key, newNode);
1300
- this.prepend(newNode);
1301
- if (this.map.size > this.capacity && this.tail) {
1302
- this.map.delete(this.tail.key);
1303
- this.extract(this.tail);
1304
- }
1305
- }
1306
- /**
1307
- * Retrieves a value by key.
1308
- * Accessing the item moves it to the "most recently used" position.
1309
- * @param key The key to look for.
1310
- * @returns The value associated with the key, or undefined if not found.
1311
- */
1312
- get(key) {
1313
- const node = this.map.get(key);
1314
- if (!node) return void 0;
1315
- this.promote(node);
1316
- return node.value;
1317
- }
1318
- /**
1319
- * Checks if a key exists in the cache without changing its access order.
1320
- * @param key The key to check.
1321
- * @returns True if the key exists, false otherwise.
1322
- */
1323
- has(key) {
1324
- return this.map.has(key);
1325
- }
1326
- /**
1327
- * Removes a key and its associated value from the cache.
1328
- * @param key The key to remove.
1329
- * @returns True if the key was found and removed, false otherwise.
1330
- */
1331
- delete(key) {
1332
- const node = this.map.get(key);
1333
- if (!node) return false;
1334
- this.extract(node);
1335
- this.map.delete(key);
1336
- return true;
1337
- }
1338
- /**
1339
- * Returns an iterator of keys in the order of most recently used to least recently used.
1340
- * @returns An iterable iterator of keys.
1341
- */
1342
- *keys() {
1343
- let current = this.head;
1344
- while (current) {
1345
- yield current.key;
1346
- current = current.next;
1347
- }
1348
- }
1349
- /**
1350
- * Returns the current number of items in the cache.
1351
- */
1352
- get size() {
1353
- return this.map.size;
1354
- }
1355
- /**
1356
- * Clears all items from the cache.
1357
- */
1358
- clear() {
1359
- this.map.clear();
1360
- this.head = null;
1361
- this.tail = null;
1362
- }
1363
- };
1364
- var CacheEntanglement = class {
1365
- creation;
1366
- beforeUpdateHook;
1367
- capacity;
1368
- dependencies;
1369
- caches;
1370
- parameters;
1371
- assignments;
1372
- dependencyProperties;
1373
- updateRequirements;
1374
- constructor(creation, option) {
1375
- option = option ?? {};
1376
- const {
1377
- dependencies,
1378
- capacity,
1379
- beforeUpdateHook
1380
- } = option;
1381
- this.creation = creation;
1382
- this.beforeUpdateHook = beforeUpdateHook ?? (() => {
1383
- });
1384
- this.capacity = capacity ?? 100;
1385
- this.assignments = [];
1386
- this.caches = new LRUMap(this.capacity);
1387
- this.parameters = /* @__PURE__ */ new Map();
1388
- this.dependencies = dependencies ?? {};
1389
- this.dependencyProperties = Object.keys(this.dependencies);
1390
- this.updateRequirements = /* @__PURE__ */ new Set();
1391
- for (const name in this.dependencies) {
1392
- const dependency = this.dependencies[name];
1393
- if (!dependency.assignments.includes(this)) {
1394
- dependency.assignments.push(this);
1395
- }
1396
- }
1397
- }
1398
- bubbleUpdateSignal(key) {
1399
- this.updateRequirements.add(key);
1400
- for (let i = 0, len = this.assignments.length; i < len; i++) {
1401
- const t = this.assignments[i];
1402
- const instance = t;
1403
- for (const cacheKey of instance.caches.keys()) {
1404
- if (cacheKey === key || cacheKey.startsWith(`${key}/`)) {
1405
- instance.bubbleUpdateSignal(cacheKey);
1406
- }
1407
- }
1408
- }
1409
- }
1410
- dependencyKey(key) {
1411
- const i = key.lastIndexOf("/");
1412
- if (i === -1) {
1413
- return key;
1414
- }
1415
- return key.substring(0, i);
1416
- }
1417
- /**
1418
- * Returns all keys stored in the instance.
1419
- */
1420
- keys() {
1421
- return this.parameters.keys();
1422
- }
1423
- /**
1424
- * Deletes all cache values stored in the instance.
1425
- */
1426
- clear() {
1427
- for (const key of this.keys()) {
1428
- this.delete(key);
1429
- }
1430
- }
1431
- /**
1432
- * Checks if there is a cache value stored in the key within the instance.
1433
- * @param key The key to search.
1434
- */
1435
- exists(key) {
1436
- return this.parameters.has(key);
1437
- }
1438
- /**
1439
- * Checks if there is a cache value stored in the key within the instance.
1440
- * This method is an alias for `exists`.
1441
- * @param key The key to search.
1442
- */
1443
- has(key) {
1444
- return this.exists(key);
1445
- }
1446
- /**
1447
- * Deletes the cache value stored in the key within the instance.
1448
- * @param key The key to delete.
1449
- */
1450
- delete(key) {
1451
- this.caches.delete(key);
1452
- this.parameters.delete(key);
1453
- this.updateRequirements.delete(key);
1454
- for (let i = 0, len = this.assignments.length; i < len; i++) {
1455
- const t = this.assignments[i];
1456
- const instance = t;
1457
- for (const cacheKey of instance.keys()) {
1458
- if (cacheKey === key || cacheKey.startsWith(`${key}/`)) {
1459
- instance.delete(cacheKey);
1464
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
1465
+ if (cIdx >= 0) return true;
1460
1466
  }
1461
1467
  }
1468
+ return false;
1462
1469
  }
1470
+ return targetVerObj.exists;
1463
1471
  }
1464
- };
1465
- var CacheData = class _CacheData {
1466
- static StructuredClone = globalThis.structuredClone.bind(globalThis);
1467
- _value;
1468
- constructor(value) {
1469
- this._value = value;
1470
- }
1471
- /**
1472
- * This is cached data.
1473
- * It was generated at the time of caching, so there is a risk of modification if it's an object due to shallow copying.
1474
- * 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.
1475
- */
1476
- get raw() {
1477
- return this._value;
1478
- }
1479
- /**
1480
- * The method returns a copied value of the cached data.
1481
- * You can pass a function as a parameter to copy the value. This parameter function should return the copied value.
1482
- *
1483
- * If no parameter is passed, it defaults to using `structuredClone` function to copy the value.
1484
- * If you prefer shallow copying instead of deep copying,
1485
- * you can use the default options `array-shallow-copy`, `object-shallow-copy` and `deep-copy`,
1486
- * which are replaced with functions to shallow copy arrays and objects, respectively. This is a syntactic sugar.
1487
- * @param strategy The function that returns the copied value.
1488
- * If you want to perform a shallow copy, simply pass the strings `array-shallow-copy` or `object-shallow-copy` for easy use.
1489
- * The `array-shallow-copy` strategy performs a shallow copy of an array.
1490
- * The `object-shallow-copy` strategy performs a shallow copy of an object.
1491
- * The `deep-copy` strategy performs a deep copy of the value using `structuredClone`.
1492
- * The default is `deep-copy`.
1493
- */
1494
- clone(strategy = "deep-copy") {
1495
- if (strategy && typeof strategy !== "string") {
1496
- return strategy(this.raw);
1497
- }
1498
- switch (strategy) {
1499
- case "array-shallow-copy":
1500
- return [].concat(this.raw);
1501
- case "object-shallow-copy":
1502
- return Object.assign({}, this.raw);
1503
- case "deep-copy":
1504
- default:
1505
- return _CacheData.StructuredClone(this.raw);
1506
- }
1507
- }
1508
- };
1509
- var CacheEntanglementSync = class extends CacheEntanglement {
1510
- constructor(creation, option) {
1511
- super(creation, option);
1512
- }
1513
- recache(key) {
1514
- if (!this.parameters.has(key)) {
1515
- return;
1516
- }
1517
- if (!this.caches.has(key) || this.updateRequirements.has(key)) {
1518
- this.resolve(key, ...this.parameters.get(key));
1519
- }
1520
- return this.caches.get(key);
1521
- }
1522
- resolve(key, ...parameter) {
1523
- const resolved = {};
1524
- const dependencyKey = this.dependencyKey(key);
1525
- this.beforeUpdateHook(key, dependencyKey, ...parameter);
1526
- for (let i = 0, len = this.dependencyProperties.length; i < len; i++) {
1527
- const name = this.dependencyProperties[i];
1528
- const dependency = this.dependencies[name];
1529
- if (!dependency.exists(key) && !dependency.exists(dependencyKey)) {
1530
- throw new Error(`The key '${key}' or '${dependencyKey}' has not been assigned yet in dependency '${name.toString()}'.`, {
1531
- cause: {
1532
- from: this
1533
- }
1534
- });
1535
- }
1536
- const dependencyValue = dependency.recache(key) ?? dependency.recache(dependencyKey);
1537
- resolved[name] = dependencyValue;
1538
- }
1539
- const value = new CacheData(this.creation(key, resolved, ...parameter));
1540
- this.updateRequirements.delete(key);
1541
- this.parameters.set(key, parameter);
1542
- this.caches.set(key, value);
1543
- return value;
1544
- }
1545
- get(key) {
1546
- if (!this.parameters.has(key)) {
1547
- throw new Error(`Cache value not found: ${key}`);
1548
- }
1549
- return this.cache(key, ...this.parameters.get(key));
1550
- }
1551
- cache(key, ...parameter) {
1552
- if (!this.caches.has(key) || this.updateRequirements.has(key)) {
1553
- this.resolve(key, ...parameter);
1472
+ async _diskDelete(key, snapshotVersion) {
1473
+ const strategy = this.strategy;
1474
+ if (!strategy) throw new Error("Root Transaction missing strategy");
1475
+ const rootAsAny = this.root;
1476
+ if (await this._diskExists(key, snapshotVersion)) {
1477
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
1478
+ if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
1479
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
1480
+ await strategy.delete(key);
1481
+ rootAsAny.diskCache.delete(key);
1554
1482
  }
1555
- return this.caches.get(key);
1556
- }
1557
- update(key, ...parameter) {
1558
- this.bubbleUpdateSignal(key);
1559
- this.resolve(key, ...parameter);
1560
- return this.caches.get(key);
1483
+ if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
1484
+ this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });
1561
1485
  }
1562
1486
  };
1563
1487
  var BPTreeTransaction = class _BPTreeTransaction {
1564
- _cachedRegexp;
1565
- nodes;
1488
+ _cachedRegexp = /* @__PURE__ */ new Map();
1489
+ nodes = /* @__PURE__ */ new Map();
1566
1490
  deletedNodeBuffer = /* @__PURE__ */ new Map();
1567
1491
  rootTx;
1568
1492
  mvccRoot;
@@ -1592,8 +1516,12 @@ var BPTreeTransaction = class _BPTreeTransaction {
1592
1516
  like: (nv, v) => {
1593
1517
  const nodeValue = this.comparator.match(nv);
1594
1518
  const value = v;
1595
- const cache = this._cachedRegexp.cache(value);
1596
- const regexp = cache.raw;
1519
+ if (!this._cachedRegexp.has(value)) {
1520
+ const pattern = value.replace(/%/g, ".*").replace(/_/g, ".");
1521
+ const regexp2 = new RegExp(`^${pattern}$`, "i");
1522
+ this._cachedRegexp.set(value, regexp2);
1523
+ }
1524
+ const regexp = this._cachedRegexp.get(value);
1597
1525
  return regexp.test(nodeValue);
1598
1526
  }
1599
1527
  };
@@ -1765,6 +1693,9 @@ var BPTreeTransaction = class _BPTreeTransaction {
1765
1693
  }
1766
1694
  return true;
1767
1695
  }
1696
+ _cloneNode(node) {
1697
+ return JSON.parse(JSON.stringify(node));
1698
+ }
1768
1699
  /**
1769
1700
  * Selects the best driver key from a condition object.
1770
1701
  * The driver key determines the starting point and traversal direction for queries.
@@ -1797,17 +1728,6 @@ var BPTreeTransaction = class _BPTreeTransaction {
1797
1728
  this.strategy = strategy;
1798
1729
  this.comparator = comparator;
1799
1730
  this.option = option ?? {};
1800
- this.nodes = new LRUMap(this.option.capacity ?? 1e3);
1801
- this._cachedRegexp = this._createCachedRegexp();
1802
- }
1803
- _createCachedRegexp() {
1804
- return new CacheEntanglementSync((key) => {
1805
- const pattern = key.replace(/%/g, ".*").replace(/_/g, ".");
1806
- const regexp = new RegExp(`^${pattern}$`, "i");
1807
- return regexp;
1808
- }, {
1809
- capacity: this.option.capacity ?? 1e3
1810
- });
1811
1731
  }
1812
1732
  ensureValues(v) {
1813
1733
  if (!Array.isArray(v)) {
@@ -1840,7 +1760,6 @@ var BPTreeTransaction = class _BPTreeTransaction {
1840
1760
  }
1841
1761
  _clearCache() {
1842
1762
  this._cachedRegexp.clear();
1843
- this.nodes.clear();
1844
1763
  }
1845
1764
  /**
1846
1765
  * Clears all cached nodes.
@@ -1891,9 +1810,6 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
1891
1810
  );
1892
1811
  }
1893
1812
  getNode(id) {
1894
- if (this.nodes.has(id)) {
1895
- return this.nodes.get(id);
1896
- }
1897
1813
  return this.mvcc.read(id);
1898
1814
  }
1899
1815
  /**
@@ -1911,23 +1827,22 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
1911
1827
  prev
1912
1828
  };
1913
1829
  this.mvcc.create(id, node);
1914
- this.nodes.set(id, node);
1915
1830
  return node;
1916
1831
  }
1917
1832
  _updateNode(node) {
1833
+ if (this.mvcc.isDeleted(node.id)) {
1834
+ return;
1835
+ }
1918
1836
  this.mvcc.write(node.id, node);
1919
- this.nodes.set(node.id, node);
1920
1837
  }
1921
1838
  _deleteNode(node) {
1839
+ if (this.mvcc.isDeleted(node.id)) {
1840
+ return;
1841
+ }
1922
1842
  this.mvcc.delete(node.id);
1923
- this.nodes.delete(node.id);
1924
1843
  }
1925
1844
  _readHead() {
1926
- if (this.nodes.has("__HEAD__")) {
1927
- return this.nodes.get("__HEAD__") ?? null;
1928
- }
1929
- const head = this.mvcc.read("__HEAD__");
1930
- return head ?? null;
1845
+ return this.mvcc.read("__HEAD__");
1931
1846
  }
1932
1847
  _writeHead(head) {
1933
1848
  if (!this.mvcc.exists("__HEAD__")) {
@@ -1935,49 +1850,56 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
1935
1850
  } else {
1936
1851
  this.mvcc.write("__HEAD__", head);
1937
1852
  }
1938
- this.nodes.set("__HEAD__", head);
1939
1853
  this.rootId = head.root;
1940
1854
  }
1941
1855
  _insertAtLeaf(node, key, value) {
1942
- if (node.values.length) {
1943
- for (let i = 0, len = node.values.length; i < len; i++) {
1944
- const nValue = node.values[i];
1856
+ let leaf = node;
1857
+ if (leaf.values.length) {
1858
+ for (let i = 0, len = leaf.values.length; i < len; i++) {
1859
+ const nValue = leaf.values[i];
1945
1860
  if (this.comparator.isSame(value, nValue)) {
1946
- const keys = node.keys[i];
1861
+ const keys = leaf.keys[i];
1947
1862
  if (keys.includes(key)) {
1948
1863
  break;
1949
1864
  }
1950
- keys.push(key);
1951
- this._updateNode(node);
1952
- return;
1865
+ leaf = this._cloneNode(leaf);
1866
+ leaf.keys[i].push(key);
1867
+ this._updateNode(leaf);
1868
+ return leaf;
1953
1869
  } else if (this.comparator.isLower(value, nValue)) {
1954
- node.values.splice(i, 0, value);
1955
- node.keys.splice(i, 0, [key]);
1956
- this._updateNode(node);
1957
- return;
1958
- } else if (i + 1 === node.values.length) {
1959
- node.values.push(value);
1960
- node.keys.push([key]);
1961
- this._updateNode(node);
1962
- return;
1870
+ leaf = this._cloneNode(leaf);
1871
+ leaf.values.splice(i, 0, value);
1872
+ leaf.keys.splice(i, 0, [key]);
1873
+ this._updateNode(leaf);
1874
+ return leaf;
1875
+ } else if (i + 1 === leaf.values.length) {
1876
+ leaf = this._cloneNode(leaf);
1877
+ leaf.values.push(value);
1878
+ leaf.keys.push([key]);
1879
+ this._updateNode(leaf);
1880
+ return leaf;
1963
1881
  }
1964
1882
  }
1965
1883
  } else {
1966
- node.values = [value];
1967
- node.keys = [[key]];
1968
- this._updateNode(node);
1969
- return;
1884
+ leaf = this._cloneNode(leaf);
1885
+ leaf.values = [value];
1886
+ leaf.keys = [[key]];
1887
+ this._updateNode(leaf);
1888
+ return leaf;
1970
1889
  }
1890
+ return leaf;
1971
1891
  }
1972
- _insertInParent(node, value, pointer) {
1892
+ _insertInParent(node, value, newSiblingNode) {
1973
1893
  if (this.rootId === node.id) {
1974
- const root = this._createNode(false, [node.id, pointer.id], [value]);
1894
+ node = this._cloneNode(node);
1895
+ newSiblingNode = this._cloneNode(newSiblingNode);
1896
+ const root = this._createNode(false, [node.id, newSiblingNode.id], [value]);
1975
1897
  this.rootId = root.id;
1976
1898
  node.parent = root.id;
1977
- pointer.parent = root.id;
1978
- if (pointer.leaf) {
1979
- node.next = pointer.id;
1980
- pointer.prev = node.id;
1899
+ newSiblingNode.parent = root.id;
1900
+ if (newSiblingNode.leaf) {
1901
+ node.next = newSiblingNode.id;
1902
+ newSiblingNode.prev = node.id;
1981
1903
  }
1982
1904
  this._writeHead({
1983
1905
  root: root.id,
@@ -1985,53 +1907,54 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
1985
1907
  data: this.strategy.head.data
1986
1908
  });
1987
1909
  this._updateNode(node);
1988
- this._updateNode(pointer);
1910
+ this._updateNode(newSiblingNode);
1989
1911
  return;
1990
1912
  }
1991
- const parentNode = this.getNode(node.parent);
1913
+ const parentNode = this._cloneNode(this.getNode(node.parent));
1992
1914
  const nodeIndex = parentNode.keys.indexOf(node.id);
1993
1915
  if (nodeIndex === -1) {
1994
1916
  throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
1995
1917
  }
1996
1918
  parentNode.values.splice(nodeIndex, 0, value);
1997
- parentNode.keys.splice(nodeIndex + 1, 0, pointer.id);
1998
- pointer.parent = parentNode.id;
1999
- if (pointer.leaf) {
2000
- const leftSibling = node;
1919
+ parentNode.keys.splice(nodeIndex + 1, 0, newSiblingNode.id);
1920
+ newSiblingNode = this._cloneNode(newSiblingNode);
1921
+ newSiblingNode.parent = parentNode.id;
1922
+ if (newSiblingNode.leaf) {
1923
+ const leftSibling = this._cloneNode(node);
2001
1924
  const oldNextId = leftSibling.next;
2002
- pointer.prev = leftSibling.id;
2003
- pointer.next = oldNextId;
2004
- leftSibling.next = pointer.id;
1925
+ newSiblingNode.prev = leftSibling.id;
1926
+ newSiblingNode.next = oldNextId;
1927
+ leftSibling.next = newSiblingNode.id;
2005
1928
  this._updateNode(leftSibling);
2006
1929
  if (oldNextId) {
2007
- const oldNext = this.getNode(oldNextId);
2008
- oldNext.prev = pointer.id;
1930
+ const oldNext = this._cloneNode(this.getNode(oldNextId));
1931
+ oldNext.prev = newSiblingNode.id;
2009
1932
  this._updateNode(oldNext);
2010
1933
  }
2011
1934
  }
2012
1935
  this._updateNode(parentNode);
2013
- this._updateNode(pointer);
1936
+ this._updateNode(newSiblingNode);
2014
1937
  if (parentNode.keys.length > this.order) {
2015
- const parentPointer = this._createNode(false, [], []);
2016
- parentPointer.parent = parentNode.parent;
1938
+ const newSiblingNodeRecursive = this._createNode(false, [], []);
1939
+ newSiblingNodeRecursive.parent = parentNode.parent;
2017
1940
  const mid = Math.ceil(this.order / 2) - 1;
2018
- parentPointer.values = parentNode.values.slice(mid + 1);
2019
- parentPointer.keys = parentNode.keys.slice(mid + 1);
1941
+ newSiblingNodeRecursive.values = parentNode.values.slice(mid + 1);
1942
+ newSiblingNodeRecursive.keys = parentNode.keys.slice(mid + 1);
2020
1943
  const midValue = parentNode.values[mid];
2021
1944
  parentNode.values = parentNode.values.slice(0, mid);
2022
1945
  parentNode.keys = parentNode.keys.slice(0, mid + 1);
2023
1946
  for (const k of parentNode.keys) {
2024
- const n = this.getNode(k);
1947
+ const n = this._cloneNode(this.getNode(k));
2025
1948
  n.parent = parentNode.id;
2026
1949
  this._updateNode(n);
2027
1950
  }
2028
- for (const k of parentPointer.keys) {
2029
- const n = this.getNode(k);
2030
- n.parent = parentPointer.id;
1951
+ for (const k of newSiblingNodeRecursive.keys) {
1952
+ const n = this._cloneNode(this.getNode(k));
1953
+ n.parent = newSiblingNodeRecursive.id;
2031
1954
  this._updateNode(n);
2032
1955
  }
2033
1956
  this._updateNode(parentNode);
2034
- this._insertInParent(parentNode, midValue, parentPointer);
1957
+ this._insertInParent(parentNode, midValue, newSiblingNodeRecursive);
2035
1958
  }
2036
1959
  }
2037
1960
  insertableNode(value) {
@@ -2214,21 +2137,6 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2214
2137
  }
2215
2138
  return false;
2216
2139
  }
2217
- forceUpdate(id) {
2218
- if (id) {
2219
- this.nodes.delete(id);
2220
- this.getNode(id);
2221
- return 1;
2222
- }
2223
- const keys = Array.from(this.nodes.keys());
2224
- for (const key of keys) {
2225
- this.nodes.delete(key);
2226
- }
2227
- for (const key of keys) {
2228
- this.getNode(key);
2229
- }
2230
- return keys.length;
2231
- }
2232
2140
  get(key) {
2233
2141
  let node = this.leftestNode();
2234
2142
  while (true) {
@@ -2314,10 +2222,10 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2314
2222
  return map;
2315
2223
  }
2316
2224
  insert(key, value) {
2317
- const before = this.insertableNode(value);
2318
- this._insertAtLeaf(before, key, value);
2225
+ let before = this.insertableNode(value);
2226
+ before = this._insertAtLeaf(before, key, value);
2319
2227
  if (before.values.length === this.order) {
2320
- const after = this._createNode(
2228
+ let after = this._createNode(
2321
2229
  true,
2322
2230
  [],
2323
2231
  [],
@@ -2326,10 +2234,13 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2326
2234
  null
2327
2235
  );
2328
2236
  const mid = Math.ceil(this.order / 2) - 1;
2237
+ after = this._cloneNode(after);
2329
2238
  after.values = before.values.slice(mid + 1);
2330
2239
  after.keys = before.keys.slice(mid + 1);
2331
2240
  before.values = before.values.slice(0, mid + 1);
2332
2241
  before.keys = before.keys.slice(0, mid + 1);
2242
+ this._updateNode(before);
2243
+ this._updateNode(after);
2333
2244
  this._insertInParent(before, after.values[0], after);
2334
2245
  }
2335
2246
  }
@@ -2343,6 +2254,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2343
2254
  }
2344
2255
  }
2345
2256
  if (keyIndex !== -1) {
2257
+ node = this._cloneNode(node);
2346
2258
  node.keys.splice(keyIndex, 1);
2347
2259
  const valueIndex = keyIndex > 0 ? keyIndex - 1 : 0;
2348
2260
  node.values.splice(valueIndex, 1);
@@ -2352,7 +2264,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2352
2264
  if (this.rootId === node.id && node.keys.length === 1 && !node.leaf) {
2353
2265
  const keys = node.keys;
2354
2266
  this._deleteNode(node);
2355
- const newRoot = this.getNode(keys[0]);
2267
+ const newRoot = this._cloneNode(this.getNode(keys[0]));
2356
2268
  newRoot.parent = null;
2357
2269
  this._updateNode(newRoot);
2358
2270
  this._writeHead({
@@ -2360,17 +2272,17 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2360
2272
  order: this.order,
2361
2273
  data: this.strategy.head.data
2362
2274
  });
2363
- return;
2275
+ return node;
2364
2276
  } else if (this.rootId === node.id) {
2365
2277
  this._writeHead({
2366
2278
  root: node.id,
2367
2279
  order: this.order,
2368
2280
  data: this.strategy.head.data
2369
2281
  });
2370
- return;
2282
+ return node;
2371
2283
  } else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
2372
2284
  if (node.parent === null) {
2373
- return;
2285
+ return node;
2374
2286
  }
2375
2287
  let isPredecessor = false;
2376
2288
  let parentNode = this.getNode(node.parent);
@@ -2391,78 +2303,80 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2391
2303
  }
2392
2304
  }
2393
2305
  }
2394
- let pointer;
2306
+ let siblingNode;
2395
2307
  let guess;
2396
2308
  if (prevNode === null) {
2397
- pointer = nextNode;
2309
+ siblingNode = nextNode;
2398
2310
  guess = postValue;
2399
2311
  } else if (nextNode === null) {
2400
2312
  isPredecessor = true;
2401
- pointer = prevNode;
2313
+ siblingNode = prevNode;
2402
2314
  guess = prevValue;
2403
2315
  } else {
2404
2316
  if (node.values.length + nextNode.values.length < this.order) {
2405
- pointer = nextNode;
2317
+ siblingNode = nextNode;
2406
2318
  guess = postValue;
2407
2319
  } else {
2408
2320
  isPredecessor = true;
2409
- pointer = prevNode;
2321
+ siblingNode = prevNode;
2410
2322
  guess = prevValue;
2411
2323
  }
2412
2324
  }
2413
- if (!pointer) {
2414
- return;
2325
+ if (!siblingNode) {
2326
+ return node;
2415
2327
  }
2416
- if (node.values.length + pointer.values.length < this.order) {
2328
+ node = this._cloneNode(node);
2329
+ siblingNode = this._cloneNode(siblingNode);
2330
+ if (node.values.length + siblingNode.values.length < this.order) {
2417
2331
  if (!isPredecessor) {
2418
- const pTemp = pointer;
2419
- pointer = node;
2332
+ const pTemp = siblingNode;
2333
+ siblingNode = node;
2420
2334
  node = pTemp;
2421
2335
  }
2422
- pointer.keys.push(...node.keys);
2336
+ siblingNode.keys.push(...node.keys);
2423
2337
  if (!node.leaf) {
2424
- pointer.values.push(guess);
2338
+ siblingNode.values.push(guess);
2425
2339
  } else {
2426
- pointer.next = node.next;
2427
- if (pointer.next) {
2428
- const n = this.getNode(pointer.next);
2429
- n.prev = pointer.id;
2340
+ siblingNode.next = node.next;
2341
+ if (siblingNode.next) {
2342
+ const n = this._cloneNode(this.getNode(siblingNode.next));
2343
+ n.prev = siblingNode.id;
2430
2344
  this._updateNode(n);
2431
2345
  }
2432
2346
  }
2433
- pointer.values.push(...node.values);
2434
- if (!pointer.leaf) {
2435
- const keys = pointer.keys;
2347
+ siblingNode.values.push(...node.values);
2348
+ if (!siblingNode.leaf) {
2349
+ const keys = siblingNode.keys;
2436
2350
  for (const key2 of keys) {
2437
- const node2 = this.getNode(key2);
2438
- node2.parent = pointer.id;
2351
+ const node2 = this._cloneNode(this.getNode(key2));
2352
+ node2.parent = siblingNode.id;
2439
2353
  this._updateNode(node2);
2440
2354
  }
2441
2355
  }
2442
2356
  this._deleteNode(node);
2443
- this._updateNode(pointer);
2357
+ this._updateNode(siblingNode);
2444
2358
  this._deleteEntry(this.getNode(node.parent), node.id);
2445
2359
  } else {
2446
2360
  if (isPredecessor) {
2447
2361
  let pointerPm;
2448
2362
  let pointerKm;
2449
2363
  if (!node.leaf) {
2450
- pointerPm = pointer.keys.splice(-1)[0];
2451
- pointerKm = pointer.values.splice(-1)[0];
2364
+ pointerPm = siblingNode.keys.splice(-1)[0];
2365
+ pointerKm = siblingNode.values.splice(-1)[0];
2452
2366
  node.keys = [pointerPm, ...node.keys];
2453
2367
  node.values = [guess, ...node.values];
2454
- parentNode = this.getNode(node.parent);
2368
+ parentNode = this._cloneNode(this.getNode(node.parent));
2455
2369
  const nodeIndex = parentNode.keys.indexOf(node.id);
2456
2370
  if (nodeIndex > 0) {
2457
2371
  parentNode.values[nodeIndex - 1] = pointerKm;
2458
2372
  this._updateNode(parentNode);
2459
2373
  }
2460
2374
  } else {
2461
- pointerPm = pointer.keys.splice(-1)[0];
2462
- pointerKm = pointer.values.splice(-1)[0];
2375
+ pointerPm = siblingNode.keys.splice(-1)[0];
2376
+ pointerKm = siblingNode.values.splice(-1)[0];
2463
2377
  node.keys = [pointerPm, ...node.keys];
2464
2378
  node.values = [pointerKm, ...node.values];
2465
- parentNode = this.getNode(node.parent);
2379
+ parentNode = this._cloneNode(this.getNode(node.parent));
2466
2380
  const nodeIndex = parentNode.keys.indexOf(node.id);
2467
2381
  if (nodeIndex > 0) {
2468
2382
  parentNode.values[nodeIndex - 1] = pointerKm;
@@ -2470,61 +2384,62 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2470
2384
  }
2471
2385
  }
2472
2386
  this._updateNode(node);
2473
- this._updateNode(pointer);
2387
+ this._updateNode(siblingNode);
2474
2388
  } else {
2475
2389
  let pointerP0;
2476
2390
  let pointerK0;
2477
2391
  if (!node.leaf) {
2478
- pointerP0 = pointer.keys.splice(0, 1)[0];
2479
- pointerK0 = pointer.values.splice(0, 1)[0];
2392
+ pointerP0 = siblingNode.keys.splice(0, 1)[0];
2393
+ pointerK0 = siblingNode.values.splice(0, 1)[0];
2480
2394
  node.keys = [...node.keys, pointerP0];
2481
2395
  node.values = [...node.values, guess];
2482
- parentNode = this.getNode(node.parent);
2483
- const pointerIndex = parentNode.keys.indexOf(pointer.id);
2396
+ parentNode = this._cloneNode(this.getNode(node.parent));
2397
+ const pointerIndex = parentNode.keys.indexOf(siblingNode.id);
2484
2398
  if (pointerIndex > 0) {
2485
2399
  parentNode.values[pointerIndex - 1] = pointerK0;
2486
2400
  this._updateNode(parentNode);
2487
2401
  }
2488
2402
  } else {
2489
- pointerP0 = pointer.keys.splice(0, 1)[0];
2490
- pointerK0 = pointer.values.splice(0, 1)[0];
2403
+ pointerP0 = siblingNode.keys.splice(0, 1)[0];
2404
+ pointerK0 = siblingNode.values.splice(0, 1)[0];
2491
2405
  node.keys = [...node.keys, pointerP0];
2492
2406
  node.values = [...node.values, pointerK0];
2493
- parentNode = this.getNode(node.parent);
2494
- const pointerIndex = parentNode.keys.indexOf(pointer.id);
2407
+ parentNode = this._cloneNode(this.getNode(node.parent));
2408
+ const pointerIndex = parentNode.keys.indexOf(siblingNode.id);
2495
2409
  if (pointerIndex > 0) {
2496
- parentNode.values[pointerIndex - 1] = pointer.values[0];
2410
+ parentNode.values[pointerIndex - 1] = siblingNode.values[0];
2497
2411
  this._updateNode(parentNode);
2498
2412
  }
2499
2413
  }
2500
2414
  this._updateNode(node);
2501
- this._updateNode(pointer);
2415
+ this._updateNode(siblingNode);
2502
2416
  }
2503
- if (!pointer.leaf) {
2504
- for (const key2 of pointer.keys) {
2505
- const n = this.getNode(key2);
2506
- n.parent = pointer.id;
2417
+ if (!siblingNode.leaf) {
2418
+ for (const key2 of siblingNode.keys) {
2419
+ const n = this._cloneNode(this.getNode(key2));
2420
+ n.parent = siblingNode.id;
2507
2421
  this._updateNode(n);
2508
2422
  }
2509
2423
  }
2510
2424
  if (!node.leaf) {
2511
2425
  for (const key2 of node.keys) {
2512
- const n = this.getNode(key2);
2426
+ const n = this._cloneNode(this.getNode(key2));
2513
2427
  n.parent = node.id;
2514
2428
  this._updateNode(n);
2515
2429
  }
2516
2430
  }
2517
2431
  if (!parentNode.leaf) {
2518
2432
  for (const key2 of parentNode.keys) {
2519
- const n = this.getNode(key2);
2433
+ const n = this._cloneNode(this.getNode(key2));
2520
2434
  n.parent = parentNode.id;
2521
2435
  this._updateNode(n);
2522
2436
  }
2523
2437
  }
2524
2438
  }
2525
2439
  } else {
2526
- this._updateNode(node);
2440
+ this._updateNode(this._cloneNode(node));
2527
2441
  }
2442
+ return node;
2528
2443
  }
2529
2444
  delete(key, value) {
2530
2445
  let node = this.insertableNodeByPrimary(value);
@@ -2537,13 +2452,15 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2537
2452
  const keys = node.keys[i];
2538
2453
  const keyIndex = keys.indexOf(key);
2539
2454
  if (keyIndex !== -1) {
2540
- keys.splice(keyIndex, 1);
2541
- if (keys.length === 0) {
2455
+ node = this._cloneNode(node);
2456
+ const freshKeys = node.keys[i];
2457
+ freshKeys.splice(keyIndex, 1);
2458
+ if (freshKeys.length === 0) {
2542
2459
  node.keys.splice(i, 1);
2543
2460
  node.values.splice(i, 1);
2544
2461
  }
2545
2462
  this._updateNode(node);
2546
- this._deleteEntry(node, key);
2463
+ node = this._deleteEntry(node, key);
2547
2464
  found = true;
2548
2465
  break;
2549
2466
  }
@@ -2586,15 +2503,6 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2586
2503
  }
2587
2504
  }
2588
2505
  if (result.success) {
2589
- for (const r of result.created) {
2590
- this.nodes.set(r.key, r.data);
2591
- }
2592
- for (const r of result.updated) {
2593
- this.nodes.set(r.key, r.data);
2594
- }
2595
- for (const r of result.deleted) {
2596
- this.nodes.delete(r.key);
2597
- }
2598
2506
  }
2599
2507
  }
2600
2508
  return result;
@@ -2638,7 +2546,9 @@ var BPTreeMVCCStrategySync = class extends SyncMVCCStrategy {
2638
2546
  };
2639
2547
  var BPTreeSync = class extends BPTreeSyncTransaction {
2640
2548
  constructor(strategy, comparator, option) {
2641
- const mvccRoot = new SyncMVCCTransaction(new BPTreeMVCCStrategySync(strategy));
2549
+ const mvccRoot = new SyncMVCCTransaction(new BPTreeMVCCStrategySync(strategy), {
2550
+ cacheCapacity: option?.capacity ?? void 0
2551
+ });
2642
2552
  super(
2643
2553
  null,
2644
2554
  mvccRoot,
@@ -2961,9 +2871,6 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
2961
2871
  });
2962
2872
  }
2963
2873
  async getNode(id) {
2964
- if (this.nodes.has(id)) {
2965
- return this.nodes.get(id);
2966
- }
2967
2874
  return await this.mvcc.read(id);
2968
2875
  }
2969
2876
  /**
@@ -2980,24 +2887,31 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
2980
2887
  next,
2981
2888
  prev
2982
2889
  };
2890
+ const head = await this._readHead();
2891
+ if (head) {
2892
+ await this._writeHead({
2893
+ root: head.root,
2894
+ order: head.order,
2895
+ data: this.strategy.head.data
2896
+ });
2897
+ }
2983
2898
  await this.mvcc.create(id, node);
2984
- this.nodes.set(id, node);
2985
2899
  return node;
2986
2900
  }
2987
2901
  async _updateNode(node) {
2902
+ if (this.mvcc.isDeleted(node.id)) {
2903
+ return;
2904
+ }
2988
2905
  await this.mvcc.write(node.id, node);
2989
- this.nodes.set(node.id, node);
2990
2906
  }
2991
2907
  async _deleteNode(node) {
2908
+ if (this.mvcc.isDeleted(node.id)) {
2909
+ return;
2910
+ }
2992
2911
  await this.mvcc.delete(node.id);
2993
- this.nodes.delete(node.id);
2994
2912
  }
2995
2913
  async _readHead() {
2996
- if (this.nodes.has("__HEAD__")) {
2997
- return this.nodes.get("__HEAD__") ?? null;
2998
- }
2999
- const head = await this.mvcc.read("__HEAD__");
3000
- return head ?? null;
2914
+ return await this.mvcc.read("__HEAD__");
3001
2915
  }
3002
2916
  async _writeHead(head) {
3003
2917
  if (!await this.mvcc.exists("__HEAD__")) {
@@ -3005,49 +2919,56 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3005
2919
  } else {
3006
2920
  await this.mvcc.write("__HEAD__", head);
3007
2921
  }
3008
- this.nodes.set("__HEAD__", head);
3009
2922
  this.rootId = head.root;
3010
2923
  }
3011
2924
  async _insertAtLeaf(node, key, value) {
3012
- if (node.values.length) {
3013
- for (let i = 0, len = node.values.length; i < len; i++) {
3014
- const nValue = node.values[i];
2925
+ let leaf = node;
2926
+ if (leaf.values.length) {
2927
+ for (let i = 0, len = leaf.values.length; i < len; i++) {
2928
+ const nValue = leaf.values[i];
3015
2929
  if (this.comparator.isSame(value, nValue)) {
3016
- const keys = node.keys[i];
2930
+ const keys = leaf.keys[i];
3017
2931
  if (keys.includes(key)) {
3018
2932
  break;
3019
2933
  }
3020
- keys.push(key);
3021
- await this._updateNode(node);
3022
- return;
2934
+ leaf = this._cloneNode(leaf);
2935
+ leaf.keys[i].push(key);
2936
+ await this._updateNode(leaf);
2937
+ return leaf;
3023
2938
  } else if (this.comparator.isLower(value, nValue)) {
3024
- node.values.splice(i, 0, value);
3025
- node.keys.splice(i, 0, [key]);
3026
- await this._updateNode(node);
3027
- return;
3028
- } else if (i + 1 === node.values.length) {
3029
- node.values.push(value);
3030
- node.keys.push([key]);
3031
- await this._updateNode(node);
3032
- return;
2939
+ leaf = this._cloneNode(leaf);
2940
+ leaf.values.splice(i, 0, value);
2941
+ leaf.keys.splice(i, 0, [key]);
2942
+ await this._updateNode(leaf);
2943
+ return leaf;
2944
+ } else if (i + 1 === leaf.values.length) {
2945
+ leaf = this._cloneNode(leaf);
2946
+ leaf.values.push(value);
2947
+ leaf.keys.push([key]);
2948
+ await this._updateNode(leaf);
2949
+ return leaf;
3033
2950
  }
3034
2951
  }
3035
2952
  } else {
3036
- node.values = [value];
3037
- node.keys = [[key]];
3038
- await this._updateNode(node);
3039
- return;
2953
+ leaf = this._cloneNode(leaf);
2954
+ leaf.values = [value];
2955
+ leaf.keys = [[key]];
2956
+ await this._updateNode(leaf);
2957
+ return leaf;
3040
2958
  }
2959
+ return leaf;
3041
2960
  }
3042
- async _insertInParent(node, value, pointer) {
2961
+ async _insertInParent(node, value, newSiblingNode) {
3043
2962
  if (this.rootId === node.id) {
3044
- const root = await this._createNode(false, [node.id, pointer.id], [value]);
2963
+ node = this._cloneNode(node);
2964
+ newSiblingNode = this._cloneNode(newSiblingNode);
2965
+ const root = await this._createNode(false, [node.id, newSiblingNode.id], [value]);
3045
2966
  this.rootId = root.id;
3046
2967
  node.parent = root.id;
3047
- pointer.parent = root.id;
3048
- if (pointer.leaf) {
3049
- node.next = pointer.id;
3050
- pointer.prev = node.id;
2968
+ newSiblingNode.parent = root.id;
2969
+ if (newSiblingNode.leaf) {
2970
+ node.next = newSiblingNode.id;
2971
+ newSiblingNode.prev = node.id;
3051
2972
  }
3052
2973
  await this._writeHead({
3053
2974
  root: root.id,
@@ -3055,53 +2976,54 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3055
2976
  data: this.strategy.head.data
3056
2977
  });
3057
2978
  await this._updateNode(node);
3058
- await this._updateNode(pointer);
2979
+ await this._updateNode(newSiblingNode);
3059
2980
  return;
3060
2981
  }
3061
- const parentNode = await this.getNode(node.parent);
2982
+ const parentNode = this._cloneNode(await this.getNode(node.parent));
3062
2983
  const nodeIndex = parentNode.keys.indexOf(node.id);
3063
2984
  if (nodeIndex === -1) {
3064
2985
  throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
3065
2986
  }
3066
2987
  parentNode.values.splice(nodeIndex, 0, value);
3067
- parentNode.keys.splice(nodeIndex + 1, 0, pointer.id);
3068
- pointer.parent = parentNode.id;
3069
- if (pointer.leaf) {
3070
- const leftSibling = node;
2988
+ parentNode.keys.splice(nodeIndex + 1, 0, newSiblingNode.id);
2989
+ newSiblingNode = this._cloneNode(newSiblingNode);
2990
+ newSiblingNode.parent = parentNode.id;
2991
+ if (newSiblingNode.leaf) {
2992
+ const leftSibling = this._cloneNode(node);
3071
2993
  const oldNextId = leftSibling.next;
3072
- pointer.prev = leftSibling.id;
3073
- pointer.next = oldNextId;
3074
- leftSibling.next = pointer.id;
2994
+ newSiblingNode.prev = leftSibling.id;
2995
+ newSiblingNode.next = oldNextId;
2996
+ leftSibling.next = newSiblingNode.id;
3075
2997
  await this._updateNode(leftSibling);
3076
2998
  if (oldNextId) {
3077
- const oldNext = await this.getNode(oldNextId);
3078
- oldNext.prev = pointer.id;
2999
+ const oldNext = this._cloneNode(await this.getNode(oldNextId));
3000
+ oldNext.prev = newSiblingNode.id;
3079
3001
  await this._updateNode(oldNext);
3080
3002
  }
3081
3003
  }
3082
3004
  await this._updateNode(parentNode);
3083
- await this._updateNode(pointer);
3005
+ await this._updateNode(newSiblingNode);
3084
3006
  if (parentNode.keys.length > this.order) {
3085
- const parentPointer = await this._createNode(false, [], []);
3086
- parentPointer.parent = parentNode.parent;
3007
+ const newSiblingNodeRecursive = await this._createNode(false, [], []);
3008
+ newSiblingNodeRecursive.parent = parentNode.parent;
3087
3009
  const mid = Math.ceil(this.order / 2) - 1;
3088
- parentPointer.values = parentNode.values.slice(mid + 1);
3089
- parentPointer.keys = parentNode.keys.slice(mid + 1);
3010
+ newSiblingNodeRecursive.values = parentNode.values.slice(mid + 1);
3011
+ newSiblingNodeRecursive.keys = parentNode.keys.slice(mid + 1);
3090
3012
  const midValue = parentNode.values[mid];
3091
3013
  parentNode.values = parentNode.values.slice(0, mid);
3092
3014
  parentNode.keys = parentNode.keys.slice(0, mid + 1);
3093
3015
  for (const k of parentNode.keys) {
3094
- const n = await this.getNode(k);
3016
+ const n = this._cloneNode(await this.getNode(k));
3095
3017
  n.parent = parentNode.id;
3096
3018
  await this._updateNode(n);
3097
3019
  }
3098
- for (const k of parentPointer.keys) {
3099
- const n = await this.getNode(k);
3100
- n.parent = parentPointer.id;
3020
+ for (const k of newSiblingNodeRecursive.keys) {
3021
+ const n = this._cloneNode(await this.getNode(k));
3022
+ n.parent = newSiblingNodeRecursive.id;
3101
3023
  await this._updateNode(n);
3102
3024
  }
3103
3025
  await this._updateNode(parentNode);
3104
- await this._insertInParent(parentNode, midValue, parentPointer);
3026
+ await this._insertInParent(parentNode, midValue, newSiblingNodeRecursive);
3105
3027
  }
3106
3028
  }
3107
3029
  async insertableNode(value) {
@@ -3290,21 +3212,6 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3290
3212
  }
3291
3213
  return false;
3292
3214
  }
3293
- async forceUpdate(id) {
3294
- if (id) {
3295
- this.nodes.delete(id);
3296
- await this.getNode(id);
3297
- return 1;
3298
- }
3299
- const keys = Array.from(this.nodes.keys());
3300
- for (const key of keys) {
3301
- this.nodes.delete(key);
3302
- }
3303
- for (const key of keys) {
3304
- await this.getNode(key);
3305
- }
3306
- return keys.length;
3307
- }
3308
3215
  async get(key) {
3309
3216
  let node = await this.leftestNode();
3310
3217
  while (true) {
@@ -3391,10 +3298,10 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3391
3298
  }
3392
3299
  async insert(key, value) {
3393
3300
  return this.writeLock(0, async () => {
3394
- const before = await this.insertableNode(value);
3395
- await this._insertAtLeaf(before, key, value);
3301
+ let before = await this.insertableNode(value);
3302
+ before = await this._insertAtLeaf(before, key, value);
3396
3303
  if (before.values.length === this.order) {
3397
- const after = await this._createNode(
3304
+ let after = await this._createNode(
3398
3305
  true,
3399
3306
  [],
3400
3307
  [],
@@ -3403,10 +3310,13 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3403
3310
  null
3404
3311
  );
3405
3312
  const mid = Math.ceil(this.order / 2) - 1;
3313
+ after = this._cloneNode(after);
3406
3314
  after.values = before.values.slice(mid + 1);
3407
3315
  after.keys = before.keys.slice(mid + 1);
3408
3316
  before.values = before.values.slice(0, mid + 1);
3409
3317
  before.keys = before.keys.slice(0, mid + 1);
3318
+ await this._updateNode(before);
3319
+ await this._updateNode(after);
3410
3320
  await this._insertInParent(before, after.values[0], after);
3411
3321
  }
3412
3322
  });
@@ -3421,6 +3331,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3421
3331
  }
3422
3332
  }
3423
3333
  if (keyIndex !== -1) {
3334
+ node = this._cloneNode(node);
3424
3335
  node.keys.splice(keyIndex, 1);
3425
3336
  const valueIndex = keyIndex > 0 ? keyIndex - 1 : 0;
3426
3337
  node.values.splice(valueIndex, 1);
@@ -3430,7 +3341,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3430
3341
  if (this.rootId === node.id && node.keys.length === 1 && !node.leaf) {
3431
3342
  const keys = node.keys;
3432
3343
  this._deleteNode(node);
3433
- const newRoot = await this.getNode(keys[0]);
3344
+ const newRoot = this._cloneNode(await this.getNode(keys[0]));
3434
3345
  newRoot.parent = null;
3435
3346
  await this._updateNode(newRoot);
3436
3347
  await this._writeHead({
@@ -3438,14 +3349,17 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3438
3349
  order: this.order,
3439
3350
  data: this.strategy.head.data
3440
3351
  });
3441
- return;
3352
+ return node;
3442
3353
  } else if (this.rootId === node.id) {
3443
- const root = await this.getNode(this.rootId);
3444
- await this._updateNode(root);
3445
- return;
3354
+ await this._writeHead({
3355
+ root: node.id,
3356
+ order: this.order,
3357
+ data: this.strategy.head.data
3358
+ });
3359
+ return node;
3446
3360
  } else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
3447
3361
  if (node.parent === null) {
3448
- return;
3362
+ return node;
3449
3363
  }
3450
3364
  let isPredecessor = false;
3451
3365
  let parentNode = await this.getNode(node.parent);
@@ -3466,78 +3380,80 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3466
3380
  }
3467
3381
  }
3468
3382
  }
3469
- let pointer;
3383
+ let siblingNode;
3470
3384
  let guess;
3471
3385
  if (prevNode === null) {
3472
- pointer = nextNode;
3386
+ siblingNode = nextNode;
3473
3387
  guess = postValue;
3474
3388
  } else if (nextNode === null) {
3475
3389
  isPredecessor = true;
3476
- pointer = prevNode;
3390
+ siblingNode = prevNode;
3477
3391
  guess = prevValue;
3478
3392
  } else {
3479
3393
  if (node.values.length + nextNode.values.length < this.order) {
3480
- pointer = nextNode;
3394
+ siblingNode = nextNode;
3481
3395
  guess = postValue;
3482
3396
  } else {
3483
3397
  isPredecessor = true;
3484
- pointer = prevNode;
3398
+ siblingNode = prevNode;
3485
3399
  guess = prevValue;
3486
3400
  }
3487
3401
  }
3488
- if (!pointer) {
3489
- return;
3402
+ if (!siblingNode) {
3403
+ return node;
3490
3404
  }
3491
- if (node.values.length + pointer.values.length < this.order) {
3405
+ node = this._cloneNode(node);
3406
+ siblingNode = this._cloneNode(siblingNode);
3407
+ if (node.values.length + siblingNode.values.length < this.order) {
3492
3408
  if (!isPredecessor) {
3493
- const pTemp = pointer;
3494
- pointer = node;
3409
+ const pTemp = siblingNode;
3410
+ siblingNode = node;
3495
3411
  node = pTemp;
3496
3412
  }
3497
- pointer.keys.push(...node.keys);
3413
+ siblingNode.keys.push(...node.keys);
3498
3414
  if (!node.leaf) {
3499
- pointer.values.push(guess);
3415
+ siblingNode.values.push(guess);
3500
3416
  } else {
3501
- pointer.next = node.next;
3502
- if (pointer.next) {
3503
- const n = await this.getNode(pointer.next);
3504
- n.prev = pointer.id;
3417
+ siblingNode.next = node.next;
3418
+ if (siblingNode.next) {
3419
+ const n = this._cloneNode(await this.getNode(siblingNode.next));
3420
+ n.prev = siblingNode.id;
3505
3421
  await this._updateNode(n);
3506
3422
  }
3507
3423
  }
3508
- pointer.values.push(...node.values);
3509
- if (!pointer.leaf) {
3510
- const keys = pointer.keys;
3424
+ siblingNode.values.push(...node.values);
3425
+ if (!siblingNode.leaf) {
3426
+ const keys = siblingNode.keys;
3511
3427
  for (const key2 of keys) {
3512
- const node2 = await this.getNode(key2);
3513
- node2.parent = pointer.id;
3428
+ const node2 = this._cloneNode(await this.getNode(key2));
3429
+ node2.parent = siblingNode.id;
3514
3430
  await this._updateNode(node2);
3515
3431
  }
3516
3432
  }
3517
3433
  this._deleteNode(node);
3518
- await this._updateNode(pointer);
3434
+ await this._updateNode(siblingNode);
3519
3435
  await this._deleteEntry(await this.getNode(node.parent), node.id);
3520
3436
  } else {
3521
3437
  if (isPredecessor) {
3522
3438
  let pointerPm;
3523
3439
  let pointerKm;
3524
3440
  if (!node.leaf) {
3525
- pointerPm = pointer.keys.splice(-1)[0];
3526
- pointerKm = pointer.values.splice(-1)[0];
3441
+ pointerPm = siblingNode.keys.splice(-1)[0];
3442
+ pointerKm = siblingNode.values.splice(-1)[0];
3527
3443
  node.keys = [pointerPm, ...node.keys];
3528
3444
  node.values = [guess, ...node.values];
3529
- parentNode = await this.getNode(node.parent);
3445
+ parentNode = this._cloneNode(await this.getNode(node.parent));
3530
3446
  const nodeIndex = parentNode.keys.indexOf(node.id);
3531
3447
  if (nodeIndex > 0) {
3532
3448
  parentNode.values[nodeIndex - 1] = pointerKm;
3533
3449
  await this._updateNode(parentNode);
3534
3450
  }
3535
3451
  } else {
3536
- pointerPm = pointer.keys.splice(-1)[0];
3537
- pointerKm = pointer.values.splice(-1)[0];
3452
+ pointerPm = siblingNode.keys.splice(-1)[0];
3453
+ pointerKm = siblingNode.values.splice(-1)[0];
3538
3454
  node.keys = [pointerPm, ...node.keys];
3539
3455
  node.values = [pointerKm, ...node.values];
3540
- parentNode = await this.getNode(node.parent);
3456
+ parentNode = this._cloneNode(await this.getNode(node.parent));
3541
3457
  const nodeIndex = parentNode.keys.indexOf(node.id);
3542
3458
  if (nodeIndex > 0) {
3543
3459
  parentNode.values[nodeIndex - 1] = pointerKm;
@@ -3545,61 +3461,62 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3545
3461
  }
3546
3462
  }
3547
3463
  await this._updateNode(node);
3548
- await this._updateNode(pointer);
3464
+ await this._updateNode(siblingNode);
3549
3465
  } else {
3550
3466
  let pointerP0;
3551
3467
  let pointerK0;
3552
3468
  if (!node.leaf) {
3553
- pointerP0 = pointer.keys.splice(0, 1)[0];
3554
- pointerK0 = pointer.values.splice(0, 1)[0];
3469
+ pointerP0 = siblingNode.keys.splice(0, 1)[0];
3470
+ pointerK0 = siblingNode.values.splice(0, 1)[0];
3555
3471
  node.keys = [...node.keys, pointerP0];
3556
3472
  node.values = [...node.values, guess];
3557
- parentNode = await this.getNode(node.parent);
3558
- const pointerIndex = parentNode.keys.indexOf(pointer.id);
3473
+ parentNode = this._cloneNode(await this.getNode(node.parent));
3474
+ const pointerIndex = parentNode.keys.indexOf(siblingNode.id);
3559
3475
  if (pointerIndex > 0) {
3560
3476
  parentNode.values[pointerIndex - 1] = pointerK0;
3561
3477
  await this._updateNode(parentNode);
3562
3478
  }
3563
3479
  } else {
3564
- pointerP0 = pointer.keys.splice(0, 1)[0];
3565
- pointerK0 = pointer.values.splice(0, 1)[0];
3480
+ pointerP0 = siblingNode.keys.splice(0, 1)[0];
3481
+ pointerK0 = siblingNode.values.splice(0, 1)[0];
3566
3482
  node.keys = [...node.keys, pointerP0];
3567
3483
  node.values = [...node.values, pointerK0];
3568
- parentNode = await this.getNode(node.parent);
3569
- const pointerIndex = parentNode.keys.indexOf(pointer.id);
3484
+ parentNode = this._cloneNode(await this.getNode(node.parent));
3485
+ const pointerIndex = parentNode.keys.indexOf(siblingNode.id);
3570
3486
  if (pointerIndex > 0) {
3571
- parentNode.values[pointerIndex - 1] = pointer.values[0];
3487
+ parentNode.values[pointerIndex - 1] = siblingNode.values[0];
3572
3488
  await this._updateNode(parentNode);
3573
3489
  }
3574
3490
  }
3575
3491
  await this._updateNode(node);
3576
- await this._updateNode(pointer);
3492
+ await this._updateNode(siblingNode);
3577
3493
  }
3578
- if (!pointer.leaf) {
3579
- for (const key2 of pointer.keys) {
3580
- const n = await this.getNode(key2);
3581
- n.parent = pointer.id;
3494
+ if (!siblingNode.leaf) {
3495
+ for (const key2 of siblingNode.keys) {
3496
+ const n = this._cloneNode(await this.getNode(key2));
3497
+ n.parent = siblingNode.id;
3582
3498
  await this._updateNode(n);
3583
3499
  }
3584
3500
  }
3585
3501
  if (!node.leaf) {
3586
3502
  for (const key2 of node.keys) {
3587
- const n = await this.getNode(key2);
3503
+ const n = this._cloneNode(await this.getNode(key2));
3588
3504
  n.parent = node.id;
3589
3505
  await this._updateNode(n);
3590
3506
  }
3591
3507
  }
3592
3508
  if (!parentNode.leaf) {
3593
3509
  for (const key2 of parentNode.keys) {
3594
- const n = await this.getNode(key2);
3510
+ const n = this._cloneNode(await this.getNode(key2));
3595
3511
  n.parent = parentNode.id;
3596
3512
  await this._updateNode(n);
3597
3513
  }
3598
3514
  }
3599
3515
  }
3600
3516
  } else {
3601
- await this._updateNode(node);
3517
+ await this._updateNode(this._cloneNode(node));
3602
3518
  }
3519
+ return node;
3603
3520
  }
3604
3521
  async delete(key, value) {
3605
3522
  return this.writeLock(0, async () => {
@@ -3613,13 +3530,15 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3613
3530
  const keys = node.keys[i];
3614
3531
  const keyIndex = keys.indexOf(key);
3615
3532
  if (keyIndex !== -1) {
3616
- keys.splice(keyIndex, 1);
3617
- if (keys.length === 0) {
3533
+ node = this._cloneNode(node);
3534
+ const freshKeys = node.keys[i];
3535
+ freshKeys.splice(keyIndex, 1);
3536
+ if (freshKeys.length === 0) {
3618
3537
  node.keys.splice(i, 1);
3619
3538
  node.values.splice(i, 1);
3620
3539
  }
3621
3540
  await this._updateNode(node);
3622
- await this._deleteEntry(node, key);
3541
+ node = await this._deleteEntry(node, key);
3623
3542
  found = true;
3624
3543
  break;
3625
3544
  }
@@ -3662,21 +3581,10 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3662
3581
  this.rootTx.rootId = this.rootId;
3663
3582
  }
3664
3583
  }
3665
- if (result.success) {
3666
- for (const r of result.created) {
3667
- this.nodes.set(r.key, r.data);
3668
- }
3669
- for (const r of result.updated) {
3670
- this.nodes.set(r.key, r.data);
3671
- }
3672
- for (const r of result.deleted) {
3673
- this.nodes.delete(r.key);
3674
- }
3675
- }
3676
3584
  }
3677
3585
  return result;
3678
3586
  }
3679
- rollback() {
3587
+ async rollback() {
3680
3588
  return this.mvcc.rollback();
3681
3589
  }
3682
3590
  };
@@ -3715,7 +3623,9 @@ var BPTreeMVCCStrategyAsync = class extends AsyncMVCCStrategy {
3715
3623
  };
3716
3624
  var BPTreeAsync = class extends BPTreeAsyncTransaction {
3717
3625
  constructor(strategy, comparator, option) {
3718
- const mvccRoot = new AsyncMVCCTransaction(new BPTreeMVCCStrategyAsync(strategy));
3626
+ const mvccRoot = new AsyncMVCCTransaction(new BPTreeMVCCStrategyAsync(strategy), {
3627
+ cacheCapacity: option?.capacity ?? void 0
3628
+ });
3719
3629
  super(
3720
3630
  null,
3721
3631
  mvccRoot,
@@ -4267,7 +4177,7 @@ var LRUMap2 = class {
4267
4177
  this.tail = null;
4268
4178
  }
4269
4179
  };
4270
- var CacheEntanglement2 = class {
4180
+ var CacheEntanglement = class {
4271
4181
  creation;
4272
4182
  beforeUpdateHook;
4273
4183
  capacity;
@@ -4368,7 +4278,7 @@ var CacheEntanglement2 = class {
4368
4278
  }
4369
4279
  }
4370
4280
  };
4371
- var CacheData2 = class _CacheData2 {
4281
+ var CacheData = class _CacheData {
4372
4282
  static StructuredClone = globalThis.structuredClone.bind(globalThis);
4373
4283
  _value;
4374
4284
  constructor(value) {
@@ -4408,11 +4318,11 @@ var CacheData2 = class _CacheData2 {
4408
4318
  return Object.assign({}, this.raw);
4409
4319
  case "deep-copy":
4410
4320
  default:
4411
- return _CacheData2.StructuredClone(this.raw);
4321
+ return _CacheData.StructuredClone(this.raw);
4412
4322
  }
4413
4323
  }
4414
4324
  };
4415
- var CacheEntanglementSync2 = class extends CacheEntanglement2 {
4325
+ var CacheEntanglementSync = class extends CacheEntanglement {
4416
4326
  constructor(creation, option) {
4417
4327
  super(creation, option);
4418
4328
  }
@@ -4442,7 +4352,7 @@ var CacheEntanglementSync2 = class extends CacheEntanglement2 {
4442
4352
  const dependencyValue = dependency.recache(key) ?? dependency.recache(dependencyKey);
4443
4353
  resolved[name] = dependencyValue;
4444
4354
  }
4445
- const value = new CacheData2(this.creation(key, resolved, ...parameter));
4355
+ const value = new CacheData(this.creation(key, resolved, ...parameter));
4446
4356
  this.updateRequirements.delete(key);
4447
4357
  this.parameters.set(key, parameter);
4448
4358
  this.caches.set(key, value);
@@ -4466,7 +4376,7 @@ var CacheEntanglementSync2 = class extends CacheEntanglement2 {
4466
4376
  return this.caches.get(key);
4467
4377
  }
4468
4378
  };
4469
- var CacheEntanglementAsync = class extends CacheEntanglement2 {
4379
+ var CacheEntanglementAsync = class extends CacheEntanglement {
4470
4380
  constructor(creation, option) {
4471
4381
  super(creation, option);
4472
4382
  }
@@ -4496,7 +4406,7 @@ var CacheEntanglementAsync = class extends CacheEntanglement2 {
4496
4406
  const dependencyValue = await dependency.recache(key) ?? await dependency.recache(dependencyKey);
4497
4407
  resolved[name] = dependencyValue;
4498
4408
  }
4499
- const value = new CacheData2(await this.creation(key, resolved, ...parameter));
4409
+ const value = new CacheData(await this.creation(key, resolved, ...parameter));
4500
4410
  this.updateRequirements.delete(key);
4501
4411
  this.parameters.set(key, parameter);
4502
4412
  this.caches.set(key, value);
@@ -4601,6 +4511,42 @@ var InvertedWeakMap = class {
4601
4511
  // node_modules/mvcc-api/dist/esm/index.mjs
4602
4512
  var MVCCStrategy2 = class {
4603
4513
  };
4514
+ var LRUMap3 = class {
4515
+ cache = /* @__PURE__ */ new Map();
4516
+ capacity;
4517
+ constructor(capacity) {
4518
+ this.capacity = capacity;
4519
+ }
4520
+ get(key) {
4521
+ if (!this.cache.has(key)) return void 0;
4522
+ const value = this.cache.get(key);
4523
+ this.cache.delete(key);
4524
+ this.cache.set(key, value);
4525
+ return value;
4526
+ }
4527
+ set(key, value) {
4528
+ if (this.cache.has(key)) {
4529
+ this.cache.delete(key);
4530
+ } else if (this.cache.size >= this.capacity) {
4531
+ const oldestKey = this.cache.keys().next().value;
4532
+ if (oldestKey !== void 0) this.cache.delete(oldestKey);
4533
+ }
4534
+ this.cache.set(key, value);
4535
+ return this;
4536
+ }
4537
+ has(key) {
4538
+ return this.cache.has(key);
4539
+ }
4540
+ delete(key) {
4541
+ return this.cache.delete(key);
4542
+ }
4543
+ clear() {
4544
+ this.cache.clear();
4545
+ }
4546
+ get size() {
4547
+ return this.cache.size;
4548
+ }
4549
+ };
4604
4550
  var MVCCTransaction2 = class {
4605
4551
  committed;
4606
4552
  snapshotVersion;
@@ -4608,7 +4554,6 @@ var MVCCTransaction2 = class {
4608
4554
  writeBuffer;
4609
4555
  deleteBuffer;
4610
4556
  createdKeys;
4611
- // create()로 생성된 키 추적
4612
4557
  deletedValues;
4613
4558
  // delete 시 삭제 전 값 저장
4614
4559
  originallyExisted;
@@ -4627,7 +4572,8 @@ var MVCCTransaction2 = class {
4627
4572
  versionIndex = /* @__PURE__ */ new Map();
4628
4573
  deletedCache = /* @__PURE__ */ new Map();
4629
4574
  activeTransactions = /* @__PURE__ */ new Set();
4630
- constructor(strategy, parent, snapshotVersion) {
4575
+ diskCache;
4576
+ constructor(strategy, options, parent, snapshotVersion) {
4631
4577
  this.snapshotVersion = snapshotVersion ?? 0;
4632
4578
  this.writeBuffer = /* @__PURE__ */ new Map();
4633
4579
  this.deleteBuffer = /* @__PURE__ */ new Set();
@@ -4642,6 +4588,7 @@ var MVCCTransaction2 = class {
4642
4588
  this.snapshotLocalVersion = parent.localVersion;
4643
4589
  this.strategy = void 0;
4644
4590
  this.root = parent.root;
4591
+ this.diskCache = parent.diskCache;
4645
4592
  } else {
4646
4593
  if (!strategy) throw new Error("Root Transaction must get Strategy");
4647
4594
  this.strategy = strategy;
@@ -4649,8 +4596,13 @@ var MVCCTransaction2 = class {
4649
4596
  this.localVersion = 0;
4650
4597
  this.snapshotLocalVersion = 0;
4651
4598
  this.root = this;
4599
+ this.diskCache = new LRUMap3(options?.cacheCapacity ?? 1e3);
4652
4600
  }
4653
4601
  }
4602
+ /**
4603
+ * Checks if the transaction is a root transaction.
4604
+ * @returns True if the transaction is a root transaction, false otherwise.
4605
+ */
4654
4606
  isRoot() {
4655
4607
  return !this.parent;
4656
4608
  }
@@ -4667,7 +4619,22 @@ var MVCCTransaction2 = class {
4667
4619
  }
4668
4620
  return false;
4669
4621
  }
4670
- // --- Internal buffer manipulation helpers ---
4622
+ /**
4623
+ * Checks if a key was written in this transaction.
4624
+ * @param key The key to check.
4625
+ * @returns True if the key was written in this transaction, false otherwise.
4626
+ */
4627
+ isWrote(key) {
4628
+ return this.writeBuffer.has(key);
4629
+ }
4630
+ /**
4631
+ * Checks if a key was deleted in this transaction.
4632
+ * @param key The key to check.
4633
+ * @returns True if the key was deleted in this transaction, false otherwise.
4634
+ */
4635
+ isDeleted(key) {
4636
+ return this.deleteBuffer.has(key);
4637
+ }
4671
4638
  _recordHistory(key) {
4672
4639
  const existsInWriteBuffer = this.writeBuffer.has(key);
4673
4640
  const existsInDeleteBuffer = this.deleteBuffer.has(key);
@@ -4681,6 +4648,41 @@ var MVCCTransaction2 = class {
4681
4648
  });
4682
4649
  }
4683
4650
  }
4651
+ /**
4652
+ * BINARY SEARCH HELPER: Finds the index of the last element in the array
4653
+ * where item[key] <= target. Assumes the array is sorted by 'key' ascending.
4654
+ */
4655
+ _findLastLE(array, target, property) {
4656
+ let left = 0;
4657
+ let right = array.length - 1;
4658
+ let result = -1;
4659
+ while (left <= right) {
4660
+ const mid = left + right >> 1;
4661
+ if (array[mid][property] <= target) {
4662
+ result = mid;
4663
+ left = mid + 1;
4664
+ } else {
4665
+ right = mid - 1;
4666
+ }
4667
+ }
4668
+ return result;
4669
+ }
4670
+ /**
4671
+ * BINARY SEARCH HELPER: Finds the index of the element in the array
4672
+ * where item[key] === target. Assumes the array is sorted by 'key' ascending.
4673
+ */
4674
+ _findExact(array, target, property) {
4675
+ let left = 0;
4676
+ let right = array.length - 1;
4677
+ while (left <= right) {
4678
+ const mid = left + right >> 1;
4679
+ const val = array[mid][property];
4680
+ if (val === target) return mid;
4681
+ if (val < target) left = mid + 1;
4682
+ else right = mid - 1;
4683
+ }
4684
+ return -1;
4685
+ }
4684
4686
  _bufferCreate(key, value, version) {
4685
4687
  if (version === void 0) this.localVersion++;
4686
4688
  const targetVersion = version ?? this.localVersion;
@@ -4730,7 +4732,11 @@ var MVCCTransaction2 = class {
4730
4732
  deleted.push({ key, data });
4731
4733
  }
4732
4734
  }
4733
- return { created, updated, deleted };
4735
+ return {
4736
+ created,
4737
+ updated,
4738
+ deleted
4739
+ };
4734
4740
  }
4735
4741
  /**
4736
4742
  * Rolls back the transaction.
@@ -4748,7 +4754,12 @@ var MVCCTransaction2 = class {
4748
4754
  if (this.root !== this) {
4749
4755
  this.root.activeTransactions.delete(this);
4750
4756
  }
4751
- return { success: true, created, updated, deleted };
4757
+ return {
4758
+ success: true,
4759
+ created,
4760
+ updated,
4761
+ deleted
4762
+ };
4752
4763
  }
4753
4764
  /**
4754
4765
  * Cleans up both deletedCache and versionIndex based on minActiveVersion.
@@ -4834,7 +4845,7 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4834
4845
  createNested() {
4835
4846
  if (this.committed) throw new Error("Transaction already committed");
4836
4847
  const childVersion = this.isRoot() ? this.version : this.snapshotVersion;
4837
- const child = new _SyncMVCCTransaction2(void 0, this, childVersion);
4848
+ const child = new _SyncMVCCTransaction2(void 0, void 0, this, childVersion);
4838
4849
  this.root.activeTransactions.add(child);
4839
4850
  return child;
4840
4851
  }
@@ -4857,78 +4868,114 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4857
4868
  return this._diskExists(key, this.snapshotVersion);
4858
4869
  }
4859
4870
  _existsSnapshot(key, snapshotVersion, snapshotLocalVersion) {
4860
- if (this.writeBuffer.has(key)) {
4861
- const keyModVersion = this.keyVersions.get(key);
4862
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
4863
- return true;
4864
- }
4865
- }
4866
- if (this.deleteBuffer.has(key)) {
4867
- const keyModVersion = this.keyVersions.get(key);
4868
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
4869
- return false;
4870
- }
4871
- }
4872
- const history = this.bufferHistory.get(key);
4873
- if (history && snapshotLocalVersion !== void 0) {
4874
- for (let i = history.length - 1; i >= 0; i--) {
4875
- if (history[i].version <= snapshotLocalVersion) {
4876
- return history[i].exists;
4877
- }
4871
+ let current = this;
4872
+ let slVer = snapshotLocalVersion;
4873
+ while (current) {
4874
+ if (current.writeBuffer.has(key)) {
4875
+ const keyModVersion = current.keyVersions.get(key);
4876
+ if (slVer === void 0 || keyModVersion <= slVer) return true;
4877
+ }
4878
+ if (current.deleteBuffer.has(key)) {
4879
+ const keyModVersion = current.keyVersions.get(key);
4880
+ if (slVer === void 0 || keyModVersion <= slVer) return false;
4881
+ }
4882
+ const history = current.bufferHistory.get(key);
4883
+ if (history && slVer !== void 0) {
4884
+ const idx = current._findLastLE(history, slVer, "version");
4885
+ if (idx >= 0) return history[idx].exists;
4886
+ }
4887
+ if (current.parent) {
4888
+ slVer = current.snapshotLocalVersion;
4889
+ current = current.parent;
4890
+ } else {
4891
+ return current._diskExists(key, snapshotVersion);
4878
4892
  }
4879
4893
  }
4880
- if (this.parent) {
4881
- return this.parent._existsSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
4882
- } else {
4883
- return this._diskExists(key, snapshotVersion);
4884
- }
4894
+ return false;
4885
4895
  }
4886
4896
  _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
4887
- if (this.writeBuffer.has(key)) {
4888
- const keyModVersion = this.keyVersions.get(key);
4889
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
4890
- return this.writeBuffer.get(key);
4897
+ let current = this;
4898
+ let slVer = snapshotLocalVersion;
4899
+ while (current) {
4900
+ if (current.writeBuffer.has(key)) {
4901
+ const keyModVersion = current.keyVersions.get(key);
4902
+ if (slVer === void 0 || keyModVersion <= slVer) {
4903
+ return current.writeBuffer.get(key);
4904
+ }
4891
4905
  }
4892
- }
4893
- if (this.deleteBuffer.has(key)) {
4894
- const keyModVersion = this.keyVersions.get(key);
4895
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
4896
- return null;
4906
+ if (current.deleteBuffer.has(key)) {
4907
+ const keyModVersion = current.keyVersions.get(key);
4908
+ if (slVer === void 0 || keyModVersion <= slVer) {
4909
+ return null;
4910
+ }
4897
4911
  }
4898
- }
4899
- const history = this.bufferHistory.get(key);
4900
- if (history && snapshotLocalVersion !== void 0) {
4901
- for (let i = history.length - 1; i >= 0; i--) {
4902
- if (history[i].version <= snapshotLocalVersion) {
4903
- return history[i].exists ? history[i].value : null;
4912
+ const history = current.bufferHistory.get(key);
4913
+ if (history && slVer !== void 0) {
4914
+ const idx = current._findLastLE(history, slVer, "version");
4915
+ if (idx >= 0) {
4916
+ return history[idx].exists ? history[idx].value : null;
4904
4917
  }
4905
4918
  }
4919
+ if (current.parent) {
4920
+ slVer = current.snapshotLocalVersion;
4921
+ current = current.parent;
4922
+ } else {
4923
+ return current._diskRead(key, snapshotVersion);
4924
+ }
4906
4925
  }
4907
- if (this.parent) {
4908
- return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
4909
- } else {
4910
- return this._diskRead(key, snapshotVersion);
4911
- }
4926
+ return null;
4912
4927
  }
4913
4928
  commit(label) {
4914
4929
  const { created, updated, deleted } = this.getResultEntries();
4915
4930
  if (this.committed) {
4916
- return { label, success: false, error: "Transaction already committed", conflict: void 0, created, updated, deleted };
4931
+ return {
4932
+ label,
4933
+ success: false,
4934
+ error: "Transaction already committed",
4935
+ conflict: void 0,
4936
+ created,
4937
+ updated,
4938
+ deleted
4939
+ };
4917
4940
  }
4918
4941
  if (this.hasCommittedAncestor()) {
4919
- return { label, success: false, error: "Ancestor transaction already committed", conflict: void 0, created, updated, deleted };
4942
+ return {
4943
+ label,
4944
+ success: false,
4945
+ error: "Ancestor transaction already committed",
4946
+ conflict: void 0,
4947
+ created,
4948
+ updated,
4949
+ deleted
4950
+ };
4920
4951
  }
4921
4952
  if (this.parent) {
4922
4953
  const failure = this.parent._merge(this);
4923
4954
  if (failure) {
4924
- return { label, success: false, error: failure.error, conflict: failure.conflict, created, updated, deleted };
4955
+ return {
4956
+ label,
4957
+ success: false,
4958
+ error: failure.error,
4959
+ conflict: failure.conflict,
4960
+ created,
4961
+ updated,
4962
+ deleted
4963
+ };
4925
4964
  }
4926
4965
  this.committed = true;
4927
4966
  } else {
4928
4967
  if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
4929
4968
  const failure = this._merge(this);
4930
4969
  if (failure) {
4931
- return { label, success: false, error: failure.error, conflict: failure.conflict, created: [], updated: [], deleted: [] };
4970
+ return {
4971
+ label,
4972
+ success: false,
4973
+ error: failure.error,
4974
+ conflict: failure.conflict,
4975
+ created: [],
4976
+ updated: [],
4977
+ deleted: []
4978
+ };
4932
4979
  }
4933
4980
  this.writeBuffer.clear();
4934
4981
  this.deleteBuffer.clear();
@@ -4941,7 +4988,13 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4941
4988
  this.snapshotVersion = this.version;
4942
4989
  }
4943
4990
  }
4944
- return { label, success: true, created, updated, deleted };
4991
+ return {
4992
+ label,
4993
+ success: true,
4994
+ created,
4995
+ updated,
4996
+ deleted
4997
+ };
4945
4998
  }
4946
4999
  _merge(child) {
4947
5000
  if (this.parent) {
@@ -4950,7 +5003,11 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4950
5003
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
4951
5004
  return {
4952
5005
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
4953
- conflict: { key, parent: this.read(key), child: child.read(key) }
5006
+ conflict: {
5007
+ key,
5008
+ parent: this.read(key),
5009
+ child: child.read(key)
5010
+ }
4954
5011
  };
4955
5012
  }
4956
5013
  }
@@ -4959,7 +5016,11 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4959
5016
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
4960
5017
  return {
4961
5018
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
4962
- conflict: { key, parent: this.read(key), child: child.read(key) }
5019
+ conflict: {
5020
+ key,
5021
+ parent: this.read(key),
5022
+ child: child.read(key)
5023
+ }
4963
5024
  };
4964
5025
  }
4965
5026
  }
@@ -4988,7 +5049,11 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4988
5049
  if (lastVer > child.snapshotVersion) {
4989
5050
  return {
4990
5051
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (v${lastVer})`,
4991
- conflict: { key, parent: this.read(key), child: child.read(key) }
5052
+ conflict: {
5053
+ key,
5054
+ parent: this.read(key),
5055
+ child: child.read(key)
5056
+ }
4992
5057
  };
4993
5058
  }
4994
5059
  }
@@ -4996,7 +5061,11 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4996
5061
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
4997
5062
  return {
4998
5063
  error: `Commit conflict: Key '${key}' was modified by a newer transaction in the same session (Local v${lastModLocalVer})`,
4999
- conflict: { key, parent: this.read(key), child: child.read(key) }
5064
+ conflict: {
5065
+ key,
5066
+ parent: this.read(key),
5067
+ child: child.read(key)
5068
+ }
5000
5069
  };
5001
5070
  }
5002
5071
  }
@@ -5031,10 +5100,14 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
5031
5100
  _diskWrite(key, value, version) {
5032
5101
  const strategy = this.strategy;
5033
5102
  if (!strategy) throw new Error("Root Transaction missing strategy");
5034
- if (strategy.exists(key)) {
5035
- const currentVal = strategy.read(key);
5103
+ const rootAsAny = this.root;
5104
+ if (this._diskExists(key, version)) {
5105
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
5036
5106
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
5037
5107
  this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
5108
+ rootAsAny.diskCache.set(key, value);
5109
+ } else {
5110
+ rootAsAny.diskCache.set(key, value);
5038
5111
  }
5039
5112
  strategy.write(key, value);
5040
5113
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -5045,23 +5118,25 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
5045
5118
  if (!strategy) throw new Error("Root Transaction missing strategy");
5046
5119
  const versions = this.versionIndex.get(key);
5047
5120
  if (!versions) {
5048
- return strategy.exists(key) ? strategy.read(key) : null;
5121
+ const rootAsAny = this.root;
5122
+ if (this._diskExists(key, snapshotVersion)) {
5123
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
5124
+ rootAsAny.diskCache.set(key, val);
5125
+ return val;
5126
+ }
5127
+ return null;
5049
5128
  }
5050
5129
  let targetVerObj = null;
5051
5130
  let nextVerObj = null;
5052
- for (const v of versions) {
5053
- if (v.version <= snapshotVersion) targetVerObj = v;
5054
- else {
5055
- nextVerObj = v;
5056
- break;
5057
- }
5058
- }
5131
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
5132
+ if (idx >= 0) targetVerObj = versions[idx];
5133
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
5059
5134
  if (!targetVerObj) {
5060
5135
  if (nextVerObj) {
5061
5136
  const cached2 = this.deletedCache.get(key);
5062
5137
  if (cached2) {
5063
- const match = cached2.find((c) => c.deletedAtVersion === nextVerObj.version);
5064
- if (match) return match.value;
5138
+ const cIdx = this._findExact(cached2, nextVerObj.version, "deletedAtVersion");
5139
+ if (cIdx >= 0) return cached2[cIdx].value;
5065
5140
  }
5066
5141
  }
5067
5142
  return null;
@@ -5069,12 +5144,18 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
5069
5144
  if (!targetVerObj.exists) return null;
5070
5145
  if (!nextVerObj) {
5071
5146
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
5072
- return strategy.read(key);
5147
+ if (this._diskExists(key, snapshotVersion)) {
5148
+ const rootAsAny = this.root;
5149
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
5150
+ rootAsAny.diskCache.set(key, val);
5151
+ return val;
5152
+ }
5153
+ return null;
5073
5154
  }
5074
5155
  const cached = this.deletedCache.get(key);
5075
5156
  if (cached) {
5076
- const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
5077
- if (match) return match.value;
5157
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
5158
+ if (cIdx >= 0) return cached[cIdx].value;
5078
5159
  }
5079
5160
  return null;
5080
5161
  }
@@ -5083,23 +5164,23 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
5083
5164
  if (!strategy) throw new Error("Root Transaction missing strategy");
5084
5165
  const versions = this.versionIndex.get(key);
5085
5166
  if (!versions) {
5086
- return strategy.exists(key);
5167
+ const rootAsAny = this.root;
5168
+ if (rootAsAny.diskCache.has(key)) return rootAsAny.diskCache.get(key) !== null;
5169
+ const exists = strategy.exists(key);
5170
+ if (!exists) rootAsAny.diskCache.set(key, null);
5171
+ return exists;
5087
5172
  }
5088
5173
  let targetVerObj = null;
5089
5174
  let nextVerObj = null;
5090
- for (const v of versions) {
5091
- if (v.version <= snapshotVersion) targetVerObj = v;
5092
- else {
5093
- nextVerObj = v;
5094
- break;
5095
- }
5096
- }
5175
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
5176
+ if (idx >= 0) targetVerObj = versions[idx];
5177
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
5097
5178
  if (!targetVerObj) {
5098
5179
  if (nextVerObj) {
5099
5180
  const cached = this.deletedCache.get(key);
5100
5181
  if (cached) {
5101
- const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
5102
- if (match) return true;
5182
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
5183
+ if (cIdx >= 0) return true;
5103
5184
  }
5104
5185
  }
5105
5186
  return false;
@@ -5109,11 +5190,13 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
5109
5190
  _diskDelete(key, snapshotVersion) {
5110
5191
  const strategy = this.strategy;
5111
5192
  if (!strategy) throw new Error("Root Transaction missing strategy");
5112
- if (strategy.exists(key)) {
5113
- const currentVal = strategy.read(key);
5193
+ const rootAsAny = this.root;
5194
+ if (this._diskExists(key, snapshotVersion)) {
5195
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
5114
5196
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
5115
5197
  this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
5116
5198
  strategy.delete(key);
5199
+ rootAsAny.diskCache.delete(key);
5117
5200
  }
5118
5201
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
5119
5202
  this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });
@@ -5427,7 +5510,7 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5427
5510
  createNested() {
5428
5511
  if (this.committed) throw new Error("Transaction already committed");
5429
5512
  const childVersion = this.isRoot() ? this.version : this.snapshotVersion;
5430
- const child = new _AsyncMVCCTransaction2(void 0, this, childVersion);
5513
+ const child = new _AsyncMVCCTransaction2(void 0, void 0, this, childVersion);
5431
5514
  this.root.activeTransactions.add(child);
5432
5515
  return child;
5433
5516
  }
@@ -5450,78 +5533,114 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5450
5533
  return await this._diskExists(key, this.snapshotVersion);
5451
5534
  }
5452
5535
  async _existsSnapshot(key, snapshotVersion, snapshotLocalVersion) {
5453
- if (this.writeBuffer.has(key)) {
5454
- const keyModVersion = this.keyVersions.get(key);
5455
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
5456
- return true;
5457
- }
5458
- }
5459
- if (this.deleteBuffer.has(key)) {
5460
- const keyModVersion = this.keyVersions.get(key);
5461
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
5462
- return false;
5463
- }
5464
- }
5465
- const history = this.bufferHistory.get(key);
5466
- if (history && snapshotLocalVersion !== void 0) {
5467
- for (let i = history.length - 1; i >= 0; i--) {
5468
- if (history[i].version <= snapshotLocalVersion) {
5469
- return history[i].exists;
5470
- }
5536
+ let current = this;
5537
+ let slVer = snapshotLocalVersion;
5538
+ while (current) {
5539
+ if (current.writeBuffer.has(key)) {
5540
+ const keyModVersion = current.keyVersions.get(key);
5541
+ if (slVer === void 0 || keyModVersion <= slVer) return true;
5542
+ }
5543
+ if (current.deleteBuffer.has(key)) {
5544
+ const keyModVersion = current.keyVersions.get(key);
5545
+ if (slVer === void 0 || keyModVersion <= slVer) return false;
5546
+ }
5547
+ const history = current.bufferHistory.get(key);
5548
+ if (history && slVer !== void 0) {
5549
+ const idx = current._findLastLE(history, slVer, "version");
5550
+ if (idx >= 0) return history[idx].exists;
5551
+ }
5552
+ if (current.parent) {
5553
+ slVer = current.snapshotLocalVersion;
5554
+ current = current.parent;
5555
+ } else {
5556
+ return await current._diskExists(key, snapshotVersion);
5471
5557
  }
5472
5558
  }
5473
- if (this.parent) {
5474
- return this.parent._existsSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
5475
- } else {
5476
- return await this._diskExists(key, snapshotVersion);
5477
- }
5559
+ return false;
5478
5560
  }
5479
5561
  async _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
5480
- if (this.writeBuffer.has(key)) {
5481
- const keyModVersion = this.keyVersions.get(key);
5482
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
5483
- return this.writeBuffer.get(key);
5562
+ let current = this;
5563
+ let slVer = snapshotLocalVersion;
5564
+ while (current) {
5565
+ if (current.writeBuffer.has(key)) {
5566
+ const keyModVersion = current.keyVersions.get(key);
5567
+ if (slVer === void 0 || keyModVersion <= slVer) {
5568
+ return current.writeBuffer.get(key);
5569
+ }
5484
5570
  }
5485
- }
5486
- if (this.deleteBuffer.has(key)) {
5487
- const keyModVersion = this.keyVersions.get(key);
5488
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
5489
- return null;
5571
+ if (current.deleteBuffer.has(key)) {
5572
+ const keyModVersion = current.keyVersions.get(key);
5573
+ if (slVer === void 0 || keyModVersion <= slVer) {
5574
+ return null;
5575
+ }
5490
5576
  }
5491
- }
5492
- const history = this.bufferHistory.get(key);
5493
- if (history && snapshotLocalVersion !== void 0) {
5494
- for (let i = history.length - 1; i >= 0; i--) {
5495
- if (history[i].version <= snapshotLocalVersion) {
5496
- return history[i].exists ? history[i].value : null;
5577
+ const history = current.bufferHistory.get(key);
5578
+ if (history && slVer !== void 0) {
5579
+ const idx = current._findLastLE(history, slVer, "version");
5580
+ if (idx >= 0) {
5581
+ return history[idx].exists ? history[idx].value : null;
5497
5582
  }
5498
5583
  }
5584
+ if (current.parent) {
5585
+ slVer = current.snapshotLocalVersion;
5586
+ current = current.parent;
5587
+ } else {
5588
+ return await current._diskRead(key, snapshotVersion);
5589
+ }
5499
5590
  }
5500
- if (this.parent) {
5501
- return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
5502
- } else {
5503
- return await this._diskRead(key, snapshotVersion);
5504
- }
5591
+ return null;
5505
5592
  }
5506
5593
  async commit(label) {
5507
5594
  const { created, updated, deleted } = this.getResultEntries();
5508
5595
  if (this.committed) {
5509
- return { label, success: false, error: "Transaction already committed", conflict: void 0, created, updated, deleted };
5596
+ return {
5597
+ label,
5598
+ success: false,
5599
+ error: "Transaction already committed",
5600
+ conflict: void 0,
5601
+ created,
5602
+ updated,
5603
+ deleted
5604
+ };
5510
5605
  }
5511
5606
  if (this.hasCommittedAncestor()) {
5512
- return { label, success: false, error: "Ancestor transaction already committed", conflict: void 0, created, updated, deleted };
5607
+ return {
5608
+ label,
5609
+ success: false,
5610
+ error: "Ancestor transaction already committed",
5611
+ conflict: void 0,
5612
+ created,
5613
+ updated,
5614
+ deleted
5615
+ };
5513
5616
  }
5514
5617
  if (this.parent) {
5515
5618
  const failure = await this.parent._merge(this);
5516
5619
  if (failure) {
5517
- return { label, success: false, error: failure.error, conflict: failure.conflict, created, updated, deleted };
5620
+ return {
5621
+ label,
5622
+ success: false,
5623
+ error: failure.error,
5624
+ conflict: failure.conflict,
5625
+ created,
5626
+ updated,
5627
+ deleted
5628
+ };
5518
5629
  }
5519
5630
  this.committed = true;
5520
5631
  } else {
5521
5632
  if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
5522
5633
  const failure = await this._merge(this);
5523
5634
  if (failure) {
5524
- return { label, success: false, error: failure.error, conflict: failure.conflict, created: [], updated: [], deleted: [] };
5635
+ return {
5636
+ label,
5637
+ success: false,
5638
+ error: failure.error,
5639
+ conflict: failure.conflict,
5640
+ created: [],
5641
+ updated: [],
5642
+ deleted: []
5643
+ };
5525
5644
  }
5526
5645
  this.writeBuffer.clear();
5527
5646
  this.deleteBuffer.clear();
@@ -5534,7 +5653,13 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5534
5653
  this.snapshotVersion = this.version;
5535
5654
  }
5536
5655
  }
5537
- return { label, success: true, created, updated, deleted };
5656
+ return {
5657
+ label,
5658
+ success: true,
5659
+ created,
5660
+ updated,
5661
+ deleted
5662
+ };
5538
5663
  }
5539
5664
  async _merge(child) {
5540
5665
  return this.writeLock(async () => {
@@ -5544,7 +5669,11 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5544
5669
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
5545
5670
  return {
5546
5671
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
5547
- conflict: { key, parent: await this.read(key), child: await child.read(key) }
5672
+ conflict: {
5673
+ key,
5674
+ parent: await this.read(key),
5675
+ child: await child.read(key)
5676
+ }
5548
5677
  };
5549
5678
  }
5550
5679
  }
@@ -5553,7 +5682,11 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5553
5682
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
5554
5683
  return {
5555
5684
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
5556
- conflict: { key, parent: await this.read(key), child: await child.read(key) }
5685
+ conflict: {
5686
+ key,
5687
+ parent: await this.read(key),
5688
+ child: await child.read(key)
5689
+ }
5557
5690
  };
5558
5691
  }
5559
5692
  }
@@ -5583,7 +5716,11 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5583
5716
  if (lastVer > child.snapshotVersion) {
5584
5717
  return {
5585
5718
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (v${lastVer})`,
5586
- conflict: { key, parent: await this.read(key), child: await child.read(key) }
5719
+ conflict: {
5720
+ key,
5721
+ parent: await this.read(key),
5722
+ child: await child.read(key)
5723
+ }
5587
5724
  };
5588
5725
  }
5589
5726
  }
@@ -5591,7 +5728,11 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5591
5728
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
5592
5729
  return {
5593
5730
  error: `Commit conflict: Key '${key}' was modified by a newer transaction in the same session (Local v${lastModLocalVer})`,
5594
- conflict: { key, parent: await this.read(key), child: await child.read(key) }
5731
+ conflict: {
5732
+ key,
5733
+ parent: await this.read(key),
5734
+ child: await child.read(key)
5735
+ }
5595
5736
  };
5596
5737
  }
5597
5738
  }
@@ -5627,10 +5768,14 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5627
5768
  async _diskWrite(key, value, version) {
5628
5769
  const strategy = this.strategy;
5629
5770
  if (!strategy) throw new Error("Root Transaction missing strategy");
5630
- if (await strategy.exists(key)) {
5631
- const currentVal = await strategy.read(key);
5771
+ const rootAsAny = this.root;
5772
+ if (await this._diskExists(key, version)) {
5773
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
5632
5774
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
5633
5775
  this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
5776
+ rootAsAny.diskCache.set(key, value);
5777
+ } else {
5778
+ rootAsAny.diskCache.set(key, value);
5634
5779
  }
5635
5780
  await strategy.write(key, value);
5636
5781
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -5641,23 +5786,25 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5641
5786
  if (!strategy) throw new Error("Root Transaction missing strategy");
5642
5787
  const versions = this.versionIndex.get(key);
5643
5788
  if (!versions) {
5644
- return await strategy.exists(key) ? await strategy.read(key) : null;
5789
+ const rootAsAny = this.root;
5790
+ if (await this._diskExists(key, snapshotVersion)) {
5791
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
5792
+ rootAsAny.diskCache.set(key, val);
5793
+ return val;
5794
+ }
5795
+ return null;
5645
5796
  }
5646
5797
  let targetVerObj = null;
5647
5798
  let nextVerObj = null;
5648
- for (const v of versions) {
5649
- if (v.version <= snapshotVersion) targetVerObj = v;
5650
- else {
5651
- nextVerObj = v;
5652
- break;
5653
- }
5654
- }
5799
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
5800
+ if (idx >= 0) targetVerObj = versions[idx];
5801
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
5655
5802
  if (!targetVerObj) {
5656
5803
  if (nextVerObj) {
5657
5804
  const cached2 = this.deletedCache.get(key);
5658
5805
  if (cached2) {
5659
- const match = cached2.find((c) => c.deletedAtVersion === nextVerObj.version);
5660
- if (match) return match.value;
5806
+ const cIdx = this._findExact(cached2, nextVerObj.version, "deletedAtVersion");
5807
+ if (cIdx >= 0) return cached2[cIdx].value;
5661
5808
  }
5662
5809
  }
5663
5810
  return null;
@@ -5665,12 +5812,18 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5665
5812
  if (!targetVerObj.exists) return null;
5666
5813
  if (!nextVerObj) {
5667
5814
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
5668
- return strategy.read(key);
5815
+ if (await this._diskExists(key, snapshotVersion)) {
5816
+ const rootAsAny = this.root;
5817
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
5818
+ rootAsAny.diskCache.set(key, val);
5819
+ return val;
5820
+ }
5821
+ return null;
5669
5822
  }
5670
5823
  const cached = this.deletedCache.get(key);
5671
5824
  if (cached) {
5672
- const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
5673
- if (match) return match.value;
5825
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
5826
+ if (cIdx >= 0) return cached[cIdx].value;
5674
5827
  }
5675
5828
  return null;
5676
5829
  }
@@ -5679,23 +5832,23 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5679
5832
  if (!strategy) throw new Error("Root Transaction missing strategy");
5680
5833
  const versions = this.versionIndex.get(key);
5681
5834
  if (!versions) {
5682
- return await strategy.exists(key);
5835
+ const rootAsAny = this.root;
5836
+ if (rootAsAny.diskCache.has(key)) return rootAsAny.diskCache.get(key) !== null;
5837
+ const exists = await strategy.exists(key);
5838
+ if (!exists) rootAsAny.diskCache.set(key, null);
5839
+ return exists;
5683
5840
  }
5684
5841
  let targetVerObj = null;
5685
5842
  let nextVerObj = null;
5686
- for (const v of versions) {
5687
- if (v.version <= snapshotVersion) targetVerObj = v;
5688
- else {
5689
- nextVerObj = v;
5690
- break;
5691
- }
5692
- }
5843
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
5844
+ if (idx >= 0) targetVerObj = versions[idx];
5845
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
5693
5846
  if (!targetVerObj) {
5694
5847
  if (nextVerObj) {
5695
5848
  const cached = this.deletedCache.get(key);
5696
5849
  if (cached) {
5697
- const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
5698
- if (match) return true;
5850
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
5851
+ if (cIdx >= 0) return true;
5699
5852
  }
5700
5853
  }
5701
5854
  return false;
@@ -5705,11 +5858,13 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5705
5858
  async _diskDelete(key, snapshotVersion) {
5706
5859
  const strategy = this.strategy;
5707
5860
  if (!strategy) throw new Error("Root Transaction missing strategy");
5708
- if (await strategy.exists(key)) {
5709
- const currentVal = await strategy.read(key);
5861
+ const rootAsAny = this.root;
5862
+ if (await this._diskExists(key, snapshotVersion)) {
5863
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
5710
5864
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
5711
5865
  this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
5712
5866
  await strategy.delete(key);
5867
+ rootAsAny.diskCache.delete(key);
5713
5868
  }
5714
5869
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
5715
5870
  this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });