dataply 0.0.22-alpha.0 → 0.0.22-alpha.3

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 +1137 -984
  2. package/package.json +3 -3
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
  }
@@ -1202,367 +1445,48 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1202
1445
  const strategy = this.strategy;
1203
1446
  if (!strategy) throw new Error("Root Transaction missing strategy");
1204
1447
  const versions = this.versionIndex.get(key);
1205
- if (!versions) {
1206
- return await strategy.exists(key);
1207
- }
1208
- let targetVerObj = null;
1209
- 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
- }
1217
- if (!targetVerObj) {
1218
- if (nextVerObj) {
1219
- const cached = this.deletedCache.get(key);
1220
- 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);
1460
- }
1461
- }
1462
- }
1463
- }
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}`);
1448
+ if (!versions) {
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;
1548
1454
  }
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);
1455
+ let targetVerObj = null;
1456
+ let nextVerObj = null;
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];
1460
+ if (!targetVerObj) {
1461
+ if (nextVerObj) {
1462
+ const cached = this.deletedCache.get(key);
1463
+ if (cached) {
1464
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
1465
+ if (cIdx >= 0) return true;
1466
+ }
1467
+ }
1468
+ return false;
1554
1469
  }
1555
- return this.caches.get(key);
1470
+ return targetVerObj.exists;
1556
1471
  }
1557
- update(key, ...parameter) {
1558
- this.bubbleUpdateSignal(key);
1559
- this.resolve(key, ...parameter);
1560
- return this.caches.get(key);
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);
1482
+ }
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
  }
@@ -2578,24 +2495,13 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2578
2495
  commit(label) {
2579
2496
  let result = this.mvcc.commit(label);
2580
2497
  if (result.success) {
2581
- const isRootTx = this.rootTx !== this;
2582
- if (isRootTx) {
2498
+ const isRootTx = this.rootTx === this;
2499
+ if (!isRootTx) {
2583
2500
  result = this.rootTx.commit(label);
2584
2501
  if (result.success) {
2585
2502
  this.rootTx.rootId = this.rootId;
2586
2503
  }
2587
2504
  }
2588
- 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
- }
2599
2505
  }
2600
2506
  return result;
2601
2507
  }
@@ -2638,7 +2544,9 @@ var BPTreeMVCCStrategySync = class extends SyncMVCCStrategy {
2638
2544
  };
2639
2545
  var BPTreeSync = class extends BPTreeSyncTransaction {
2640
2546
  constructor(strategy, comparator, option) {
2641
- const mvccRoot = new SyncMVCCTransaction(new BPTreeMVCCStrategySync(strategy));
2547
+ const mvccRoot = new SyncMVCCTransaction(new BPTreeMVCCStrategySync(strategy), {
2548
+ cacheCapacity: option?.capacity ?? void 0
2549
+ });
2642
2550
  super(
2643
2551
  null,
2644
2552
  mvccRoot,
@@ -2961,9 +2869,6 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
2961
2869
  });
2962
2870
  }
2963
2871
  async getNode(id) {
2964
- if (this.nodes.has(id)) {
2965
- return this.nodes.get(id);
2966
- }
2967
2872
  return await this.mvcc.read(id);
2968
2873
  }
2969
2874
  /**
@@ -2980,24 +2885,31 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
2980
2885
  next,
2981
2886
  prev
2982
2887
  };
2888
+ const head = await this._readHead();
2889
+ if (head) {
2890
+ await this._writeHead({
2891
+ root: head.root,
2892
+ order: head.order,
2893
+ data: this.strategy.head.data
2894
+ });
2895
+ }
2983
2896
  await this.mvcc.create(id, node);
2984
- this.nodes.set(id, node);
2985
2897
  return node;
2986
2898
  }
2987
2899
  async _updateNode(node) {
2900
+ if (this.mvcc.isDeleted(node.id)) {
2901
+ return;
2902
+ }
2988
2903
  await this.mvcc.write(node.id, node);
2989
- this.nodes.set(node.id, node);
2990
2904
  }
2991
2905
  async _deleteNode(node) {
2906
+ if (this.mvcc.isDeleted(node.id)) {
2907
+ return;
2908
+ }
2992
2909
  await this.mvcc.delete(node.id);
2993
- this.nodes.delete(node.id);
2994
2910
  }
2995
2911
  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;
2912
+ return await this.mvcc.read("__HEAD__");
3001
2913
  }
3002
2914
  async _writeHead(head) {
3003
2915
  if (!await this.mvcc.exists("__HEAD__")) {
@@ -3005,49 +2917,56 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3005
2917
  } else {
3006
2918
  await this.mvcc.write("__HEAD__", head);
3007
2919
  }
3008
- this.nodes.set("__HEAD__", head);
3009
2920
  this.rootId = head.root;
3010
2921
  }
3011
2922
  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];
2923
+ let leaf = node;
2924
+ if (leaf.values.length) {
2925
+ for (let i = 0, len = leaf.values.length; i < len; i++) {
2926
+ const nValue = leaf.values[i];
3015
2927
  if (this.comparator.isSame(value, nValue)) {
3016
- const keys = node.keys[i];
2928
+ const keys = leaf.keys[i];
3017
2929
  if (keys.includes(key)) {
3018
2930
  break;
3019
2931
  }
3020
- keys.push(key);
3021
- await this._updateNode(node);
3022
- return;
2932
+ leaf = this._cloneNode(leaf);
2933
+ leaf.keys[i].push(key);
2934
+ await this._updateNode(leaf);
2935
+ return leaf;
3023
2936
  } 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;
2937
+ leaf = this._cloneNode(leaf);
2938
+ leaf.values.splice(i, 0, value);
2939
+ leaf.keys.splice(i, 0, [key]);
2940
+ await this._updateNode(leaf);
2941
+ return leaf;
2942
+ } else if (i + 1 === leaf.values.length) {
2943
+ leaf = this._cloneNode(leaf);
2944
+ leaf.values.push(value);
2945
+ leaf.keys.push([key]);
2946
+ await this._updateNode(leaf);
2947
+ return leaf;
3033
2948
  }
3034
2949
  }
3035
2950
  } else {
3036
- node.values = [value];
3037
- node.keys = [[key]];
3038
- await this._updateNode(node);
3039
- return;
2951
+ leaf = this._cloneNode(leaf);
2952
+ leaf.values = [value];
2953
+ leaf.keys = [[key]];
2954
+ await this._updateNode(leaf);
2955
+ return leaf;
3040
2956
  }
2957
+ return leaf;
3041
2958
  }
3042
- async _insertInParent(node, value, pointer) {
2959
+ async _insertInParent(node, value, newSiblingNode) {
3043
2960
  if (this.rootId === node.id) {
3044
- const root = await this._createNode(false, [node.id, pointer.id], [value]);
2961
+ node = this._cloneNode(node);
2962
+ newSiblingNode = this._cloneNode(newSiblingNode);
2963
+ const root = await this._createNode(false, [node.id, newSiblingNode.id], [value]);
3045
2964
  this.rootId = root.id;
3046
2965
  node.parent = root.id;
3047
- pointer.parent = root.id;
3048
- if (pointer.leaf) {
3049
- node.next = pointer.id;
3050
- pointer.prev = node.id;
2966
+ newSiblingNode.parent = root.id;
2967
+ if (newSiblingNode.leaf) {
2968
+ node.next = newSiblingNode.id;
2969
+ newSiblingNode.prev = node.id;
3051
2970
  }
3052
2971
  await this._writeHead({
3053
2972
  root: root.id,
@@ -3055,53 +2974,54 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3055
2974
  data: this.strategy.head.data
3056
2975
  });
3057
2976
  await this._updateNode(node);
3058
- await this._updateNode(pointer);
2977
+ await this._updateNode(newSiblingNode);
3059
2978
  return;
3060
2979
  }
3061
- const parentNode = await this.getNode(node.parent);
2980
+ const parentNode = this._cloneNode(await this.getNode(node.parent));
3062
2981
  const nodeIndex = parentNode.keys.indexOf(node.id);
3063
2982
  if (nodeIndex === -1) {
3064
2983
  throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
3065
2984
  }
3066
2985
  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;
2986
+ parentNode.keys.splice(nodeIndex + 1, 0, newSiblingNode.id);
2987
+ newSiblingNode = this._cloneNode(newSiblingNode);
2988
+ newSiblingNode.parent = parentNode.id;
2989
+ if (newSiblingNode.leaf) {
2990
+ const leftSibling = this._cloneNode(node);
3071
2991
  const oldNextId = leftSibling.next;
3072
- pointer.prev = leftSibling.id;
3073
- pointer.next = oldNextId;
3074
- leftSibling.next = pointer.id;
2992
+ newSiblingNode.prev = leftSibling.id;
2993
+ newSiblingNode.next = oldNextId;
2994
+ leftSibling.next = newSiblingNode.id;
3075
2995
  await this._updateNode(leftSibling);
3076
2996
  if (oldNextId) {
3077
- const oldNext = await this.getNode(oldNextId);
3078
- oldNext.prev = pointer.id;
2997
+ const oldNext = this._cloneNode(await this.getNode(oldNextId));
2998
+ oldNext.prev = newSiblingNode.id;
3079
2999
  await this._updateNode(oldNext);
3080
3000
  }
3081
3001
  }
3082
3002
  await this._updateNode(parentNode);
3083
- await this._updateNode(pointer);
3003
+ await this._updateNode(newSiblingNode);
3084
3004
  if (parentNode.keys.length > this.order) {
3085
- const parentPointer = await this._createNode(false, [], []);
3086
- parentPointer.parent = parentNode.parent;
3005
+ const newSiblingNodeRecursive = await this._createNode(false, [], []);
3006
+ newSiblingNodeRecursive.parent = parentNode.parent;
3087
3007
  const mid = Math.ceil(this.order / 2) - 1;
3088
- parentPointer.values = parentNode.values.slice(mid + 1);
3089
- parentPointer.keys = parentNode.keys.slice(mid + 1);
3008
+ newSiblingNodeRecursive.values = parentNode.values.slice(mid + 1);
3009
+ newSiblingNodeRecursive.keys = parentNode.keys.slice(mid + 1);
3090
3010
  const midValue = parentNode.values[mid];
3091
3011
  parentNode.values = parentNode.values.slice(0, mid);
3092
3012
  parentNode.keys = parentNode.keys.slice(0, mid + 1);
3093
3013
  for (const k of parentNode.keys) {
3094
- const n = await this.getNode(k);
3014
+ const n = this._cloneNode(await this.getNode(k));
3095
3015
  n.parent = parentNode.id;
3096
3016
  await this._updateNode(n);
3097
3017
  }
3098
- for (const k of parentPointer.keys) {
3099
- const n = await this.getNode(k);
3100
- n.parent = parentPointer.id;
3018
+ for (const k of newSiblingNodeRecursive.keys) {
3019
+ const n = this._cloneNode(await this.getNode(k));
3020
+ n.parent = newSiblingNodeRecursive.id;
3101
3021
  await this._updateNode(n);
3102
3022
  }
3103
3023
  await this._updateNode(parentNode);
3104
- await this._insertInParent(parentNode, midValue, parentPointer);
3024
+ await this._insertInParent(parentNode, midValue, newSiblingNodeRecursive);
3105
3025
  }
3106
3026
  }
3107
3027
  async insertableNode(value) {
@@ -3290,21 +3210,6 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3290
3210
  }
3291
3211
  return false;
3292
3212
  }
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
3213
  async get(key) {
3309
3214
  let node = await this.leftestNode();
3310
3215
  while (true) {
@@ -3391,10 +3296,10 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3391
3296
  }
3392
3297
  async insert(key, value) {
3393
3298
  return this.writeLock(0, async () => {
3394
- const before = await this.insertableNode(value);
3395
- await this._insertAtLeaf(before, key, value);
3299
+ let before = await this.insertableNode(value);
3300
+ before = await this._insertAtLeaf(before, key, value);
3396
3301
  if (before.values.length === this.order) {
3397
- const after = await this._createNode(
3302
+ let after = await this._createNode(
3398
3303
  true,
3399
3304
  [],
3400
3305
  [],
@@ -3403,10 +3308,13 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3403
3308
  null
3404
3309
  );
3405
3310
  const mid = Math.ceil(this.order / 2) - 1;
3311
+ after = this._cloneNode(after);
3406
3312
  after.values = before.values.slice(mid + 1);
3407
3313
  after.keys = before.keys.slice(mid + 1);
3408
3314
  before.values = before.values.slice(0, mid + 1);
3409
3315
  before.keys = before.keys.slice(0, mid + 1);
3316
+ await this._updateNode(before);
3317
+ await this._updateNode(after);
3410
3318
  await this._insertInParent(before, after.values[0], after);
3411
3319
  }
3412
3320
  });
@@ -3421,6 +3329,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3421
3329
  }
3422
3330
  }
3423
3331
  if (keyIndex !== -1) {
3332
+ node = this._cloneNode(node);
3424
3333
  node.keys.splice(keyIndex, 1);
3425
3334
  const valueIndex = keyIndex > 0 ? keyIndex - 1 : 0;
3426
3335
  node.values.splice(valueIndex, 1);
@@ -3430,7 +3339,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3430
3339
  if (this.rootId === node.id && node.keys.length === 1 && !node.leaf) {
3431
3340
  const keys = node.keys;
3432
3341
  this._deleteNode(node);
3433
- const newRoot = await this.getNode(keys[0]);
3342
+ const newRoot = this._cloneNode(await this.getNode(keys[0]));
3434
3343
  newRoot.parent = null;
3435
3344
  await this._updateNode(newRoot);
3436
3345
  await this._writeHead({
@@ -3438,14 +3347,17 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3438
3347
  order: this.order,
3439
3348
  data: this.strategy.head.data
3440
3349
  });
3441
- return;
3350
+ return node;
3442
3351
  } else if (this.rootId === node.id) {
3443
- const root = await this.getNode(this.rootId);
3444
- await this._updateNode(root);
3445
- return;
3352
+ await this._writeHead({
3353
+ root: node.id,
3354
+ order: this.order,
3355
+ data: this.strategy.head.data
3356
+ });
3357
+ return node;
3446
3358
  } else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
3447
3359
  if (node.parent === null) {
3448
- return;
3360
+ return node;
3449
3361
  }
3450
3362
  let isPredecessor = false;
3451
3363
  let parentNode = await this.getNode(node.parent);
@@ -3466,78 +3378,80 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3466
3378
  }
3467
3379
  }
3468
3380
  }
3469
- let pointer;
3381
+ let siblingNode;
3470
3382
  let guess;
3471
3383
  if (prevNode === null) {
3472
- pointer = nextNode;
3384
+ siblingNode = nextNode;
3473
3385
  guess = postValue;
3474
3386
  } else if (nextNode === null) {
3475
3387
  isPredecessor = true;
3476
- pointer = prevNode;
3388
+ siblingNode = prevNode;
3477
3389
  guess = prevValue;
3478
3390
  } else {
3479
3391
  if (node.values.length + nextNode.values.length < this.order) {
3480
- pointer = nextNode;
3392
+ siblingNode = nextNode;
3481
3393
  guess = postValue;
3482
3394
  } else {
3483
3395
  isPredecessor = true;
3484
- pointer = prevNode;
3396
+ siblingNode = prevNode;
3485
3397
  guess = prevValue;
3486
3398
  }
3487
3399
  }
3488
- if (!pointer) {
3489
- return;
3400
+ if (!siblingNode) {
3401
+ return node;
3490
3402
  }
3491
- if (node.values.length + pointer.values.length < this.order) {
3403
+ node = this._cloneNode(node);
3404
+ siblingNode = this._cloneNode(siblingNode);
3405
+ if (node.values.length + siblingNode.values.length < this.order) {
3492
3406
  if (!isPredecessor) {
3493
- const pTemp = pointer;
3494
- pointer = node;
3407
+ const pTemp = siblingNode;
3408
+ siblingNode = node;
3495
3409
  node = pTemp;
3496
3410
  }
3497
- pointer.keys.push(...node.keys);
3411
+ siblingNode.keys.push(...node.keys);
3498
3412
  if (!node.leaf) {
3499
- pointer.values.push(guess);
3413
+ siblingNode.values.push(guess);
3500
3414
  } else {
3501
- pointer.next = node.next;
3502
- if (pointer.next) {
3503
- const n = await this.getNode(pointer.next);
3504
- n.prev = pointer.id;
3415
+ siblingNode.next = node.next;
3416
+ if (siblingNode.next) {
3417
+ const n = this._cloneNode(await this.getNode(siblingNode.next));
3418
+ n.prev = siblingNode.id;
3505
3419
  await this._updateNode(n);
3506
3420
  }
3507
3421
  }
3508
- pointer.values.push(...node.values);
3509
- if (!pointer.leaf) {
3510
- const keys = pointer.keys;
3422
+ siblingNode.values.push(...node.values);
3423
+ if (!siblingNode.leaf) {
3424
+ const keys = siblingNode.keys;
3511
3425
  for (const key2 of keys) {
3512
- const node2 = await this.getNode(key2);
3513
- node2.parent = pointer.id;
3426
+ const node2 = this._cloneNode(await this.getNode(key2));
3427
+ node2.parent = siblingNode.id;
3514
3428
  await this._updateNode(node2);
3515
3429
  }
3516
3430
  }
3517
3431
  this._deleteNode(node);
3518
- await this._updateNode(pointer);
3432
+ await this._updateNode(siblingNode);
3519
3433
  await this._deleteEntry(await this.getNode(node.parent), node.id);
3520
3434
  } else {
3521
3435
  if (isPredecessor) {
3522
3436
  let pointerPm;
3523
3437
  let pointerKm;
3524
3438
  if (!node.leaf) {
3525
- pointerPm = pointer.keys.splice(-1)[0];
3526
- pointerKm = pointer.values.splice(-1)[0];
3439
+ pointerPm = siblingNode.keys.splice(-1)[0];
3440
+ pointerKm = siblingNode.values.splice(-1)[0];
3527
3441
  node.keys = [pointerPm, ...node.keys];
3528
3442
  node.values = [guess, ...node.values];
3529
- parentNode = await this.getNode(node.parent);
3443
+ parentNode = this._cloneNode(await this.getNode(node.parent));
3530
3444
  const nodeIndex = parentNode.keys.indexOf(node.id);
3531
3445
  if (nodeIndex > 0) {
3532
3446
  parentNode.values[nodeIndex - 1] = pointerKm;
3533
3447
  await this._updateNode(parentNode);
3534
3448
  }
3535
3449
  } else {
3536
- pointerPm = pointer.keys.splice(-1)[0];
3537
- pointerKm = pointer.values.splice(-1)[0];
3450
+ pointerPm = siblingNode.keys.splice(-1)[0];
3451
+ pointerKm = siblingNode.values.splice(-1)[0];
3538
3452
  node.keys = [pointerPm, ...node.keys];
3539
3453
  node.values = [pointerKm, ...node.values];
3540
- parentNode = await this.getNode(node.parent);
3454
+ parentNode = this._cloneNode(await this.getNode(node.parent));
3541
3455
  const nodeIndex = parentNode.keys.indexOf(node.id);
3542
3456
  if (nodeIndex > 0) {
3543
3457
  parentNode.values[nodeIndex - 1] = pointerKm;
@@ -3545,61 +3459,62 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3545
3459
  }
3546
3460
  }
3547
3461
  await this._updateNode(node);
3548
- await this._updateNode(pointer);
3462
+ await this._updateNode(siblingNode);
3549
3463
  } else {
3550
3464
  let pointerP0;
3551
3465
  let pointerK0;
3552
3466
  if (!node.leaf) {
3553
- pointerP0 = pointer.keys.splice(0, 1)[0];
3554
- pointerK0 = pointer.values.splice(0, 1)[0];
3467
+ pointerP0 = siblingNode.keys.splice(0, 1)[0];
3468
+ pointerK0 = siblingNode.values.splice(0, 1)[0];
3555
3469
  node.keys = [...node.keys, pointerP0];
3556
3470
  node.values = [...node.values, guess];
3557
- parentNode = await this.getNode(node.parent);
3558
- const pointerIndex = parentNode.keys.indexOf(pointer.id);
3471
+ parentNode = this._cloneNode(await this.getNode(node.parent));
3472
+ const pointerIndex = parentNode.keys.indexOf(siblingNode.id);
3559
3473
  if (pointerIndex > 0) {
3560
3474
  parentNode.values[pointerIndex - 1] = pointerK0;
3561
3475
  await this._updateNode(parentNode);
3562
3476
  }
3563
3477
  } else {
3564
- pointerP0 = pointer.keys.splice(0, 1)[0];
3565
- pointerK0 = pointer.values.splice(0, 1)[0];
3478
+ pointerP0 = siblingNode.keys.splice(0, 1)[0];
3479
+ pointerK0 = siblingNode.values.splice(0, 1)[0];
3566
3480
  node.keys = [...node.keys, pointerP0];
3567
3481
  node.values = [...node.values, pointerK0];
3568
- parentNode = await this.getNode(node.parent);
3569
- const pointerIndex = parentNode.keys.indexOf(pointer.id);
3482
+ parentNode = this._cloneNode(await this.getNode(node.parent));
3483
+ const pointerIndex = parentNode.keys.indexOf(siblingNode.id);
3570
3484
  if (pointerIndex > 0) {
3571
- parentNode.values[pointerIndex - 1] = pointer.values[0];
3485
+ parentNode.values[pointerIndex - 1] = siblingNode.values[0];
3572
3486
  await this._updateNode(parentNode);
3573
3487
  }
3574
3488
  }
3575
3489
  await this._updateNode(node);
3576
- await this._updateNode(pointer);
3490
+ await this._updateNode(siblingNode);
3577
3491
  }
3578
- if (!pointer.leaf) {
3579
- for (const key2 of pointer.keys) {
3580
- const n = await this.getNode(key2);
3581
- n.parent = pointer.id;
3492
+ if (!siblingNode.leaf) {
3493
+ for (const key2 of siblingNode.keys) {
3494
+ const n = this._cloneNode(await this.getNode(key2));
3495
+ n.parent = siblingNode.id;
3582
3496
  await this._updateNode(n);
3583
3497
  }
3584
3498
  }
3585
3499
  if (!node.leaf) {
3586
3500
  for (const key2 of node.keys) {
3587
- const n = await this.getNode(key2);
3501
+ const n = this._cloneNode(await this.getNode(key2));
3588
3502
  n.parent = node.id;
3589
3503
  await this._updateNode(n);
3590
3504
  }
3591
3505
  }
3592
3506
  if (!parentNode.leaf) {
3593
3507
  for (const key2 of parentNode.keys) {
3594
- const n = await this.getNode(key2);
3508
+ const n = this._cloneNode(await this.getNode(key2));
3595
3509
  n.parent = parentNode.id;
3596
3510
  await this._updateNode(n);
3597
3511
  }
3598
3512
  }
3599
3513
  }
3600
3514
  } else {
3601
- await this._updateNode(node);
3515
+ await this._updateNode(this._cloneNode(node));
3602
3516
  }
3517
+ return node;
3603
3518
  }
3604
3519
  async delete(key, value) {
3605
3520
  return this.writeLock(0, async () => {
@@ -3613,13 +3528,15 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3613
3528
  const keys = node.keys[i];
3614
3529
  const keyIndex = keys.indexOf(key);
3615
3530
  if (keyIndex !== -1) {
3616
- keys.splice(keyIndex, 1);
3617
- if (keys.length === 0) {
3531
+ node = this._cloneNode(node);
3532
+ const freshKeys = node.keys[i];
3533
+ freshKeys.splice(keyIndex, 1);
3534
+ if (freshKeys.length === 0) {
3618
3535
  node.keys.splice(i, 1);
3619
3536
  node.values.splice(i, 1);
3620
3537
  }
3621
3538
  await this._updateNode(node);
3622
- await this._deleteEntry(node, key);
3539
+ node = await this._deleteEntry(node, key);
3623
3540
  found = true;
3624
3541
  break;
3625
3542
  }
@@ -3662,21 +3579,10 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3662
3579
  this.rootTx.rootId = this.rootId;
3663
3580
  }
3664
3581
  }
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
3582
  }
3677
3583
  return result;
3678
3584
  }
3679
- rollback() {
3585
+ async rollback() {
3680
3586
  return this.mvcc.rollback();
3681
3587
  }
3682
3588
  };
@@ -3715,7 +3621,9 @@ var BPTreeMVCCStrategyAsync = class extends AsyncMVCCStrategy {
3715
3621
  };
3716
3622
  var BPTreeAsync = class extends BPTreeAsyncTransaction {
3717
3623
  constructor(strategy, comparator, option) {
3718
- const mvccRoot = new AsyncMVCCTransaction(new BPTreeMVCCStrategyAsync(strategy));
3624
+ const mvccRoot = new AsyncMVCCTransaction(new BPTreeMVCCStrategyAsync(strategy), {
3625
+ cacheCapacity: option?.capacity ?? void 0
3626
+ });
3719
3627
  super(
3720
3628
  null,
3721
3629
  mvccRoot,
@@ -4267,7 +4175,7 @@ var LRUMap2 = class {
4267
4175
  this.tail = null;
4268
4176
  }
4269
4177
  };
4270
- var CacheEntanglement2 = class {
4178
+ var CacheEntanglement = class {
4271
4179
  creation;
4272
4180
  beforeUpdateHook;
4273
4181
  capacity;
@@ -4368,7 +4276,7 @@ var CacheEntanglement2 = class {
4368
4276
  }
4369
4277
  }
4370
4278
  };
4371
- var CacheData2 = class _CacheData2 {
4279
+ var CacheData = class _CacheData {
4372
4280
  static StructuredClone = globalThis.structuredClone.bind(globalThis);
4373
4281
  _value;
4374
4282
  constructor(value) {
@@ -4408,11 +4316,11 @@ var CacheData2 = class _CacheData2 {
4408
4316
  return Object.assign({}, this.raw);
4409
4317
  case "deep-copy":
4410
4318
  default:
4411
- return _CacheData2.StructuredClone(this.raw);
4319
+ return _CacheData.StructuredClone(this.raw);
4412
4320
  }
4413
4321
  }
4414
4322
  };
4415
- var CacheEntanglementSync2 = class extends CacheEntanglement2 {
4323
+ var CacheEntanglementSync = class extends CacheEntanglement {
4416
4324
  constructor(creation, option) {
4417
4325
  super(creation, option);
4418
4326
  }
@@ -4442,7 +4350,7 @@ var CacheEntanglementSync2 = class extends CacheEntanglement2 {
4442
4350
  const dependencyValue = dependency.recache(key) ?? dependency.recache(dependencyKey);
4443
4351
  resolved[name] = dependencyValue;
4444
4352
  }
4445
- const value = new CacheData2(this.creation(key, resolved, ...parameter));
4353
+ const value = new CacheData(this.creation(key, resolved, ...parameter));
4446
4354
  this.updateRequirements.delete(key);
4447
4355
  this.parameters.set(key, parameter);
4448
4356
  this.caches.set(key, value);
@@ -4466,7 +4374,7 @@ var CacheEntanglementSync2 = class extends CacheEntanglement2 {
4466
4374
  return this.caches.get(key);
4467
4375
  }
4468
4376
  };
4469
- var CacheEntanglementAsync = class extends CacheEntanglement2 {
4377
+ var CacheEntanglementAsync = class extends CacheEntanglement {
4470
4378
  constructor(creation, option) {
4471
4379
  super(creation, option);
4472
4380
  }
@@ -4496,7 +4404,7 @@ var CacheEntanglementAsync = class extends CacheEntanglement2 {
4496
4404
  const dependencyValue = await dependency.recache(key) ?? await dependency.recache(dependencyKey);
4497
4405
  resolved[name] = dependencyValue;
4498
4406
  }
4499
- const value = new CacheData2(await this.creation(key, resolved, ...parameter));
4407
+ const value = new CacheData(await this.creation(key, resolved, ...parameter));
4500
4408
  this.updateRequirements.delete(key);
4501
4409
  this.parameters.set(key, parameter);
4502
4410
  this.caches.set(key, value);
@@ -4601,6 +4509,42 @@ var InvertedWeakMap = class {
4601
4509
  // node_modules/mvcc-api/dist/esm/index.mjs
4602
4510
  var MVCCStrategy2 = class {
4603
4511
  };
4512
+ var LRUMap3 = class {
4513
+ cache = /* @__PURE__ */ new Map();
4514
+ capacity;
4515
+ constructor(capacity) {
4516
+ this.capacity = capacity;
4517
+ }
4518
+ get(key) {
4519
+ if (!this.cache.has(key)) return void 0;
4520
+ const value = this.cache.get(key);
4521
+ this.cache.delete(key);
4522
+ this.cache.set(key, value);
4523
+ return value;
4524
+ }
4525
+ set(key, value) {
4526
+ if (this.cache.has(key)) {
4527
+ this.cache.delete(key);
4528
+ } else if (this.cache.size >= this.capacity) {
4529
+ const oldestKey = this.cache.keys().next().value;
4530
+ if (oldestKey !== void 0) this.cache.delete(oldestKey);
4531
+ }
4532
+ this.cache.set(key, value);
4533
+ return this;
4534
+ }
4535
+ has(key) {
4536
+ return this.cache.has(key);
4537
+ }
4538
+ delete(key) {
4539
+ return this.cache.delete(key);
4540
+ }
4541
+ clear() {
4542
+ this.cache.clear();
4543
+ }
4544
+ get size() {
4545
+ return this.cache.size;
4546
+ }
4547
+ };
4604
4548
  var MVCCTransaction2 = class {
4605
4549
  committed;
4606
4550
  snapshotVersion;
@@ -4608,7 +4552,6 @@ var MVCCTransaction2 = class {
4608
4552
  writeBuffer;
4609
4553
  deleteBuffer;
4610
4554
  createdKeys;
4611
- // create()로 생성된 키 추적
4612
4555
  deletedValues;
4613
4556
  // delete 시 삭제 전 값 저장
4614
4557
  originallyExisted;
@@ -4627,7 +4570,8 @@ var MVCCTransaction2 = class {
4627
4570
  versionIndex = /* @__PURE__ */ new Map();
4628
4571
  deletedCache = /* @__PURE__ */ new Map();
4629
4572
  activeTransactions = /* @__PURE__ */ new Set();
4630
- constructor(strategy, parent, snapshotVersion) {
4573
+ diskCache;
4574
+ constructor(strategy, options, parent, snapshotVersion) {
4631
4575
  this.snapshotVersion = snapshotVersion ?? 0;
4632
4576
  this.writeBuffer = /* @__PURE__ */ new Map();
4633
4577
  this.deleteBuffer = /* @__PURE__ */ new Set();
@@ -4642,6 +4586,7 @@ var MVCCTransaction2 = class {
4642
4586
  this.snapshotLocalVersion = parent.localVersion;
4643
4587
  this.strategy = void 0;
4644
4588
  this.root = parent.root;
4589
+ this.diskCache = parent.diskCache;
4645
4590
  } else {
4646
4591
  if (!strategy) throw new Error("Root Transaction must get Strategy");
4647
4592
  this.strategy = strategy;
@@ -4649,8 +4594,13 @@ var MVCCTransaction2 = class {
4649
4594
  this.localVersion = 0;
4650
4595
  this.snapshotLocalVersion = 0;
4651
4596
  this.root = this;
4597
+ this.diskCache = new LRUMap3(options?.cacheCapacity ?? 1e3);
4652
4598
  }
4653
4599
  }
4600
+ /**
4601
+ * Checks if the transaction is a root transaction.
4602
+ * @returns True if the transaction is a root transaction, false otherwise.
4603
+ */
4654
4604
  isRoot() {
4655
4605
  return !this.parent;
4656
4606
  }
@@ -4667,7 +4617,22 @@ var MVCCTransaction2 = class {
4667
4617
  }
4668
4618
  return false;
4669
4619
  }
4670
- // --- Internal buffer manipulation helpers ---
4620
+ /**
4621
+ * Checks if a key was written in this transaction.
4622
+ * @param key The key to check.
4623
+ * @returns True if the key was written in this transaction, false otherwise.
4624
+ */
4625
+ isWrote(key) {
4626
+ return this.writeBuffer.has(key);
4627
+ }
4628
+ /**
4629
+ * Checks if a key was deleted in this transaction.
4630
+ * @param key The key to check.
4631
+ * @returns True if the key was deleted in this transaction, false otherwise.
4632
+ */
4633
+ isDeleted(key) {
4634
+ return this.deleteBuffer.has(key);
4635
+ }
4671
4636
  _recordHistory(key) {
4672
4637
  const existsInWriteBuffer = this.writeBuffer.has(key);
4673
4638
  const existsInDeleteBuffer = this.deleteBuffer.has(key);
@@ -4681,6 +4646,41 @@ var MVCCTransaction2 = class {
4681
4646
  });
4682
4647
  }
4683
4648
  }
4649
+ /**
4650
+ * BINARY SEARCH HELPER: Finds the index of the last element in the array
4651
+ * where item[key] <= target. Assumes the array is sorted by 'key' ascending.
4652
+ */
4653
+ _findLastLE(array, target, property) {
4654
+ let left = 0;
4655
+ let right = array.length - 1;
4656
+ let result = -1;
4657
+ while (left <= right) {
4658
+ const mid = left + right >> 1;
4659
+ if (array[mid][property] <= target) {
4660
+ result = mid;
4661
+ left = mid + 1;
4662
+ } else {
4663
+ right = mid - 1;
4664
+ }
4665
+ }
4666
+ return result;
4667
+ }
4668
+ /**
4669
+ * BINARY SEARCH HELPER: Finds the index of the element in the array
4670
+ * where item[key] === target. Assumes the array is sorted by 'key' ascending.
4671
+ */
4672
+ _findExact(array, target, property) {
4673
+ let left = 0;
4674
+ let right = array.length - 1;
4675
+ while (left <= right) {
4676
+ const mid = left + right >> 1;
4677
+ const val = array[mid][property];
4678
+ if (val === target) return mid;
4679
+ if (val < target) left = mid + 1;
4680
+ else right = mid - 1;
4681
+ }
4682
+ return -1;
4683
+ }
4684
4684
  _bufferCreate(key, value, version) {
4685
4685
  if (version === void 0) this.localVersion++;
4686
4686
  const targetVersion = version ?? this.localVersion;
@@ -4730,7 +4730,11 @@ var MVCCTransaction2 = class {
4730
4730
  deleted.push({ key, data });
4731
4731
  }
4732
4732
  }
4733
- return { created, updated, deleted };
4733
+ return {
4734
+ created,
4735
+ updated,
4736
+ deleted
4737
+ };
4734
4738
  }
4735
4739
  /**
4736
4740
  * Rolls back the transaction.
@@ -4748,7 +4752,12 @@ var MVCCTransaction2 = class {
4748
4752
  if (this.root !== this) {
4749
4753
  this.root.activeTransactions.delete(this);
4750
4754
  }
4751
- return { success: true, created, updated, deleted };
4755
+ return {
4756
+ success: true,
4757
+ created,
4758
+ updated,
4759
+ deleted
4760
+ };
4752
4761
  }
4753
4762
  /**
4754
4763
  * Cleans up both deletedCache and versionIndex based on minActiveVersion.
@@ -4834,7 +4843,7 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4834
4843
  createNested() {
4835
4844
  if (this.committed) throw new Error("Transaction already committed");
4836
4845
  const childVersion = this.isRoot() ? this.version : this.snapshotVersion;
4837
- const child = new _SyncMVCCTransaction2(void 0, this, childVersion);
4846
+ const child = new _SyncMVCCTransaction2(void 0, void 0, this, childVersion);
4838
4847
  this.root.activeTransactions.add(child);
4839
4848
  return child;
4840
4849
  }
@@ -4857,78 +4866,114 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4857
4866
  return this._diskExists(key, this.snapshotVersion);
4858
4867
  }
4859
4868
  _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
- }
4869
+ let current = this;
4870
+ let slVer = snapshotLocalVersion;
4871
+ while (current) {
4872
+ if (current.writeBuffer.has(key)) {
4873
+ const keyModVersion = current.keyVersions.get(key);
4874
+ if (slVer === void 0 || keyModVersion <= slVer) return true;
4875
+ }
4876
+ if (current.deleteBuffer.has(key)) {
4877
+ const keyModVersion = current.keyVersions.get(key);
4878
+ if (slVer === void 0 || keyModVersion <= slVer) return false;
4879
+ }
4880
+ const history = current.bufferHistory.get(key);
4881
+ if (history && slVer !== void 0) {
4882
+ const idx = current._findLastLE(history, slVer, "version");
4883
+ if (idx >= 0) return history[idx].exists;
4884
+ }
4885
+ if (current.parent) {
4886
+ slVer = current.snapshotLocalVersion;
4887
+ current = current.parent;
4888
+ } else {
4889
+ return current._diskExists(key, snapshotVersion);
4878
4890
  }
4879
4891
  }
4880
- if (this.parent) {
4881
- return this.parent._existsSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
4882
- } else {
4883
- return this._diskExists(key, snapshotVersion);
4884
- }
4892
+ return false;
4885
4893
  }
4886
4894
  _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);
4895
+ let current = this;
4896
+ let slVer = snapshotLocalVersion;
4897
+ while (current) {
4898
+ if (current.writeBuffer.has(key)) {
4899
+ const keyModVersion = current.keyVersions.get(key);
4900
+ if (slVer === void 0 || keyModVersion <= slVer) {
4901
+ return current.writeBuffer.get(key);
4902
+ }
4891
4903
  }
4892
- }
4893
- if (this.deleteBuffer.has(key)) {
4894
- const keyModVersion = this.keyVersions.get(key);
4895
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
4896
- return null;
4904
+ if (current.deleteBuffer.has(key)) {
4905
+ const keyModVersion = current.keyVersions.get(key);
4906
+ if (slVer === void 0 || keyModVersion <= slVer) {
4907
+ return null;
4908
+ }
4897
4909
  }
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;
4910
+ const history = current.bufferHistory.get(key);
4911
+ if (history && slVer !== void 0) {
4912
+ const idx = current._findLastLE(history, slVer, "version");
4913
+ if (idx >= 0) {
4914
+ return history[idx].exists ? history[idx].value : null;
4904
4915
  }
4905
4916
  }
4917
+ if (current.parent) {
4918
+ slVer = current.snapshotLocalVersion;
4919
+ current = current.parent;
4920
+ } else {
4921
+ return current._diskRead(key, snapshotVersion);
4922
+ }
4906
4923
  }
4907
- if (this.parent) {
4908
- return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
4909
- } else {
4910
- return this._diskRead(key, snapshotVersion);
4911
- }
4924
+ return null;
4912
4925
  }
4913
4926
  commit(label) {
4914
4927
  const { created, updated, deleted } = this.getResultEntries();
4915
4928
  if (this.committed) {
4916
- return { label, success: false, error: "Transaction already committed", conflict: void 0, created, updated, deleted };
4929
+ return {
4930
+ label,
4931
+ success: false,
4932
+ error: "Transaction already committed",
4933
+ conflict: void 0,
4934
+ created,
4935
+ updated,
4936
+ deleted
4937
+ };
4917
4938
  }
4918
4939
  if (this.hasCommittedAncestor()) {
4919
- return { label, success: false, error: "Ancestor transaction already committed", conflict: void 0, created, updated, deleted };
4940
+ return {
4941
+ label,
4942
+ success: false,
4943
+ error: "Ancestor transaction already committed",
4944
+ conflict: void 0,
4945
+ created,
4946
+ updated,
4947
+ deleted
4948
+ };
4920
4949
  }
4921
4950
  if (this.parent) {
4922
4951
  const failure = this.parent._merge(this);
4923
4952
  if (failure) {
4924
- return { label, success: false, error: failure.error, conflict: failure.conflict, created, updated, deleted };
4953
+ return {
4954
+ label,
4955
+ success: false,
4956
+ error: failure.error,
4957
+ conflict: failure.conflict,
4958
+ created,
4959
+ updated,
4960
+ deleted
4961
+ };
4925
4962
  }
4926
4963
  this.committed = true;
4927
4964
  } else {
4928
4965
  if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
4929
4966
  const failure = this._merge(this);
4930
4967
  if (failure) {
4931
- return { label, success: false, error: failure.error, conflict: failure.conflict, created: [], updated: [], deleted: [] };
4968
+ return {
4969
+ label,
4970
+ success: false,
4971
+ error: failure.error,
4972
+ conflict: failure.conflict,
4973
+ created: [],
4974
+ updated: [],
4975
+ deleted: []
4976
+ };
4932
4977
  }
4933
4978
  this.writeBuffer.clear();
4934
4979
  this.deleteBuffer.clear();
@@ -4941,7 +4986,13 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4941
4986
  this.snapshotVersion = this.version;
4942
4987
  }
4943
4988
  }
4944
- return { label, success: true, created, updated, deleted };
4989
+ return {
4990
+ label,
4991
+ success: true,
4992
+ created,
4993
+ updated,
4994
+ deleted
4995
+ };
4945
4996
  }
4946
4997
  _merge(child) {
4947
4998
  if (this.parent) {
@@ -4950,7 +5001,11 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4950
5001
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
4951
5002
  return {
4952
5003
  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) }
5004
+ conflict: {
5005
+ key,
5006
+ parent: this.read(key),
5007
+ child: child.read(key)
5008
+ }
4954
5009
  };
4955
5010
  }
4956
5011
  }
@@ -4959,7 +5014,11 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4959
5014
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
4960
5015
  return {
4961
5016
  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) }
5017
+ conflict: {
5018
+ key,
5019
+ parent: this.read(key),
5020
+ child: child.read(key)
5021
+ }
4963
5022
  };
4964
5023
  }
4965
5024
  }
@@ -4988,7 +5047,11 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4988
5047
  if (lastVer > child.snapshotVersion) {
4989
5048
  return {
4990
5049
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (v${lastVer})`,
4991
- conflict: { key, parent: this.read(key), child: child.read(key) }
5050
+ conflict: {
5051
+ key,
5052
+ parent: this.read(key),
5053
+ child: child.read(key)
5054
+ }
4992
5055
  };
4993
5056
  }
4994
5057
  }
@@ -4996,7 +5059,11 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4996
5059
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
4997
5060
  return {
4998
5061
  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) }
5062
+ conflict: {
5063
+ key,
5064
+ parent: this.read(key),
5065
+ child: child.read(key)
5066
+ }
5000
5067
  };
5001
5068
  }
5002
5069
  }
@@ -5031,10 +5098,14 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
5031
5098
  _diskWrite(key, value, version) {
5032
5099
  const strategy = this.strategy;
5033
5100
  if (!strategy) throw new Error("Root Transaction missing strategy");
5034
- if (strategy.exists(key)) {
5035
- const currentVal = strategy.read(key);
5101
+ const rootAsAny = this.root;
5102
+ if (this._diskExists(key, version)) {
5103
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
5036
5104
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
5037
5105
  this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
5106
+ rootAsAny.diskCache.set(key, value);
5107
+ } else {
5108
+ rootAsAny.diskCache.set(key, value);
5038
5109
  }
5039
5110
  strategy.write(key, value);
5040
5111
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -5045,23 +5116,25 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
5045
5116
  if (!strategy) throw new Error("Root Transaction missing strategy");
5046
5117
  const versions = this.versionIndex.get(key);
5047
5118
  if (!versions) {
5048
- return strategy.exists(key) ? strategy.read(key) : null;
5119
+ const rootAsAny = this.root;
5120
+ if (this._diskExists(key, snapshotVersion)) {
5121
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
5122
+ rootAsAny.diskCache.set(key, val);
5123
+ return val;
5124
+ }
5125
+ return null;
5049
5126
  }
5050
5127
  let targetVerObj = null;
5051
5128
  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
- }
5129
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
5130
+ if (idx >= 0) targetVerObj = versions[idx];
5131
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
5059
5132
  if (!targetVerObj) {
5060
5133
  if (nextVerObj) {
5061
5134
  const cached2 = this.deletedCache.get(key);
5062
5135
  if (cached2) {
5063
- const match = cached2.find((c) => c.deletedAtVersion === nextVerObj.version);
5064
- if (match) return match.value;
5136
+ const cIdx = this._findExact(cached2, nextVerObj.version, "deletedAtVersion");
5137
+ if (cIdx >= 0) return cached2[cIdx].value;
5065
5138
  }
5066
5139
  }
5067
5140
  return null;
@@ -5069,12 +5142,18 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
5069
5142
  if (!targetVerObj.exists) return null;
5070
5143
  if (!nextVerObj) {
5071
5144
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
5072
- return strategy.read(key);
5145
+ if (this._diskExists(key, snapshotVersion)) {
5146
+ const rootAsAny = this.root;
5147
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
5148
+ rootAsAny.diskCache.set(key, val);
5149
+ return val;
5150
+ }
5151
+ return null;
5073
5152
  }
5074
5153
  const cached = this.deletedCache.get(key);
5075
5154
  if (cached) {
5076
- const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
5077
- if (match) return match.value;
5155
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
5156
+ if (cIdx >= 0) return cached[cIdx].value;
5078
5157
  }
5079
5158
  return null;
5080
5159
  }
@@ -5083,23 +5162,23 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
5083
5162
  if (!strategy) throw new Error("Root Transaction missing strategy");
5084
5163
  const versions = this.versionIndex.get(key);
5085
5164
  if (!versions) {
5086
- return strategy.exists(key);
5165
+ const rootAsAny = this.root;
5166
+ if (rootAsAny.diskCache.has(key)) return rootAsAny.diskCache.get(key) !== null;
5167
+ const exists = strategy.exists(key);
5168
+ if (!exists) rootAsAny.diskCache.set(key, null);
5169
+ return exists;
5087
5170
  }
5088
5171
  let targetVerObj = null;
5089
5172
  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
- }
5173
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
5174
+ if (idx >= 0) targetVerObj = versions[idx];
5175
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
5097
5176
  if (!targetVerObj) {
5098
5177
  if (nextVerObj) {
5099
5178
  const cached = this.deletedCache.get(key);
5100
5179
  if (cached) {
5101
- const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
5102
- if (match) return true;
5180
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
5181
+ if (cIdx >= 0) return true;
5103
5182
  }
5104
5183
  }
5105
5184
  return false;
@@ -5109,11 +5188,13 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
5109
5188
  _diskDelete(key, snapshotVersion) {
5110
5189
  const strategy = this.strategy;
5111
5190
  if (!strategy) throw new Error("Root Transaction missing strategy");
5112
- if (strategy.exists(key)) {
5113
- const currentVal = strategy.read(key);
5191
+ const rootAsAny = this.root;
5192
+ if (this._diskExists(key, snapshotVersion)) {
5193
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
5114
5194
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
5115
5195
  this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
5116
5196
  strategy.delete(key);
5197
+ rootAsAny.diskCache.delete(key);
5117
5198
  }
5118
5199
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
5119
5200
  this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });
@@ -5427,7 +5508,7 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5427
5508
  createNested() {
5428
5509
  if (this.committed) throw new Error("Transaction already committed");
5429
5510
  const childVersion = this.isRoot() ? this.version : this.snapshotVersion;
5430
- const child = new _AsyncMVCCTransaction2(void 0, this, childVersion);
5511
+ const child = new _AsyncMVCCTransaction2(void 0, void 0, this, childVersion);
5431
5512
  this.root.activeTransactions.add(child);
5432
5513
  return child;
5433
5514
  }
@@ -5450,78 +5531,114 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5450
5531
  return await this._diskExists(key, this.snapshotVersion);
5451
5532
  }
5452
5533
  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
- }
5534
+ let current = this;
5535
+ let slVer = snapshotLocalVersion;
5536
+ while (current) {
5537
+ if (current.writeBuffer.has(key)) {
5538
+ const keyModVersion = current.keyVersions.get(key);
5539
+ if (slVer === void 0 || keyModVersion <= slVer) return true;
5540
+ }
5541
+ if (current.deleteBuffer.has(key)) {
5542
+ const keyModVersion = current.keyVersions.get(key);
5543
+ if (slVer === void 0 || keyModVersion <= slVer) return false;
5544
+ }
5545
+ const history = current.bufferHistory.get(key);
5546
+ if (history && slVer !== void 0) {
5547
+ const idx = current._findLastLE(history, slVer, "version");
5548
+ if (idx >= 0) return history[idx].exists;
5549
+ }
5550
+ if (current.parent) {
5551
+ slVer = current.snapshotLocalVersion;
5552
+ current = current.parent;
5553
+ } else {
5554
+ return await current._diskExists(key, snapshotVersion);
5471
5555
  }
5472
5556
  }
5473
- if (this.parent) {
5474
- return this.parent._existsSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
5475
- } else {
5476
- return await this._diskExists(key, snapshotVersion);
5477
- }
5557
+ return false;
5478
5558
  }
5479
5559
  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);
5560
+ let current = this;
5561
+ let slVer = snapshotLocalVersion;
5562
+ while (current) {
5563
+ if (current.writeBuffer.has(key)) {
5564
+ const keyModVersion = current.keyVersions.get(key);
5565
+ if (slVer === void 0 || keyModVersion <= slVer) {
5566
+ return current.writeBuffer.get(key);
5567
+ }
5484
5568
  }
5485
- }
5486
- if (this.deleteBuffer.has(key)) {
5487
- const keyModVersion = this.keyVersions.get(key);
5488
- if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
5489
- return null;
5569
+ if (current.deleteBuffer.has(key)) {
5570
+ const keyModVersion = current.keyVersions.get(key);
5571
+ if (slVer === void 0 || keyModVersion <= slVer) {
5572
+ return null;
5573
+ }
5490
5574
  }
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;
5575
+ const history = current.bufferHistory.get(key);
5576
+ if (history && slVer !== void 0) {
5577
+ const idx = current._findLastLE(history, slVer, "version");
5578
+ if (idx >= 0) {
5579
+ return history[idx].exists ? history[idx].value : null;
5497
5580
  }
5498
5581
  }
5582
+ if (current.parent) {
5583
+ slVer = current.snapshotLocalVersion;
5584
+ current = current.parent;
5585
+ } else {
5586
+ return await current._diskRead(key, snapshotVersion);
5587
+ }
5499
5588
  }
5500
- if (this.parent) {
5501
- return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
5502
- } else {
5503
- return await this._diskRead(key, snapshotVersion);
5504
- }
5589
+ return null;
5505
5590
  }
5506
5591
  async commit(label) {
5507
5592
  const { created, updated, deleted } = this.getResultEntries();
5508
5593
  if (this.committed) {
5509
- return { label, success: false, error: "Transaction already committed", conflict: void 0, created, updated, deleted };
5594
+ return {
5595
+ label,
5596
+ success: false,
5597
+ error: "Transaction already committed",
5598
+ conflict: void 0,
5599
+ created,
5600
+ updated,
5601
+ deleted
5602
+ };
5510
5603
  }
5511
5604
  if (this.hasCommittedAncestor()) {
5512
- return { label, success: false, error: "Ancestor transaction already committed", conflict: void 0, created, updated, deleted };
5605
+ return {
5606
+ label,
5607
+ success: false,
5608
+ error: "Ancestor transaction already committed",
5609
+ conflict: void 0,
5610
+ created,
5611
+ updated,
5612
+ deleted
5613
+ };
5513
5614
  }
5514
5615
  if (this.parent) {
5515
5616
  const failure = await this.parent._merge(this);
5516
5617
  if (failure) {
5517
- return { label, success: false, error: failure.error, conflict: failure.conflict, created, updated, deleted };
5618
+ return {
5619
+ label,
5620
+ success: false,
5621
+ error: failure.error,
5622
+ conflict: failure.conflict,
5623
+ created,
5624
+ updated,
5625
+ deleted
5626
+ };
5518
5627
  }
5519
5628
  this.committed = true;
5520
5629
  } else {
5521
5630
  if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
5522
5631
  const failure = await this._merge(this);
5523
5632
  if (failure) {
5524
- return { label, success: false, error: failure.error, conflict: failure.conflict, created: [], updated: [], deleted: [] };
5633
+ return {
5634
+ label,
5635
+ success: false,
5636
+ error: failure.error,
5637
+ conflict: failure.conflict,
5638
+ created: [],
5639
+ updated: [],
5640
+ deleted: []
5641
+ };
5525
5642
  }
5526
5643
  this.writeBuffer.clear();
5527
5644
  this.deleteBuffer.clear();
@@ -5534,7 +5651,13 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5534
5651
  this.snapshotVersion = this.version;
5535
5652
  }
5536
5653
  }
5537
- return { label, success: true, created, updated, deleted };
5654
+ return {
5655
+ label,
5656
+ success: true,
5657
+ created,
5658
+ updated,
5659
+ deleted
5660
+ };
5538
5661
  }
5539
5662
  async _merge(child) {
5540
5663
  return this.writeLock(async () => {
@@ -5544,7 +5667,11 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5544
5667
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
5545
5668
  return {
5546
5669
  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) }
5670
+ conflict: {
5671
+ key,
5672
+ parent: await this.read(key),
5673
+ child: await child.read(key)
5674
+ }
5548
5675
  };
5549
5676
  }
5550
5677
  }
@@ -5553,7 +5680,11 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5553
5680
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
5554
5681
  return {
5555
5682
  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) }
5683
+ conflict: {
5684
+ key,
5685
+ parent: await this.read(key),
5686
+ child: await child.read(key)
5687
+ }
5557
5688
  };
5558
5689
  }
5559
5690
  }
@@ -5583,7 +5714,11 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5583
5714
  if (lastVer > child.snapshotVersion) {
5584
5715
  return {
5585
5716
  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) }
5717
+ conflict: {
5718
+ key,
5719
+ parent: await this.read(key),
5720
+ child: await child.read(key)
5721
+ }
5587
5722
  };
5588
5723
  }
5589
5724
  }
@@ -5591,7 +5726,11 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5591
5726
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
5592
5727
  return {
5593
5728
  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) }
5729
+ conflict: {
5730
+ key,
5731
+ parent: await this.read(key),
5732
+ child: await child.read(key)
5733
+ }
5595
5734
  };
5596
5735
  }
5597
5736
  }
@@ -5627,10 +5766,14 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5627
5766
  async _diskWrite(key, value, version) {
5628
5767
  const strategy = this.strategy;
5629
5768
  if (!strategy) throw new Error("Root Transaction missing strategy");
5630
- if (await strategy.exists(key)) {
5631
- const currentVal = await strategy.read(key);
5769
+ const rootAsAny = this.root;
5770
+ if (await this._diskExists(key, version)) {
5771
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
5632
5772
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
5633
5773
  this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
5774
+ rootAsAny.diskCache.set(key, value);
5775
+ } else {
5776
+ rootAsAny.diskCache.set(key, value);
5634
5777
  }
5635
5778
  await strategy.write(key, value);
5636
5779
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -5641,23 +5784,25 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5641
5784
  if (!strategy) throw new Error("Root Transaction missing strategy");
5642
5785
  const versions = this.versionIndex.get(key);
5643
5786
  if (!versions) {
5644
- return await strategy.exists(key) ? await strategy.read(key) : null;
5787
+ const rootAsAny = this.root;
5788
+ if (await this._diskExists(key, snapshotVersion)) {
5789
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
5790
+ rootAsAny.diskCache.set(key, val);
5791
+ return val;
5792
+ }
5793
+ return null;
5645
5794
  }
5646
5795
  let targetVerObj = null;
5647
5796
  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
- }
5797
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
5798
+ if (idx >= 0) targetVerObj = versions[idx];
5799
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
5655
5800
  if (!targetVerObj) {
5656
5801
  if (nextVerObj) {
5657
5802
  const cached2 = this.deletedCache.get(key);
5658
5803
  if (cached2) {
5659
- const match = cached2.find((c) => c.deletedAtVersion === nextVerObj.version);
5660
- if (match) return match.value;
5804
+ const cIdx = this._findExact(cached2, nextVerObj.version, "deletedAtVersion");
5805
+ if (cIdx >= 0) return cached2[cIdx].value;
5661
5806
  }
5662
5807
  }
5663
5808
  return null;
@@ -5665,12 +5810,18 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5665
5810
  if (!targetVerObj.exists) return null;
5666
5811
  if (!nextVerObj) {
5667
5812
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
5668
- return strategy.read(key);
5813
+ if (await this._diskExists(key, snapshotVersion)) {
5814
+ const rootAsAny = this.root;
5815
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
5816
+ rootAsAny.diskCache.set(key, val);
5817
+ return val;
5818
+ }
5819
+ return null;
5669
5820
  }
5670
5821
  const cached = this.deletedCache.get(key);
5671
5822
  if (cached) {
5672
- const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
5673
- if (match) return match.value;
5823
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
5824
+ if (cIdx >= 0) return cached[cIdx].value;
5674
5825
  }
5675
5826
  return null;
5676
5827
  }
@@ -5679,23 +5830,23 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5679
5830
  if (!strategy) throw new Error("Root Transaction missing strategy");
5680
5831
  const versions = this.versionIndex.get(key);
5681
5832
  if (!versions) {
5682
- return await strategy.exists(key);
5833
+ const rootAsAny = this.root;
5834
+ if (rootAsAny.diskCache.has(key)) return rootAsAny.diskCache.get(key) !== null;
5835
+ const exists = await strategy.exists(key);
5836
+ if (!exists) rootAsAny.diskCache.set(key, null);
5837
+ return exists;
5683
5838
  }
5684
5839
  let targetVerObj = null;
5685
5840
  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
- }
5841
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
5842
+ if (idx >= 0) targetVerObj = versions[idx];
5843
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
5693
5844
  if (!targetVerObj) {
5694
5845
  if (nextVerObj) {
5695
5846
  const cached = this.deletedCache.get(key);
5696
5847
  if (cached) {
5697
- const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
5698
- if (match) return true;
5848
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
5849
+ if (cIdx >= 0) return true;
5699
5850
  }
5700
5851
  }
5701
5852
  return false;
@@ -5705,11 +5856,13 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5705
5856
  async _diskDelete(key, snapshotVersion) {
5706
5857
  const strategy = this.strategy;
5707
5858
  if (!strategy) throw new Error("Root Transaction missing strategy");
5708
- if (await strategy.exists(key)) {
5709
- const currentVal = await strategy.read(key);
5859
+ const rootAsAny = this.root;
5860
+ if (await this._diskExists(key, snapshotVersion)) {
5861
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
5710
5862
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
5711
5863
  this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
5712
5864
  await strategy.delete(key);
5865
+ rootAsAny.diskCache.delete(key);
5713
5866
  }
5714
5867
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
5715
5868
  this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });