document-dataply 0.0.5 → 0.0.6

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 +1892 -1600
  2. package/package.json +2 -2
package/dist/cjs/index.js CHANGED
@@ -71,7 +71,7 @@ var require_cjs = __commonJS({
71
71
  BPTreeSyncTransaction: () => BPTreeSyncTransaction,
72
72
  BitmapPageManager: () => BitmapPageManager,
73
73
  CacheEntanglementAsync: () => CacheEntanglementAsync,
74
- CacheEntanglementSync: () => CacheEntanglementSync2,
74
+ CacheEntanglementSync: () => CacheEntanglementSync,
75
75
  DataPageManager: () => DataPageManager,
76
76
  Dataply: () => Dataply,
77
77
  DataplyAPI: () => DataplyAPI2,
@@ -156,6 +156,42 @@ var require_cjs = __commonJS({
156
156
  };
157
157
  var MVCCStrategy = class {
158
158
  };
159
+ var LRUMap = class {
160
+ cache = /* @__PURE__ */ new Map();
161
+ capacity;
162
+ constructor(capacity) {
163
+ this.capacity = capacity;
164
+ }
165
+ get(key) {
166
+ if (!this.cache.has(key)) return void 0;
167
+ const value = this.cache.get(key);
168
+ this.cache.delete(key);
169
+ this.cache.set(key, value);
170
+ return value;
171
+ }
172
+ set(key, value) {
173
+ if (this.cache.has(key)) {
174
+ this.cache.delete(key);
175
+ } else if (this.cache.size >= this.capacity) {
176
+ const oldestKey = this.cache.keys().next().value;
177
+ if (oldestKey !== void 0) this.cache.delete(oldestKey);
178
+ }
179
+ this.cache.set(key, value);
180
+ return this;
181
+ }
182
+ has(key) {
183
+ return this.cache.has(key);
184
+ }
185
+ delete(key) {
186
+ return this.cache.delete(key);
187
+ }
188
+ clear() {
189
+ this.cache.clear();
190
+ }
191
+ get size() {
192
+ return this.cache.size;
193
+ }
194
+ };
159
195
  var MVCCTransaction = class {
160
196
  committed;
161
197
  snapshotVersion;
@@ -163,11 +199,11 @@ var require_cjs = __commonJS({
163
199
  writeBuffer;
164
200
  deleteBuffer;
165
201
  createdKeys;
166
- // create()로 생성된 키 추적
167
202
  deletedValues;
168
203
  // delete 시 삭제 전 값 저장
169
204
  originallyExisted;
170
205
  // 트랜잭션 시작 시점에 디스크에 존재했던 키 (deleted 결과 필터링용)
206
+ bufferHistory = /* @__PURE__ */ new Map();
171
207
  // Nested Transaction Properties
172
208
  parent;
173
209
  localVersion;
@@ -181,7 +217,8 @@ var require_cjs = __commonJS({
181
217
  versionIndex = /* @__PURE__ */ new Map();
182
218
  deletedCache = /* @__PURE__ */ new Map();
183
219
  activeTransactions = /* @__PURE__ */ new Set();
184
- constructor(strategy, parent, snapshotVersion) {
220
+ diskCache;
221
+ constructor(strategy, options, parent, snapshotVersion) {
185
222
  this.snapshotVersion = snapshotVersion ?? 0;
186
223
  this.writeBuffer = /* @__PURE__ */ new Map();
187
224
  this.deleteBuffer = /* @__PURE__ */ new Set();
@@ -196,6 +233,7 @@ var require_cjs = __commonJS({
196
233
  this.snapshotLocalVersion = parent.localVersion;
197
234
  this.strategy = void 0;
198
235
  this.root = parent.root;
236
+ this.diskCache = parent.diskCache;
199
237
  } else {
200
238
  if (!strategy) throw new Error("Root Transaction must get Strategy");
201
239
  this.strategy = strategy;
@@ -203,8 +241,13 @@ var require_cjs = __commonJS({
203
241
  this.localVersion = 0;
204
242
  this.snapshotLocalVersion = 0;
205
243
  this.root = this;
244
+ this.diskCache = new LRUMap(options?.cacheCapacity ?? 1e3);
206
245
  }
207
246
  }
247
+ /**
248
+ * Checks if the transaction is a root transaction.
249
+ * @returns True if the transaction is a root transaction, false otherwise.
250
+ */
208
251
  isRoot() {
209
252
  return !this.parent;
210
253
  }
@@ -221,27 +264,96 @@ var require_cjs = __commonJS({
221
264
  }
222
265
  return false;
223
266
  }
224
- // --- Internal buffer manipulation helpers ---
225
- _bufferCreate(key, value) {
226
- this.localVersion++;
267
+ /**
268
+ * Checks if a key was written in this transaction.
269
+ * @param key The key to check.
270
+ * @returns True if the key was written in this transaction, false otherwise.
271
+ */
272
+ isWrote(key) {
273
+ return this.writeBuffer.has(key);
274
+ }
275
+ /**
276
+ * Checks if a key was deleted in this transaction.
277
+ * @param key The key to check.
278
+ * @returns True if the key was deleted in this transaction, false otherwise.
279
+ */
280
+ isDeleted(key) {
281
+ return this.deleteBuffer.has(key);
282
+ }
283
+ _recordHistory(key) {
284
+ const existsInWriteBuffer = this.writeBuffer.has(key);
285
+ const existsInDeleteBuffer = this.deleteBuffer.has(key);
286
+ const currentVer = this.keyVersions.get(key);
287
+ if (currentVer !== void 0) {
288
+ if (!this.bufferHistory.has(key)) this.bufferHistory.set(key, []);
289
+ this.bufferHistory.get(key).push({
290
+ value: existsInWriteBuffer ? this.writeBuffer.get(key) : this.deletedValues.get(key) ?? null,
291
+ exists: existsInWriteBuffer || !existsInDeleteBuffer,
292
+ version: currentVer
293
+ });
294
+ }
295
+ }
296
+ /**
297
+ * BINARY SEARCH HELPER: Finds the index of the last element in the array
298
+ * where item[key] <= target. Assumes the array is sorted by 'key' ascending.
299
+ */
300
+ _findLastLE(array, target, property) {
301
+ let left = 0;
302
+ let right = array.length - 1;
303
+ let result = -1;
304
+ while (left <= right) {
305
+ const mid = left + right >> 1;
306
+ if (array[mid][property] <= target) {
307
+ result = mid;
308
+ left = mid + 1;
309
+ } else {
310
+ right = mid - 1;
311
+ }
312
+ }
313
+ return result;
314
+ }
315
+ /**
316
+ * BINARY SEARCH HELPER: Finds the index of the element in the array
317
+ * where item[key] === target. Assumes the array is sorted by 'key' ascending.
318
+ */
319
+ _findExact(array, target, property) {
320
+ let left = 0;
321
+ let right = array.length - 1;
322
+ while (left <= right) {
323
+ const mid = left + right >> 1;
324
+ const val = array[mid][property];
325
+ if (val === target) return mid;
326
+ if (val < target) left = mid + 1;
327
+ else right = mid - 1;
328
+ }
329
+ return -1;
330
+ }
331
+ _bufferCreate(key, value, version) {
332
+ if (version === void 0) this.localVersion++;
333
+ const targetVersion = version ?? this.localVersion;
334
+ this._recordHistory(key);
227
335
  this.writeBuffer.set(key, value);
228
336
  this.createdKeys.add(key);
229
337
  this.deleteBuffer.delete(key);
230
338
  this.originallyExisted.delete(key);
231
- this.keyVersions.set(key, this.localVersion);
339
+ this.keyVersions.set(key, targetVersion);
232
340
  }
233
- _bufferWrite(key, value) {
234
- this.localVersion++;
341
+ _bufferWrite(key, value, version) {
342
+ if (version === void 0) this.localVersion++;
343
+ const targetVersion = version ?? this.localVersion;
344
+ this._recordHistory(key);
235
345
  this.writeBuffer.set(key, value);
236
346
  this.deleteBuffer.delete(key);
237
- this.keyVersions.set(key, this.localVersion);
347
+ this.keyVersions.set(key, targetVersion);
238
348
  }
239
- _bufferDelete(key) {
240
- this.localVersion++;
349
+ _bufferDelete(key, version) {
350
+ if (version === void 0) this.localVersion++;
351
+ const targetVersion = version ?? this.localVersion;
352
+ this._recordHistory(key);
241
353
  this.deleteBuffer.add(key);
242
354
  this.writeBuffer.delete(key);
243
355
  this.createdKeys.delete(key);
244
- this.keyVersions.set(key, this.localVersion);
356
+ this.keyVersions.set(key, targetVersion);
245
357
  }
246
358
  /**
247
359
  * Returns the entries that will be created, updated, and deleted by this transaction.
@@ -265,7 +377,11 @@ var require_cjs = __commonJS({
265
377
  deleted.push({ key, data });
266
378
  }
267
379
  }
268
- return { created, updated, deleted };
380
+ return {
381
+ created,
382
+ updated,
383
+ deleted
384
+ };
269
385
  }
270
386
  /**
271
387
  * Rolls back the transaction.
@@ -283,7 +399,36 @@ var require_cjs = __commonJS({
283
399
  if (this.root !== this) {
284
400
  this.root.activeTransactions.delete(this);
285
401
  }
286
- return { success: true, created, updated, deleted };
402
+ return {
403
+ success: true,
404
+ created,
405
+ updated,
406
+ deleted
407
+ };
408
+ }
409
+ /**
410
+ * Checks for conflicts among multiple transactions.
411
+ * A conflict occurs if two or more transactions modify (write or delete) the same key.
412
+ * @param transactions Array of transactions to check.
413
+ * @returns An array of keys that are in conflict.
414
+ */
415
+ static CheckConflicts(transactions) {
416
+ const modifiedKeys = /* @__PURE__ */ new Map();
417
+ const conflicts = /* @__PURE__ */ new Set();
418
+ for (const tx of transactions) {
419
+ const txModified = /* @__PURE__ */ new Set([
420
+ ...tx.writeBuffer.keys(),
421
+ ...tx.deleteBuffer
422
+ ]);
423
+ for (const key of txModified) {
424
+ const count = modifiedKeys.get(key) ?? 0;
425
+ if (count > 0) {
426
+ conflicts.add(key);
427
+ }
428
+ modifiedKeys.set(key, count + 1);
429
+ }
430
+ }
431
+ return Array.from(conflicts);
287
432
  }
288
433
  /**
289
434
  * Cleans up both deletedCache and versionIndex based on minActiveVersion.
@@ -318,7 +463,9 @@ var require_cjs = __commonJS({
318
463
  break;
319
464
  }
320
465
  }
321
- if (latestInSnapshotIdx > 0) {
466
+ if (latestInSnapshotIdx === versions.length - 1) {
467
+ this.versionIndex.delete(key);
468
+ } else if (latestInSnapshotIdx > 0) {
322
469
  versions.splice(0, latestInSnapshotIdx);
323
470
  }
324
471
  }
@@ -367,7 +514,7 @@ var require_cjs = __commonJS({
367
514
  createNested() {
368
515
  if (this.committed) throw new Error("Transaction already committed");
369
516
  const childVersion = this.isRoot() ? this.version : this.snapshotVersion;
370
- const child = new _SyncMVCCTransaction(void 0, this, childVersion);
517
+ const child = new _SyncMVCCTransaction(void 0, void 0, this, childVersion);
371
518
  this.root.activeTransactions.add(child);
372
519
  return child;
373
520
  }
@@ -375,32 +522,77 @@ var require_cjs = __commonJS({
375
522
  if (this.committed) throw new Error("Transaction already committed");
376
523
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
377
524
  if (this.deleteBuffer.has(key)) return null;
378
- return this.root._diskRead(key, this.snapshotVersion);
525
+ if (this.parent) {
526
+ return this.parent._readSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
527
+ }
528
+ return this._diskRead(key, this.snapshotVersion);
379
529
  }
380
530
  exists(key) {
381
531
  if (this.committed) throw new Error("Transaction already committed");
382
532
  if (this.deleteBuffer.has(key)) return false;
383
533
  if (this.writeBuffer.has(key)) return true;
384
- return this.root._diskExists(key, this.snapshotVersion);
534
+ if (this.parent) {
535
+ return this.parent._existsSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
536
+ }
537
+ return this._diskExists(key, this.snapshotVersion);
385
538
  }
386
- _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
387
- if (this.writeBuffer.has(key)) {
388
- const keyModVersion = this.keyVersions.get(key);
389
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
390
- return this.writeBuffer.get(key);
539
+ _existsSnapshot(key, snapshotVersion, snapshotLocalVersion) {
540
+ let current = this;
541
+ let slVer = snapshotLocalVersion;
542
+ while (current) {
543
+ if (current.writeBuffer.has(key)) {
544
+ const keyModVersion = current.keyVersions.get(key);
545
+ if (slVer === void 0 || keyModVersion <= slVer) return true;
546
+ }
547
+ if (current.deleteBuffer.has(key)) {
548
+ const keyModVersion = current.keyVersions.get(key);
549
+ if (slVer === void 0 || keyModVersion <= slVer) return false;
550
+ }
551
+ const history = current.bufferHistory.get(key);
552
+ if (history && slVer !== void 0) {
553
+ const idx = current._findLastLE(history, slVer, "version");
554
+ if (idx >= 0) return history[idx].exists;
555
+ }
556
+ if (current.parent) {
557
+ slVer = current.snapshotLocalVersion;
558
+ current = current.parent;
559
+ } else {
560
+ return current._diskExists(key, snapshotVersion);
391
561
  }
392
562
  }
393
- if (this.deleteBuffer.has(key)) {
394
- const keyModVersion = this.keyVersions.get(key);
395
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
396
- return null;
563
+ return false;
564
+ }
565
+ _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
566
+ let current = this;
567
+ let slVer = snapshotLocalVersion;
568
+ while (current) {
569
+ if (current.writeBuffer.has(key)) {
570
+ const keyModVersion = current.keyVersions.get(key);
571
+ if (slVer === void 0 || keyModVersion <= slVer) {
572
+ return current.writeBuffer.get(key);
573
+ }
574
+ }
575
+ if (current.deleteBuffer.has(key)) {
576
+ const keyModVersion = current.keyVersions.get(key);
577
+ if (slVer === void 0 || keyModVersion <= slVer) {
578
+ return null;
579
+ }
580
+ }
581
+ const history = current.bufferHistory.get(key);
582
+ if (history && slVer !== void 0) {
583
+ const idx = current._findLastLE(history, slVer, "version");
584
+ if (idx >= 0) {
585
+ return history[idx].exists ? history[idx].value : null;
586
+ }
587
+ }
588
+ if (current.parent) {
589
+ slVer = current.snapshotLocalVersion;
590
+ current = current.parent;
591
+ } else {
592
+ return current._diskRead(key, snapshotVersion);
397
593
  }
398
594
  }
399
- if (this.parent) {
400
- return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
401
- } else {
402
- return this._diskRead(key, snapshotVersion);
403
- }
595
+ return null;
404
596
  }
405
597
  commit(label) {
406
598
  const { created, updated, deleted } = this.getResultEntries();
@@ -460,6 +652,7 @@ var require_cjs = __commonJS({
460
652
  this.deletedValues.clear();
461
653
  this.originallyExisted.clear();
462
654
  this.keyVersions.clear();
655
+ this.bufferHistory.clear();
463
656
  this.localVersion = 0;
464
657
  this.snapshotVersion = this.version;
465
658
  }
@@ -500,32 +693,22 @@ var require_cjs = __commonJS({
500
693
  };
501
694
  }
502
695
  }
503
- const newLocalVersion = this.localVersion + 1;
504
- for (const key of child.writeBuffer.keys()) {
505
- this.writeBuffer.set(key, child.writeBuffer.get(key));
506
- this.deleteBuffer.delete(key);
507
- this.keyVersions.set(key, newLocalVersion);
508
- if (child.createdKeys.has(key)) {
509
- this.createdKeys.add(key);
510
- }
696
+ const mergeVersion = ++this.localVersion;
697
+ for (const [key, value] of child.writeBuffer) {
698
+ const wasCreated = child.createdKeys.has(key);
699
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
700
+ else this._bufferWrite(key, value, mergeVersion);
511
701
  }
512
702
  for (const key of child.deleteBuffer) {
513
- this.deleteBuffer.add(key);
514
- this.writeBuffer.delete(key);
515
- this.createdKeys.delete(key);
516
- this.keyVersions.set(key, newLocalVersion);
517
703
  const deletedValue = child.deletedValues.get(key);
518
- if (deletedValue !== void 0) {
519
- this.deletedValues.set(key, deletedValue);
520
- }
521
- if (child.originallyExisted.has(key)) {
704
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
705
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
522
706
  this.originallyExisted.add(key);
523
707
  }
708
+ this._bufferDelete(key, mergeVersion);
524
709
  }
525
- this.localVersion = newLocalVersion;
526
710
  this.root.activeTransactions.delete(child);
527
711
  } else {
528
- const newVersion = this.version + 1;
529
712
  if (child !== this) {
530
713
  const modifiedKeys = /* @__PURE__ */ new Set([...child.writeBuffer.keys(), ...child.deleteBuffer]);
531
714
  for (const key of modifiedKeys) {
@@ -543,50 +726,57 @@ var require_cjs = __commonJS({
543
726
  };
544
727
  }
545
728
  }
729
+ const lastModLocalVer = this.keyVersions.get(key);
730
+ if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
731
+ return {
732
+ error: `Commit conflict: Key '${key}' was modified by a newer transaction in the same session (Local v${lastModLocalVer})`,
733
+ conflict: {
734
+ key,
735
+ parent: this.read(key),
736
+ child: child.read(key)
737
+ }
738
+ };
739
+ }
546
740
  }
547
- }
548
- for (const [key, value] of child.writeBuffer) {
549
- this.writeBuffer.set(key, value);
550
- this.deleteBuffer.delete(key);
551
- if (child.createdKeys.has(key)) {
552
- this.createdKeys.add(key);
553
- }
554
- }
555
- for (const key of child.deleteBuffer) {
556
- this.deleteBuffer.add(key);
557
- this.writeBuffer.delete(key);
558
- this.createdKeys.delete(key);
559
- const deletedValue = child.deletedValues.get(key);
560
- if (deletedValue !== void 0) {
561
- this.deletedValues.set(key, deletedValue);
741
+ const mergeVersion = ++this.localVersion;
742
+ for (const [key, value] of child.writeBuffer) {
743
+ const wasCreated = child.createdKeys.has(key);
744
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
745
+ this.originallyExisted.add(key);
746
+ }
747
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
748
+ else this._bufferWrite(key, value, mergeVersion);
562
749
  }
563
- if (child.originallyExisted.has(key)) {
564
- this.originallyExisted.add(key);
750
+ for (const key of child.deleteBuffer) {
751
+ const deletedValue = child.deletedValues.get(key);
752
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
753
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
754
+ this.originallyExisted.add(key);
755
+ }
756
+ this._bufferDelete(key, mergeVersion);
565
757
  }
758
+ this.root.activeTransactions.delete(child);
759
+ } else {
760
+ const newVersion = this.version + 1;
761
+ for (const [key, value] of this.writeBuffer) this._diskWrite(key, value, newVersion);
762
+ for (const key of this.deleteBuffer) this._diskDelete(key, newVersion);
763
+ this.version = newVersion;
764
+ this._cleanupDeletedCache();
566
765
  }
567
- for (const [key, value] of child.writeBuffer) {
568
- this._diskWrite(key, value, newVersion);
569
- }
570
- for (const key of child.deleteBuffer) {
571
- this._diskDelete(key, newVersion);
572
- }
573
- this.version = newVersion;
574
- this.root.activeTransactions.delete(child);
575
- this._cleanupDeletedCache();
576
766
  }
577
767
  return null;
578
768
  }
579
- // --- Internal IO Helpers (Root Only) ---
580
769
  _diskWrite(key, value, version) {
581
770
  const strategy = this.strategy;
582
771
  if (!strategy) throw new Error("Root Transaction missing strategy");
583
- if (strategy.exists(key)) {
584
- const currentVal = strategy.read(key);
772
+ const rootAsAny = this.root;
773
+ if (this._diskExists(key, version)) {
774
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
585
775
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
586
- this.deletedCache.get(key).push({
587
- value: currentVal,
588
- deletedAtVersion: version
589
- });
776
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
777
+ rootAsAny.diskCache.set(key, value);
778
+ } else {
779
+ rootAsAny.diskCache.set(key, value);
590
780
  }
591
781
  strategy.write(key, value);
592
782
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -597,36 +787,44 @@ var require_cjs = __commonJS({
597
787
  if (!strategy) throw new Error("Root Transaction missing strategy");
598
788
  const versions = this.versionIndex.get(key);
599
789
  if (!versions) {
600
- return strategy.exists(key) ? strategy.read(key) : null;
790
+ const rootAsAny = this.root;
791
+ if (this._diskExists(key, snapshotVersion)) {
792
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
793
+ rootAsAny.diskCache.set(key, val);
794
+ return val;
795
+ }
796
+ return null;
601
797
  }
602
798
  let targetVerObj = null;
603
799
  let nextVerObj = null;
604
- for (const v of versions) {
605
- if (v.version <= snapshotVersion) {
606
- targetVerObj = v;
607
- } else {
608
- nextVerObj = v;
609
- break;
610
- }
611
- }
800
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
801
+ if (idx >= 0) targetVerObj = versions[idx];
802
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
612
803
  if (!targetVerObj) {
613
804
  if (nextVerObj) {
614
805
  const cached2 = this.deletedCache.get(key);
615
806
  if (cached2) {
616
- const match = cached2.find((c) => c.deletedAtVersion === nextVerObj.version);
617
- if (match) return match.value;
807
+ const cIdx = this._findExact(cached2, nextVerObj.version, "deletedAtVersion");
808
+ if (cIdx >= 0) return cached2[cIdx].value;
618
809
  }
619
810
  }
620
811
  return null;
621
812
  }
622
813
  if (!targetVerObj.exists) return null;
623
814
  if (!nextVerObj) {
624
- return strategy.read(key);
815
+ if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
816
+ if (this._diskExists(key, snapshotVersion)) {
817
+ const rootAsAny = this.root;
818
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
819
+ rootAsAny.diskCache.set(key, val);
820
+ return val;
821
+ }
822
+ return null;
625
823
  }
626
824
  const cached = this.deletedCache.get(key);
627
825
  if (cached) {
628
- const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
629
- if (match) return match.value;
826
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
827
+ if (cIdx >= 0) return cached[cIdx].value;
630
828
  }
631
829
  return null;
632
830
  }
@@ -635,31 +833,40 @@ var require_cjs = __commonJS({
635
833
  if (!strategy) throw new Error("Root Transaction missing strategy");
636
834
  const versions = this.versionIndex.get(key);
637
835
  if (!versions) {
638
- return strategy.exists(key);
836
+ const rootAsAny = this.root;
837
+ if (rootAsAny.diskCache.has(key)) return rootAsAny.diskCache.get(key) !== null;
838
+ const exists = strategy.exists(key);
839
+ if (!exists) rootAsAny.diskCache.set(key, null);
840
+ return exists;
639
841
  }
640
842
  let targetVerObj = null;
641
- for (const v of versions) {
642
- if (v.version <= snapshotVersion) {
643
- targetVerObj = v;
644
- } else {
645
- break;
843
+ let nextVerObj = null;
844
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
845
+ if (idx >= 0) targetVerObj = versions[idx];
846
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
847
+ if (!targetVerObj) {
848
+ if (nextVerObj) {
849
+ const cached = this.deletedCache.get(key);
850
+ if (cached) {
851
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
852
+ if (cIdx >= 0) return true;
853
+ }
646
854
  }
855
+ return false;
647
856
  }
648
- if (!targetVerObj) return strategy.exists(key);
649
857
  return targetVerObj.exists;
650
858
  }
651
859
  _diskDelete(key, snapshotVersion) {
652
860
  const strategy = this.strategy;
653
861
  if (!strategy) throw new Error("Root Transaction missing strategy");
654
- if (strategy.exists(key)) {
655
- const currentVal = strategy.read(key);
862
+ const rootAsAny = this.root;
863
+ if (this._diskExists(key, snapshotVersion)) {
864
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
656
865
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
657
- this.deletedCache.get(key).push({
658
- value: currentVal,
659
- deletedAtVersion: snapshotVersion
660
- });
866
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
867
+ strategy.delete(key);
868
+ rootAsAny.diskCache.delete(key);
661
869
  }
662
- strategy.delete(key);
663
870
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
664
871
  this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });
665
872
  }
@@ -972,7 +1179,7 @@ var require_cjs = __commonJS({
972
1179
  createNested() {
973
1180
  if (this.committed) throw new Error("Transaction already committed");
974
1181
  const childVersion = this.isRoot() ? this.version : this.snapshotVersion;
975
- const child = new _AsyncMVCCTransaction(void 0, this, childVersion);
1182
+ const child = new _AsyncMVCCTransaction(void 0, void 0, this, childVersion);
976
1183
  this.root.activeTransactions.add(child);
977
1184
  return child;
978
1185
  }
@@ -980,32 +1187,77 @@ var require_cjs = __commonJS({
980
1187
  if (this.committed) throw new Error("Transaction already committed");
981
1188
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
982
1189
  if (this.deleteBuffer.has(key)) return null;
983
- return this.root._diskRead(key, this.snapshotVersion);
1190
+ if (this.parent) {
1191
+ return this.parent._readSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
1192
+ }
1193
+ return await this._diskRead(key, this.snapshotVersion);
984
1194
  }
985
1195
  async exists(key) {
986
1196
  if (this.committed) throw new Error("Transaction already committed");
987
1197
  if (this.deleteBuffer.has(key)) return false;
988
1198
  if (this.writeBuffer.has(key)) return true;
989
- return this.root._diskExists(key, this.snapshotVersion);
1199
+ if (this.parent) {
1200
+ return this.parent._existsSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
1201
+ }
1202
+ return await this._diskExists(key, this.snapshotVersion);
990
1203
  }
991
- async _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
992
- if (this.writeBuffer.has(key)) {
993
- const keyModVersion = this.keyVersions.get(key);
994
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
995
- return this.writeBuffer.get(key);
1204
+ async _existsSnapshot(key, snapshotVersion, snapshotLocalVersion) {
1205
+ let current = this;
1206
+ let slVer = snapshotLocalVersion;
1207
+ while (current) {
1208
+ if (current.writeBuffer.has(key)) {
1209
+ const keyModVersion = current.keyVersions.get(key);
1210
+ if (slVer === void 0 || keyModVersion <= slVer) return true;
1211
+ }
1212
+ if (current.deleteBuffer.has(key)) {
1213
+ const keyModVersion = current.keyVersions.get(key);
1214
+ if (slVer === void 0 || keyModVersion <= slVer) return false;
1215
+ }
1216
+ const history = current.bufferHistory.get(key);
1217
+ if (history && slVer !== void 0) {
1218
+ const idx = current._findLastLE(history, slVer, "version");
1219
+ if (idx >= 0) return history[idx].exists;
1220
+ }
1221
+ if (current.parent) {
1222
+ slVer = current.snapshotLocalVersion;
1223
+ current = current.parent;
1224
+ } else {
1225
+ return await current._diskExists(key, snapshotVersion);
996
1226
  }
997
1227
  }
998
- if (this.deleteBuffer.has(key)) {
999
- const keyModVersion = this.keyVersions.get(key);
1000
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
1001
- return null;
1228
+ return false;
1229
+ }
1230
+ async _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
1231
+ let current = this;
1232
+ let slVer = snapshotLocalVersion;
1233
+ while (current) {
1234
+ if (current.writeBuffer.has(key)) {
1235
+ const keyModVersion = current.keyVersions.get(key);
1236
+ if (slVer === void 0 || keyModVersion <= slVer) {
1237
+ return current.writeBuffer.get(key);
1238
+ }
1239
+ }
1240
+ if (current.deleteBuffer.has(key)) {
1241
+ const keyModVersion = current.keyVersions.get(key);
1242
+ if (slVer === void 0 || keyModVersion <= slVer) {
1243
+ return null;
1244
+ }
1245
+ }
1246
+ const history = current.bufferHistory.get(key);
1247
+ if (history && slVer !== void 0) {
1248
+ const idx = current._findLastLE(history, slVer, "version");
1249
+ if (idx >= 0) {
1250
+ return history[idx].exists ? history[idx].value : null;
1251
+ }
1252
+ }
1253
+ if (current.parent) {
1254
+ slVer = current.snapshotLocalVersion;
1255
+ current = current.parent;
1256
+ } else {
1257
+ return await current._diskRead(key, snapshotVersion);
1002
1258
  }
1003
1259
  }
1004
- if (this.parent) {
1005
- return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
1006
- } else {
1007
- return this._diskRead(key, snapshotVersion);
1008
- }
1260
+ return null;
1009
1261
  }
1010
1262
  async commit(label) {
1011
1263
  const { created, updated, deleted } = this.getResultEntries();
@@ -1065,6 +1317,7 @@ var require_cjs = __commonJS({
1065
1317
  this.deletedValues.clear();
1066
1318
  this.originallyExisted.clear();
1067
1319
  this.keyVersions.clear();
1320
+ this.bufferHistory.clear();
1068
1321
  this.localVersion = 0;
1069
1322
  this.snapshotVersion = this.version;
1070
1323
  }
@@ -1106,33 +1359,23 @@ var require_cjs = __commonJS({
1106
1359
  };
1107
1360
  }
1108
1361
  }
1109
- const newLocalVersion = this.localVersion + 1;
1110
- for (const key of child.writeBuffer.keys()) {
1111
- this.writeBuffer.set(key, child.writeBuffer.get(key));
1112
- this.deleteBuffer.delete(key);
1113
- this.keyVersions.set(key, newLocalVersion);
1114
- if (child.createdKeys.has(key)) {
1115
- this.createdKeys.add(key);
1116
- }
1362
+ const mergeVersion = ++this.localVersion;
1363
+ for (const [key, value] of child.writeBuffer) {
1364
+ const wasCreated = child.createdKeys.has(key);
1365
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
1366
+ else this._bufferWrite(key, value, mergeVersion);
1117
1367
  }
1118
1368
  for (const key of child.deleteBuffer) {
1119
- this.deleteBuffer.add(key);
1120
- this.writeBuffer.delete(key);
1121
- this.createdKeys.delete(key);
1122
- this.keyVersions.set(key, newLocalVersion);
1123
1369
  const deletedValue = child.deletedValues.get(key);
1124
- if (deletedValue !== void 0) {
1125
- this.deletedValues.set(key, deletedValue);
1126
- }
1127
- if (child.originallyExisted.has(key)) {
1370
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
1371
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
1128
1372
  this.originallyExisted.add(key);
1129
1373
  }
1374
+ this._bufferDelete(key, mergeVersion);
1130
1375
  }
1131
- this.localVersion = newLocalVersion;
1132
1376
  this.root.activeTransactions.delete(child);
1133
1377
  return null;
1134
1378
  } else {
1135
- const newVersion = this.version + 1;
1136
1379
  if (child !== this) {
1137
1380
  const modifiedKeys = /* @__PURE__ */ new Set([...child.writeBuffer.keys(), ...child.deleteBuffer]);
1138
1381
  for (const key of modifiedKeys) {
@@ -1150,51 +1393,58 @@ var require_cjs = __commonJS({
1150
1393
  };
1151
1394
  }
1152
1395
  }
1396
+ const lastModLocalVer = this.keyVersions.get(key);
1397
+ if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
1398
+ return {
1399
+ error: `Commit conflict: Key '${key}' was modified by a newer transaction in the same session (Local v${lastModLocalVer})`,
1400
+ conflict: {
1401
+ key,
1402
+ parent: await this.read(key),
1403
+ child: await child.read(key)
1404
+ }
1405
+ };
1406
+ }
1153
1407
  }
1154
- }
1155
- for (const [key, value] of child.writeBuffer) {
1156
- this.writeBuffer.set(key, value);
1157
- this.deleteBuffer.delete(key);
1158
- if (child.createdKeys.has(key)) {
1159
- this.createdKeys.add(key);
1160
- }
1161
- }
1162
- for (const key of child.deleteBuffer) {
1163
- this.deleteBuffer.add(key);
1164
- this.writeBuffer.delete(key);
1165
- this.createdKeys.delete(key);
1166
- const deletedValue = child.deletedValues.get(key);
1167
- if (deletedValue !== void 0) {
1168
- this.deletedValues.set(key, deletedValue);
1408
+ const mergeVersion = ++this.localVersion;
1409
+ for (const [key, value] of child.writeBuffer) {
1410
+ const wasCreated = child.createdKeys.has(key);
1411
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
1412
+ this.originallyExisted.add(key);
1413
+ }
1414
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
1415
+ else this._bufferWrite(key, value, mergeVersion);
1169
1416
  }
1170
- if (child.originallyExisted.has(key)) {
1171
- this.originallyExisted.add(key);
1417
+ for (const key of child.deleteBuffer) {
1418
+ const deletedValue = child.deletedValues.get(key);
1419
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
1420
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
1421
+ this.originallyExisted.add(key);
1422
+ }
1423
+ this._bufferDelete(key, mergeVersion);
1172
1424
  }
1425
+ this.root.activeTransactions.delete(child);
1426
+ } else {
1427
+ const newVersion = this.version + 1;
1428
+ for (const [key, value] of this.writeBuffer) await this._diskWrite(key, value, newVersion);
1429
+ for (const key of this.deleteBuffer) await this._diskDelete(key, newVersion);
1430
+ this.version = newVersion;
1431
+ this._cleanupDeletedCache();
1173
1432
  }
1174
- for (const [key, value] of child.writeBuffer) {
1175
- await this._diskWrite(key, value, newVersion);
1176
- }
1177
- for (const key of child.deleteBuffer) {
1178
- await this._diskDelete(key, newVersion);
1179
- }
1180
- this.version = newVersion;
1181
- this.root.activeTransactions.delete(child);
1182
- this._cleanupDeletedCache();
1183
1433
  return null;
1184
1434
  }
1185
1435
  });
1186
1436
  }
1187
- // --- Internal IO Helpers (Root Only) ---
1188
1437
  async _diskWrite(key, value, version) {
1189
1438
  const strategy = this.strategy;
1190
1439
  if (!strategy) throw new Error("Root Transaction missing strategy");
1191
- if (await strategy.exists(key)) {
1192
- const currentVal = await strategy.read(key);
1440
+ const rootAsAny = this.root;
1441
+ if (await this._diskExists(key, version)) {
1442
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
1193
1443
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
1194
- this.deletedCache.get(key).push({
1195
- value: currentVal,
1196
- deletedAtVersion: version
1197
- });
1444
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
1445
+ rootAsAny.diskCache.set(key, value);
1446
+ } else {
1447
+ rootAsAny.diskCache.set(key, value);
1198
1448
  }
1199
1449
  await strategy.write(key, value);
1200
1450
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -1205,36 +1455,44 @@ var require_cjs = __commonJS({
1205
1455
  if (!strategy) throw new Error("Root Transaction missing strategy");
1206
1456
  const versions = this.versionIndex.get(key);
1207
1457
  if (!versions) {
1208
- return await strategy.exists(key) ? strategy.read(key) : null;
1458
+ const rootAsAny = this.root;
1459
+ if (await this._diskExists(key, snapshotVersion)) {
1460
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
1461
+ rootAsAny.diskCache.set(key, val);
1462
+ return val;
1463
+ }
1464
+ return null;
1209
1465
  }
1210
1466
  let targetVerObj = null;
1211
1467
  let nextVerObj = null;
1212
- for (const v of versions) {
1213
- if (v.version <= snapshotVersion) {
1214
- targetVerObj = v;
1215
- } else {
1216
- nextVerObj = v;
1217
- break;
1218
- }
1219
- }
1468
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
1469
+ if (idx >= 0) targetVerObj = versions[idx];
1470
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
1220
1471
  if (!targetVerObj) {
1221
1472
  if (nextVerObj) {
1222
1473
  const cached2 = this.deletedCache.get(key);
1223
1474
  if (cached2) {
1224
- const match = cached2.find((c) => c.deletedAtVersion === nextVerObj.version);
1225
- if (match) return match.value;
1475
+ const cIdx = this._findExact(cached2, nextVerObj.version, "deletedAtVersion");
1476
+ if (cIdx >= 0) return cached2[cIdx].value;
1226
1477
  }
1227
1478
  }
1228
1479
  return null;
1229
1480
  }
1230
1481
  if (!targetVerObj.exists) return null;
1231
1482
  if (!nextVerObj) {
1232
- return strategy.read(key);
1483
+ if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
1484
+ if (await this._diskExists(key, snapshotVersion)) {
1485
+ const rootAsAny = this.root;
1486
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
1487
+ rootAsAny.diskCache.set(key, val);
1488
+ return val;
1489
+ }
1490
+ return null;
1233
1491
  }
1234
1492
  const cached = this.deletedCache.get(key);
1235
1493
  if (cached) {
1236
- const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
1237
- if (match) return match.value;
1494
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
1495
+ if (cIdx >= 0) return cached[cIdx].value;
1238
1496
  }
1239
1497
  return null;
1240
1498
  }
@@ -1243,359 +1501,47 @@ var require_cjs = __commonJS({
1243
1501
  if (!strategy) throw new Error("Root Transaction missing strategy");
1244
1502
  const versions = this.versionIndex.get(key);
1245
1503
  if (!versions) {
1246
- return strategy.exists(key);
1504
+ const rootAsAny = this.root;
1505
+ if (rootAsAny.diskCache.has(key)) return rootAsAny.diskCache.get(key) !== null;
1506
+ const exists = await strategy.exists(key);
1507
+ if (!exists) rootAsAny.diskCache.set(key, null);
1508
+ return exists;
1247
1509
  }
1248
1510
  let targetVerObj = null;
1249
- for (const v of versions) {
1250
- if (v.version <= snapshotVersion) {
1251
- targetVerObj = v;
1252
- } else {
1253
- break;
1511
+ let nextVerObj = null;
1512
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
1513
+ if (idx >= 0) targetVerObj = versions[idx];
1514
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
1515
+ if (!targetVerObj) {
1516
+ if (nextVerObj) {
1517
+ const cached = this.deletedCache.get(key);
1518
+ if (cached) {
1519
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
1520
+ if (cIdx >= 0) return true;
1521
+ }
1254
1522
  }
1523
+ return false;
1255
1524
  }
1256
- if (!targetVerObj) return strategy.exists(key);
1257
1525
  return targetVerObj.exists;
1258
1526
  }
1259
1527
  async _diskDelete(key, snapshotVersion) {
1260
1528
  const strategy = this.strategy;
1261
1529
  if (!strategy) throw new Error("Root Transaction missing strategy");
1262
- if (await strategy.exists(key)) {
1263
- const currentVal = await strategy.read(key);
1530
+ const rootAsAny = this.root;
1531
+ if (await this._diskExists(key, snapshotVersion)) {
1532
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
1264
1533
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
1265
- this.deletedCache.get(key).push({
1266
- value: currentVal,
1267
- deletedAtVersion: snapshotVersion
1268
- });
1534
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
1535
+ await strategy.delete(key);
1536
+ rootAsAny.diskCache.delete(key);
1269
1537
  }
1270
- await strategy.delete(key);
1271
1538
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
1272
1539
  this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });
1273
1540
  }
1274
1541
  };
1275
- var LRUMap = class {
1276
- capacity;
1277
- map;
1278
- head = null;
1279
- tail = null;
1280
- /**
1281
- * Creates an instance of LRUMap.
1282
- * @param capacity The maximum number of items the cache can hold.
1283
- */
1284
- constructor(capacity) {
1285
- this.capacity = capacity;
1286
- this.map = /* @__PURE__ */ new Map();
1287
- }
1288
- /**
1289
- * Promotes a node to the head of the linked list (marks as most recently used).
1290
- * @param node The node to promote.
1291
- */
1292
- promote(node) {
1293
- this.extract(node);
1294
- this.prepend(node);
1295
- }
1296
- /**
1297
- * Disconnects a node from the doubly linked list.
1298
- * @param node The node to extract.
1299
- */
1300
- extract(node) {
1301
- if (node.prev) node.prev.next = node.next;
1302
- else this.head = node.next;
1303
- if (node.next) node.next.prev = node.prev;
1304
- else this.tail = node.prev;
1305
- node.prev = null;
1306
- node.next = null;
1307
- }
1308
- /**
1309
- * Inserts a node at the head of the doubly linked list.
1310
- * @param node The node to prepend.
1311
- */
1312
- prepend(node) {
1313
- node.next = this.head;
1314
- if (this.head) this.head.prev = node;
1315
- this.head = node;
1316
- if (!this.tail) this.tail = node;
1317
- }
1318
- /**
1319
- * Stores or updates a value by key.
1320
- * If the capacity is exceeded, the least recently used item (tail) is removed.
1321
- * @param key The key to store.
1322
- * @param value The value to store.
1323
- */
1324
- set(key, value) {
1325
- const existing = this.map.get(key);
1326
- if (existing) {
1327
- existing.value = value;
1328
- this.promote(existing);
1329
- return;
1330
- }
1331
- const newNode = { key, value, prev: null, next: null };
1332
- this.map.set(key, newNode);
1333
- this.prepend(newNode);
1334
- if (this.map.size > this.capacity && this.tail) {
1335
- this.map.delete(this.tail.key);
1336
- this.extract(this.tail);
1337
- }
1338
- }
1339
- /**
1340
- * Retrieves a value by key.
1341
- * Accessing the item moves it to the "most recently used" position.
1342
- * @param key The key to look for.
1343
- * @returns The value associated with the key, or undefined if not found.
1344
- */
1345
- get(key) {
1346
- const node = this.map.get(key);
1347
- if (!node) return void 0;
1348
- this.promote(node);
1349
- return node.value;
1350
- }
1351
- /**
1352
- * Checks if a key exists in the cache without changing its access order.
1353
- * @param key The key to check.
1354
- * @returns True if the key exists, false otherwise.
1355
- */
1356
- has(key) {
1357
- return this.map.has(key);
1358
- }
1359
- /**
1360
- * Removes a key and its associated value from the cache.
1361
- * @param key The key to remove.
1362
- * @returns True if the key was found and removed, false otherwise.
1363
- */
1364
- delete(key) {
1365
- const node = this.map.get(key);
1366
- if (!node) return false;
1367
- this.extract(node);
1368
- this.map.delete(key);
1369
- return true;
1370
- }
1371
- /**
1372
- * Returns an iterator of keys in the order of most recently used to least recently used.
1373
- * @returns An iterable iterator of keys.
1374
- */
1375
- *keys() {
1376
- let current = this.head;
1377
- while (current) {
1378
- yield current.key;
1379
- current = current.next;
1380
- }
1381
- }
1382
- /**
1383
- * Returns the current number of items in the cache.
1384
- */
1385
- get size() {
1386
- return this.map.size;
1387
- }
1388
- /**
1389
- * Clears all items from the cache.
1390
- */
1391
- clear() {
1392
- this.map.clear();
1393
- this.head = null;
1394
- this.tail = null;
1395
- }
1396
- };
1397
- var CacheEntanglement = class {
1398
- creation;
1399
- beforeUpdateHook;
1400
- capacity;
1401
- dependencies;
1402
- caches;
1403
- parameters;
1404
- assignments;
1405
- dependencyProperties;
1406
- updateRequirements;
1407
- constructor(creation, option) {
1408
- option = option ?? {};
1409
- const {
1410
- dependencies,
1411
- capacity,
1412
- beforeUpdateHook
1413
- } = option;
1414
- this.creation = creation;
1415
- this.beforeUpdateHook = beforeUpdateHook ?? (() => {
1416
- });
1417
- this.capacity = capacity ?? 100;
1418
- this.assignments = [];
1419
- this.caches = new LRUMap(this.capacity);
1420
- this.parameters = /* @__PURE__ */ new Map();
1421
- this.dependencies = dependencies ?? {};
1422
- this.dependencyProperties = Object.keys(this.dependencies);
1423
- this.updateRequirements = /* @__PURE__ */ new Set();
1424
- for (const name in this.dependencies) {
1425
- const dependency = this.dependencies[name];
1426
- if (!dependency.assignments.includes(this)) {
1427
- dependency.assignments.push(this);
1428
- }
1429
- }
1430
- }
1431
- bubbleUpdateSignal(key) {
1432
- this.updateRequirements.add(key);
1433
- for (let i = 0, len = this.assignments.length; i < len; i++) {
1434
- const t = this.assignments[i];
1435
- const instance = t;
1436
- for (const cacheKey of instance.caches.keys()) {
1437
- if (cacheKey === key || cacheKey.startsWith(`${key}/`)) {
1438
- instance.bubbleUpdateSignal(cacheKey);
1439
- }
1440
- }
1441
- }
1442
- }
1443
- dependencyKey(key) {
1444
- const i = key.lastIndexOf("/");
1445
- if (i === -1) {
1446
- return key;
1447
- }
1448
- return key.substring(0, i);
1449
- }
1450
- /**
1451
- * Returns all keys stored in the instance.
1452
- */
1453
- keys() {
1454
- return this.parameters.keys();
1455
- }
1456
- /**
1457
- * Deletes all cache values stored in the instance.
1458
- */
1459
- clear() {
1460
- for (const key of this.keys()) {
1461
- this.delete(key);
1462
- }
1463
- }
1464
- /**
1465
- * Checks if there is a cache value stored in the key within the instance.
1466
- * @param key The key to search.
1467
- */
1468
- exists(key) {
1469
- return this.parameters.has(key);
1470
- }
1471
- /**
1472
- * Checks if there is a cache value stored in the key within the instance.
1473
- * This method is an alias for `exists`.
1474
- * @param key The key to search.
1475
- */
1476
- has(key) {
1477
- return this.exists(key);
1478
- }
1479
- /**
1480
- * Deletes the cache value stored in the key within the instance.
1481
- * @param key The key to delete.
1482
- */
1483
- delete(key) {
1484
- this.caches.delete(key);
1485
- this.parameters.delete(key);
1486
- this.updateRequirements.delete(key);
1487
- for (let i = 0, len = this.assignments.length; i < len; i++) {
1488
- const t = this.assignments[i];
1489
- const instance = t;
1490
- for (const cacheKey of instance.keys()) {
1491
- if (cacheKey === key || cacheKey.startsWith(`${key}/`)) {
1492
- instance.delete(cacheKey);
1493
- }
1494
- }
1495
- }
1496
- }
1497
- };
1498
- var CacheData = class _CacheData {
1499
- static StructuredClone = globalThis.structuredClone.bind(globalThis);
1500
- _value;
1501
- constructor(value) {
1502
- this._value = value;
1503
- }
1504
- /**
1505
- * This is cached data.
1506
- * It was generated at the time of caching, so there is a risk of modification if it's an object due to shallow copying.
1507
- * 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.
1508
- */
1509
- get raw() {
1510
- return this._value;
1511
- }
1512
- /**
1513
- * The method returns a copied value of the cached data.
1514
- * You can pass a function as a parameter to copy the value. This parameter function should return the copied value.
1515
- *
1516
- * If no parameter is passed, it defaults to using `structuredClone` function to copy the value.
1517
- * If you prefer shallow copying instead of deep copying,
1518
- * you can use the default options `array-shallow-copy`, `object-shallow-copy` and `deep-copy`,
1519
- * which are replaced with functions to shallow copy arrays and objects, respectively. This is a syntactic sugar.
1520
- * @param strategy The function that returns the copied value.
1521
- * If you want to perform a shallow copy, simply pass the strings `array-shallow-copy` or `object-shallow-copy` for easy use.
1522
- * The `array-shallow-copy` strategy performs a shallow copy of an array.
1523
- * The `object-shallow-copy` strategy performs a shallow copy of an object.
1524
- * The `deep-copy` strategy performs a deep copy of the value using `structuredClone`.
1525
- * The default is `deep-copy`.
1526
- */
1527
- clone(strategy = "deep-copy") {
1528
- if (strategy && typeof strategy !== "string") {
1529
- return strategy(this.raw);
1530
- }
1531
- switch (strategy) {
1532
- case "array-shallow-copy":
1533
- return [].concat(this.raw);
1534
- case "object-shallow-copy":
1535
- return Object.assign({}, this.raw);
1536
- case "deep-copy":
1537
- default:
1538
- return _CacheData.StructuredClone(this.raw);
1539
- }
1540
- }
1541
- };
1542
- var CacheEntanglementSync = class extends CacheEntanglement {
1543
- constructor(creation, option) {
1544
- super(creation, option);
1545
- }
1546
- recache(key) {
1547
- if (!this.parameters.has(key)) {
1548
- return;
1549
- }
1550
- if (!this.caches.has(key) || this.updateRequirements.has(key)) {
1551
- this.resolve(key, ...this.parameters.get(key));
1552
- }
1553
- return this.caches.get(key);
1554
- }
1555
- resolve(key, ...parameter) {
1556
- const resolved = {};
1557
- const dependencyKey = this.dependencyKey(key);
1558
- this.beforeUpdateHook(key, dependencyKey, ...parameter);
1559
- for (let i = 0, len = this.dependencyProperties.length; i < len; i++) {
1560
- const name = this.dependencyProperties[i];
1561
- const dependency = this.dependencies[name];
1562
- if (!dependency.exists(key) && !dependency.exists(dependencyKey)) {
1563
- throw new Error(`The key '${key}' or '${dependencyKey}' has not been assigned yet in dependency '${name.toString()}'.`, {
1564
- cause: {
1565
- from: this
1566
- }
1567
- });
1568
- }
1569
- const dependencyValue = dependency.recache(key) ?? dependency.recache(dependencyKey);
1570
- resolved[name] = dependencyValue;
1571
- }
1572
- const value = new CacheData(this.creation(key, resolved, ...parameter));
1573
- this.updateRequirements.delete(key);
1574
- this.parameters.set(key, parameter);
1575
- this.caches.set(key, value);
1576
- return value;
1577
- }
1578
- get(key) {
1579
- if (!this.parameters.has(key)) {
1580
- throw new Error(`Cache value not found: ${key}`);
1581
- }
1582
- return this.cache(key, ...this.parameters.get(key));
1583
- }
1584
- cache(key, ...parameter) {
1585
- if (!this.caches.has(key) || this.updateRequirements.has(key)) {
1586
- this.resolve(key, ...parameter);
1587
- }
1588
- return this.caches.get(key);
1589
- }
1590
- update(key, ...parameter) {
1591
- this.bubbleUpdateSignal(key);
1592
- this.resolve(key, ...parameter);
1593
- return this.caches.get(key);
1594
- }
1595
- };
1596
1542
  var BPTreeTransaction = class _BPTreeTransaction {
1597
- _cachedRegexp;
1598
- nodes;
1543
+ _cachedRegexp = /* @__PURE__ */ new Map();
1544
+ nodes = /* @__PURE__ */ new Map();
1599
1545
  deletedNodeBuffer = /* @__PURE__ */ new Map();
1600
1546
  rootTx;
1601
1547
  mvccRoot;
@@ -1605,6 +1551,8 @@ var require_cjs = __commonJS({
1605
1551
  option;
1606
1552
  order;
1607
1553
  rootId;
1554
+ isInitialized = false;
1555
+ isDestroyed = false;
1608
1556
  verifierMap = {
1609
1557
  gt: (nv, v) => this.comparator.isHigher(nv, v),
1610
1558
  gte: (nv, v) => this.comparator.isHigher(nv, v) || this.comparator.isSame(nv, v),
@@ -1623,8 +1571,12 @@ var require_cjs = __commonJS({
1623
1571
  like: (nv, v) => {
1624
1572
  const nodeValue = this.comparator.match(nv);
1625
1573
  const value = v;
1626
- const cache = this._cachedRegexp.cache(value);
1627
- const regexp = cache.raw;
1574
+ if (!this._cachedRegexp.has(value)) {
1575
+ const pattern = value.replace(/%/g, ".*").replace(/_/g, ".");
1576
+ const regexp2 = new RegExp(`^${pattern}$`, "i");
1577
+ this._cachedRegexp.set(value, regexp2);
1578
+ }
1579
+ const regexp = this._cachedRegexp.get(value);
1628
1580
  return regexp.test(nodeValue);
1629
1581
  }
1630
1582
  };
@@ -1765,6 +1717,15 @@ var require_cjs = __commonJS({
1765
1717
  }
1766
1718
  return best;
1767
1719
  }
1720
+ /**
1721
+ * Checks for conflicts between multiple transactions.
1722
+ *
1723
+ * @param transactions Array of BPTreeTransaction instances to check
1724
+ * @returns An array of keys that are in conflict. Empty array if no conflicts.
1725
+ */
1726
+ static CheckConflicts(transactions) {
1727
+ return MVCCTransaction.CheckConflicts(transactions.map((tx) => tx.mvcc));
1728
+ }
1768
1729
  /**
1769
1730
  * Returns the ID of the root node.
1770
1731
  * @returns The root node ID.
@@ -1796,6 +1757,9 @@ var require_cjs = __commonJS({
1796
1757
  }
1797
1758
  return true;
1798
1759
  }
1760
+ _cloneNode(node) {
1761
+ return JSON.parse(JSON.stringify(node));
1762
+ }
1799
1763
  /**
1800
1764
  * Selects the best driver key from a condition object.
1801
1765
  * The driver key determines the starting point and traversal direction for queries.
@@ -1828,17 +1792,6 @@ var require_cjs = __commonJS({
1828
1792
  this.strategy = strategy;
1829
1793
  this.comparator = comparator;
1830
1794
  this.option = option ?? {};
1831
- this.nodes = new LRUMap(this.option.capacity ?? 1e3);
1832
- this._cachedRegexp = this._createCachedRegexp();
1833
- }
1834
- _createCachedRegexp() {
1835
- return new CacheEntanglementSync((key) => {
1836
- const pattern = key.replace(/%/g, ".*").replace(/_/g, ".");
1837
- const regexp = new RegExp(`^${pattern}$`, "i");
1838
- return regexp;
1839
- }, {
1840
- capacity: this.option.capacity ?? 1e3
1841
- });
1842
1795
  }
1843
1796
  ensureValues(v) {
1844
1797
  if (!Array.isArray(v)) {
@@ -1869,13 +1822,25 @@ var require_cjs = __commonJS({
1869
1822
  getResultEntries() {
1870
1823
  return this.mvcc.getResultEntries();
1871
1824
  }
1825
+ _clearCache() {
1826
+ this._cachedRegexp.clear();
1827
+ }
1872
1828
  /**
1873
1829
  * Clears all cached nodes.
1874
1830
  * This method is useful for freeing up memory when the tree is no longer needed.
1875
1831
  */
1876
1832
  clear() {
1877
- this._cachedRegexp.clear();
1878
- this.nodes.clear();
1833
+ if (this.rootTx !== this) {
1834
+ throw new Error("Cannot call clear on a nested transaction");
1835
+ }
1836
+ this._clearInternal();
1837
+ }
1838
+ _clearInternal() {
1839
+ if (this.isDestroyed) {
1840
+ throw new Error("Transaction already destroyed");
1841
+ }
1842
+ this._clearCache();
1843
+ this.isDestroyed = true;
1879
1844
  }
1880
1845
  _binarySearchValues(values, target, usePrimary = false, upperBound = false) {
1881
1846
  let low = 0;
@@ -1909,9 +1874,6 @@ var require_cjs = __commonJS({
1909
1874
  );
1910
1875
  }
1911
1876
  getNode(id) {
1912
- if (this.nodes.has(id)) {
1913
- return this.nodes.get(id);
1914
- }
1915
1877
  return this.mvcc.read(id);
1916
1878
  }
1917
1879
  /**
@@ -1929,23 +1891,22 @@ var require_cjs = __commonJS({
1929
1891
  prev
1930
1892
  };
1931
1893
  this.mvcc.create(id, node);
1932
- this.nodes.set(id, node);
1933
1894
  return node;
1934
1895
  }
1935
1896
  _updateNode(node) {
1897
+ if (this.mvcc.isDeleted(node.id)) {
1898
+ return;
1899
+ }
1936
1900
  this.mvcc.write(node.id, node);
1937
- this.nodes.set(node.id, node);
1938
1901
  }
1939
1902
  _deleteNode(node) {
1903
+ if (this.mvcc.isDeleted(node.id)) {
1904
+ return;
1905
+ }
1940
1906
  this.mvcc.delete(node.id);
1941
- this.nodes.delete(node.id);
1942
1907
  }
1943
1908
  _readHead() {
1944
- if (this.nodes.has("__HEAD__")) {
1945
- return this.nodes.get("__HEAD__") ?? null;
1946
- }
1947
- const head = this.mvcc.read("__HEAD__");
1948
- return head ?? null;
1909
+ return this.mvcc.read("__HEAD__");
1949
1910
  }
1950
1911
  _writeHead(head) {
1951
1912
  if (!this.mvcc.exists("__HEAD__")) {
@@ -1953,49 +1914,56 @@ var require_cjs = __commonJS({
1953
1914
  } else {
1954
1915
  this.mvcc.write("__HEAD__", head);
1955
1916
  }
1956
- this.nodes.set("__HEAD__", head);
1957
1917
  this.rootId = head.root;
1958
1918
  }
1959
1919
  _insertAtLeaf(node, key, value) {
1960
- if (node.values.length) {
1961
- for (let i = 0, len = node.values.length; i < len; i++) {
1962
- const nValue = node.values[i];
1920
+ let leaf = node;
1921
+ if (leaf.values.length) {
1922
+ for (let i = 0, len = leaf.values.length; i < len; i++) {
1923
+ const nValue = leaf.values[i];
1963
1924
  if (this.comparator.isSame(value, nValue)) {
1964
- const keys = node.keys[i];
1925
+ const keys = leaf.keys[i];
1965
1926
  if (keys.includes(key)) {
1966
1927
  break;
1967
1928
  }
1968
- keys.push(key);
1969
- this._updateNode(node);
1970
- return;
1929
+ leaf = this._cloneNode(leaf);
1930
+ leaf.keys[i].push(key);
1931
+ this._updateNode(leaf);
1932
+ return leaf;
1971
1933
  } else if (this.comparator.isLower(value, nValue)) {
1972
- node.values.splice(i, 0, value);
1973
- node.keys.splice(i, 0, [key]);
1974
- this._updateNode(node);
1975
- return;
1976
- } else if (i + 1 === node.values.length) {
1977
- node.values.push(value);
1978
- node.keys.push([key]);
1979
- this._updateNode(node);
1980
- return;
1934
+ leaf = this._cloneNode(leaf);
1935
+ leaf.values.splice(i, 0, value);
1936
+ leaf.keys.splice(i, 0, [key]);
1937
+ this._updateNode(leaf);
1938
+ return leaf;
1939
+ } else if (i + 1 === leaf.values.length) {
1940
+ leaf = this._cloneNode(leaf);
1941
+ leaf.values.push(value);
1942
+ leaf.keys.push([key]);
1943
+ this._updateNode(leaf);
1944
+ return leaf;
1981
1945
  }
1982
1946
  }
1983
1947
  } else {
1984
- node.values = [value];
1985
- node.keys = [[key]];
1986
- this._updateNode(node);
1987
- return;
1948
+ leaf = this._cloneNode(leaf);
1949
+ leaf.values = [value];
1950
+ leaf.keys = [[key]];
1951
+ this._updateNode(leaf);
1952
+ return leaf;
1988
1953
  }
1954
+ return leaf;
1989
1955
  }
1990
- _insertInParent(node, value, pointer) {
1956
+ _insertInParent(node, value, newSiblingNode) {
1991
1957
  if (this.rootId === node.id) {
1992
- const root = this._createNode(false, [node.id, pointer.id], [value]);
1958
+ node = this._cloneNode(node);
1959
+ newSiblingNode = this._cloneNode(newSiblingNode);
1960
+ const root = this._createNode(false, [node.id, newSiblingNode.id], [value]);
1993
1961
  this.rootId = root.id;
1994
1962
  node.parent = root.id;
1995
- pointer.parent = root.id;
1996
- if (pointer.leaf) {
1997
- node.next = pointer.id;
1998
- pointer.prev = node.id;
1963
+ newSiblingNode.parent = root.id;
1964
+ if (newSiblingNode.leaf) {
1965
+ node.next = newSiblingNode.id;
1966
+ newSiblingNode.prev = node.id;
1999
1967
  }
2000
1968
  this._writeHead({
2001
1969
  root: root.id,
@@ -2003,53 +1971,54 @@ var require_cjs = __commonJS({
2003
1971
  data: this.strategy.head.data
2004
1972
  });
2005
1973
  this._updateNode(node);
2006
- this._updateNode(pointer);
1974
+ this._updateNode(newSiblingNode);
2007
1975
  return;
2008
1976
  }
2009
- const parentNode = this.getNode(node.parent);
1977
+ const parentNode = this._cloneNode(this.getNode(node.parent));
2010
1978
  const nodeIndex = parentNode.keys.indexOf(node.id);
2011
1979
  if (nodeIndex === -1) {
2012
1980
  throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
2013
1981
  }
2014
1982
  parentNode.values.splice(nodeIndex, 0, value);
2015
- parentNode.keys.splice(nodeIndex + 1, 0, pointer.id);
2016
- pointer.parent = parentNode.id;
2017
- if (pointer.leaf) {
2018
- const leftSibling = node;
1983
+ parentNode.keys.splice(nodeIndex + 1, 0, newSiblingNode.id);
1984
+ newSiblingNode = this._cloneNode(newSiblingNode);
1985
+ newSiblingNode.parent = parentNode.id;
1986
+ if (newSiblingNode.leaf) {
1987
+ const leftSibling = this._cloneNode(node);
2019
1988
  const oldNextId = leftSibling.next;
2020
- pointer.prev = leftSibling.id;
2021
- pointer.next = oldNextId;
2022
- leftSibling.next = pointer.id;
1989
+ newSiblingNode.prev = leftSibling.id;
1990
+ newSiblingNode.next = oldNextId;
1991
+ leftSibling.next = newSiblingNode.id;
2023
1992
  this._updateNode(leftSibling);
2024
1993
  if (oldNextId) {
2025
- const oldNext = this.getNode(oldNextId);
2026
- oldNext.prev = pointer.id;
1994
+ const oldNext = this._cloneNode(this.getNode(oldNextId));
1995
+ oldNext.prev = newSiblingNode.id;
2027
1996
  this._updateNode(oldNext);
2028
1997
  }
2029
1998
  }
2030
1999
  this._updateNode(parentNode);
2031
- this._updateNode(pointer);
2000
+ this._updateNode(newSiblingNode);
2032
2001
  if (parentNode.keys.length > this.order) {
2033
- const parentPointer = this._createNode(false, [], []);
2034
- parentPointer.parent = parentNode.parent;
2002
+ const newSiblingNodeRecursive = this._createNode(false, [], []);
2003
+ newSiblingNodeRecursive.parent = parentNode.parent;
2035
2004
  const mid = Math.ceil(this.order / 2) - 1;
2036
- parentPointer.values = parentNode.values.slice(mid + 1);
2037
- parentPointer.keys = parentNode.keys.slice(mid + 1);
2005
+ newSiblingNodeRecursive.values = parentNode.values.slice(mid + 1);
2006
+ newSiblingNodeRecursive.keys = parentNode.keys.slice(mid + 1);
2038
2007
  const midValue = parentNode.values[mid];
2039
2008
  parentNode.values = parentNode.values.slice(0, mid);
2040
2009
  parentNode.keys = parentNode.keys.slice(0, mid + 1);
2041
2010
  for (const k of parentNode.keys) {
2042
- const n = this.getNode(k);
2011
+ const n = this._cloneNode(this.getNode(k));
2043
2012
  n.parent = parentNode.id;
2044
2013
  this._updateNode(n);
2045
2014
  }
2046
- for (const k of parentPointer.keys) {
2047
- const n = this.getNode(k);
2048
- n.parent = parentPointer.id;
2015
+ for (const k of newSiblingNodeRecursive.keys) {
2016
+ const n = this._cloneNode(this.getNode(k));
2017
+ n.parent = newSiblingNodeRecursive.id;
2049
2018
  this._updateNode(n);
2050
2019
  }
2051
2020
  this._updateNode(parentNode);
2052
- this._insertInParent(parentNode, midValue, parentPointer);
2021
+ this._insertInParent(parentNode, midValue, newSiblingNodeRecursive);
2053
2022
  }
2054
2023
  }
2055
2024
  insertableNode(value) {
@@ -2179,28 +2148,42 @@ var require_cjs = __commonJS({
2179
2148
  }
2180
2149
  }
2181
2150
  init() {
2182
- this.clear();
2183
- const head = this._readHead();
2184
- if (head === null) {
2185
- this.order = this.strategy.order;
2186
- const root = this._createNode(true, [], []);
2187
- this._writeHead({
2188
- root: root.id,
2189
- order: this.order,
2190
- data: this.strategy.head.data
2191
- });
2192
- } else {
2193
- const { root, order } = head;
2194
- this.strategy.head = head;
2195
- this.order = order;
2196
- this._writeHead({
2197
- root,
2198
- order: this.order,
2199
- data: this.strategy.head.data
2200
- });
2151
+ if (this.rootTx !== this) {
2152
+ throw new Error("Cannot call init on a nested transaction");
2153
+ }
2154
+ this._initInternal();
2155
+ }
2156
+ _initInternal() {
2157
+ if (this.isInitialized) {
2158
+ throw new Error("Transaction already initialized");
2159
+ }
2160
+ if (this.isDestroyed) {
2161
+ throw new Error("Transaction already destroyed");
2201
2162
  }
2202
- if (this.order < 3) {
2203
- throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
2163
+ this.isInitialized = true;
2164
+ try {
2165
+ this._clearCache();
2166
+ const head = this._readHead();
2167
+ if (head === null) {
2168
+ this.order = this.strategy.order;
2169
+ const root = this._createNode(true, [], []);
2170
+ this._writeHead({
2171
+ root: root.id,
2172
+ order: this.order,
2173
+ data: this.strategy.head.data
2174
+ });
2175
+ } else {
2176
+ const { root, order } = head;
2177
+ this.strategy.head = head;
2178
+ this.order = order;
2179
+ this.rootId = root;
2180
+ }
2181
+ if (this.order < 3) {
2182
+ throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
2183
+ }
2184
+ } catch (e) {
2185
+ this.isInitialized = false;
2186
+ throw e;
2204
2187
  }
2205
2188
  }
2206
2189
  exists(key, value) {
@@ -2214,21 +2197,6 @@ var require_cjs = __commonJS({
2214
2197
  }
2215
2198
  return false;
2216
2199
  }
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
2200
  get(key) {
2233
2201
  let node = this.leftestNode();
2234
2202
  while (true) {
@@ -2314,10 +2282,10 @@ var require_cjs = __commonJS({
2314
2282
  return map;
2315
2283
  }
2316
2284
  insert(key, value) {
2317
- const before = this.insertableNode(value);
2318
- this._insertAtLeaf(before, key, value);
2285
+ let before = this.insertableNode(value);
2286
+ before = this._insertAtLeaf(before, key, value);
2319
2287
  if (before.values.length === this.order) {
2320
- const after = this._createNode(
2288
+ let after = this._createNode(
2321
2289
  true,
2322
2290
  [],
2323
2291
  [],
@@ -2326,10 +2294,13 @@ var require_cjs = __commonJS({
2326
2294
  null
2327
2295
  );
2328
2296
  const mid = Math.ceil(this.order / 2) - 1;
2297
+ after = this._cloneNode(after);
2329
2298
  after.values = before.values.slice(mid + 1);
2330
2299
  after.keys = before.keys.slice(mid + 1);
2331
2300
  before.values = before.values.slice(0, mid + 1);
2332
2301
  before.keys = before.keys.slice(0, mid + 1);
2302
+ this._updateNode(before);
2303
+ this._updateNode(after);
2333
2304
  this._insertInParent(before, after.values[0], after);
2334
2305
  }
2335
2306
  }
@@ -2343,6 +2314,7 @@ var require_cjs = __commonJS({
2343
2314
  }
2344
2315
  }
2345
2316
  if (keyIndex !== -1) {
2317
+ node = this._cloneNode(node);
2346
2318
  node.keys.splice(keyIndex, 1);
2347
2319
  const valueIndex = keyIndex > 0 ? keyIndex - 1 : 0;
2348
2320
  node.values.splice(valueIndex, 1);
@@ -2352,7 +2324,7 @@ var require_cjs = __commonJS({
2352
2324
  if (this.rootId === node.id && node.keys.length === 1 && !node.leaf) {
2353
2325
  const keys = node.keys;
2354
2326
  this._deleteNode(node);
2355
- const newRoot = this.getNode(keys[0]);
2327
+ const newRoot = this._cloneNode(this.getNode(keys[0]));
2356
2328
  newRoot.parent = null;
2357
2329
  this._updateNode(newRoot);
2358
2330
  this._writeHead({
@@ -2360,17 +2332,17 @@ var require_cjs = __commonJS({
2360
2332
  order: this.order,
2361
2333
  data: this.strategy.head.data
2362
2334
  });
2363
- return;
2335
+ return node;
2364
2336
  } else if (this.rootId === node.id) {
2365
2337
  this._writeHead({
2366
2338
  root: node.id,
2367
2339
  order: this.order,
2368
2340
  data: this.strategy.head.data
2369
2341
  });
2370
- return;
2342
+ return node;
2371
2343
  } else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
2372
2344
  if (node.parent === null) {
2373
- return;
2345
+ return node;
2374
2346
  }
2375
2347
  let isPredecessor = false;
2376
2348
  let parentNode = this.getNode(node.parent);
@@ -2391,78 +2363,80 @@ var require_cjs = __commonJS({
2391
2363
  }
2392
2364
  }
2393
2365
  }
2394
- let pointer;
2366
+ let siblingNode;
2395
2367
  let guess;
2396
2368
  if (prevNode === null) {
2397
- pointer = nextNode;
2369
+ siblingNode = nextNode;
2398
2370
  guess = postValue;
2399
2371
  } else if (nextNode === null) {
2400
2372
  isPredecessor = true;
2401
- pointer = prevNode;
2373
+ siblingNode = prevNode;
2402
2374
  guess = prevValue;
2403
2375
  } else {
2404
2376
  if (node.values.length + nextNode.values.length < this.order) {
2405
- pointer = nextNode;
2377
+ siblingNode = nextNode;
2406
2378
  guess = postValue;
2407
2379
  } else {
2408
2380
  isPredecessor = true;
2409
- pointer = prevNode;
2381
+ siblingNode = prevNode;
2410
2382
  guess = prevValue;
2411
2383
  }
2412
2384
  }
2413
- if (!pointer) {
2414
- return;
2385
+ if (!siblingNode) {
2386
+ return node;
2415
2387
  }
2416
- if (node.values.length + pointer.values.length < this.order) {
2388
+ node = this._cloneNode(node);
2389
+ siblingNode = this._cloneNode(siblingNode);
2390
+ if (node.values.length + siblingNode.values.length < this.order) {
2417
2391
  if (!isPredecessor) {
2418
- const pTemp = pointer;
2419
- pointer = node;
2392
+ const pTemp = siblingNode;
2393
+ siblingNode = node;
2420
2394
  node = pTemp;
2421
2395
  }
2422
- pointer.keys.push(...node.keys);
2396
+ siblingNode.keys.push(...node.keys);
2423
2397
  if (!node.leaf) {
2424
- pointer.values.push(guess);
2398
+ siblingNode.values.push(guess);
2425
2399
  } else {
2426
- pointer.next = node.next;
2427
- if (pointer.next) {
2428
- const n = this.getNode(pointer.next);
2429
- n.prev = pointer.id;
2400
+ siblingNode.next = node.next;
2401
+ if (siblingNode.next) {
2402
+ const n = this._cloneNode(this.getNode(siblingNode.next));
2403
+ n.prev = siblingNode.id;
2430
2404
  this._updateNode(n);
2431
2405
  }
2432
2406
  }
2433
- pointer.values.push(...node.values);
2434
- if (!pointer.leaf) {
2435
- const keys = pointer.keys;
2407
+ siblingNode.values.push(...node.values);
2408
+ if (!siblingNode.leaf) {
2409
+ const keys = siblingNode.keys;
2436
2410
  for (const key2 of keys) {
2437
- const node2 = this.getNode(key2);
2438
- node2.parent = pointer.id;
2411
+ const node2 = this._cloneNode(this.getNode(key2));
2412
+ node2.parent = siblingNode.id;
2439
2413
  this._updateNode(node2);
2440
2414
  }
2441
2415
  }
2442
2416
  this._deleteNode(node);
2443
- this._updateNode(pointer);
2417
+ this._updateNode(siblingNode);
2444
2418
  this._deleteEntry(this.getNode(node.parent), node.id);
2445
2419
  } else {
2446
2420
  if (isPredecessor) {
2447
2421
  let pointerPm;
2448
2422
  let pointerKm;
2449
2423
  if (!node.leaf) {
2450
- pointerPm = pointer.keys.splice(-1)[0];
2451
- pointerKm = pointer.values.splice(-1)[0];
2424
+ pointerPm = siblingNode.keys.splice(-1)[0];
2425
+ pointerKm = siblingNode.values.splice(-1)[0];
2452
2426
  node.keys = [pointerPm, ...node.keys];
2453
2427
  node.values = [guess, ...node.values];
2454
- parentNode = this.getNode(node.parent);
2428
+ parentNode = this._cloneNode(this.getNode(node.parent));
2455
2429
  const nodeIndex = parentNode.keys.indexOf(node.id);
2456
2430
  if (nodeIndex > 0) {
2457
2431
  parentNode.values[nodeIndex - 1] = pointerKm;
2458
2432
  this._updateNode(parentNode);
2459
2433
  }
2460
2434
  } else {
2461
- pointerPm = pointer.keys.splice(-1)[0];
2462
- pointerKm = pointer.values.splice(-1)[0];
2435
+ pointerPm = siblingNode.keys.splice(-1)[0];
2436
+ pointerKm = siblingNode.values.splice(-1)[0];
2463
2437
  node.keys = [pointerPm, ...node.keys];
2464
2438
  node.values = [pointerKm, ...node.values];
2465
- parentNode = this.getNode(node.parent);
2439
+ parentNode = this._cloneNode(this.getNode(node.parent));
2466
2440
  const nodeIndex = parentNode.keys.indexOf(node.id);
2467
2441
  if (nodeIndex > 0) {
2468
2442
  parentNode.values[nodeIndex - 1] = pointerKm;
@@ -2470,63 +2444,70 @@ var require_cjs = __commonJS({
2470
2444
  }
2471
2445
  }
2472
2446
  this._updateNode(node);
2473
- this._updateNode(pointer);
2447
+ this._updateNode(siblingNode);
2474
2448
  } else {
2475
2449
  let pointerP0;
2476
2450
  let pointerK0;
2477
2451
  if (!node.leaf) {
2478
- pointerP0 = pointer.keys.splice(0, 1)[0];
2479
- pointerK0 = pointer.values.splice(0, 1)[0];
2452
+ pointerP0 = siblingNode.keys.splice(0, 1)[0];
2453
+ pointerK0 = siblingNode.values.splice(0, 1)[0];
2480
2454
  node.keys = [...node.keys, pointerP0];
2481
2455
  node.values = [...node.values, guess];
2482
- parentNode = this.getNode(node.parent);
2483
- const pointerIndex = parentNode.keys.indexOf(pointer.id);
2456
+ parentNode = this._cloneNode(this.getNode(node.parent));
2457
+ const pointerIndex = parentNode.keys.indexOf(siblingNode.id);
2484
2458
  if (pointerIndex > 0) {
2485
2459
  parentNode.values[pointerIndex - 1] = pointerK0;
2486
2460
  this._updateNode(parentNode);
2487
2461
  }
2488
2462
  } else {
2489
- pointerP0 = pointer.keys.splice(0, 1)[0];
2490
- pointerK0 = pointer.values.splice(0, 1)[0];
2463
+ pointerP0 = siblingNode.keys.splice(0, 1)[0];
2464
+ pointerK0 = siblingNode.values.splice(0, 1)[0];
2491
2465
  node.keys = [...node.keys, pointerP0];
2492
2466
  node.values = [...node.values, pointerK0];
2493
- parentNode = this.getNode(node.parent);
2494
- const pointerIndex = parentNode.keys.indexOf(pointer.id);
2467
+ parentNode = this._cloneNode(this.getNode(node.parent));
2468
+ const pointerIndex = parentNode.keys.indexOf(siblingNode.id);
2495
2469
  if (pointerIndex > 0) {
2496
- parentNode.values[pointerIndex - 1] = pointer.values[0];
2470
+ parentNode.values[pointerIndex - 1] = siblingNode.values[0];
2497
2471
  this._updateNode(parentNode);
2498
2472
  }
2499
2473
  }
2500
2474
  this._updateNode(node);
2501
- this._updateNode(pointer);
2475
+ this._updateNode(siblingNode);
2502
2476
  }
2503
- if (!pointer.leaf) {
2504
- for (const key2 of pointer.keys) {
2505
- const n = this.getNode(key2);
2506
- n.parent = pointer.id;
2477
+ if (!siblingNode.leaf) {
2478
+ for (const key2 of siblingNode.keys) {
2479
+ const n = this._cloneNode(this.getNode(key2));
2480
+ n.parent = siblingNode.id;
2507
2481
  this._updateNode(n);
2508
2482
  }
2509
2483
  }
2510
2484
  if (!node.leaf) {
2511
2485
  for (const key2 of node.keys) {
2512
- const n = this.getNode(key2);
2486
+ const n = this._cloneNode(this.getNode(key2));
2513
2487
  n.parent = node.id;
2514
2488
  this._updateNode(n);
2515
2489
  }
2516
2490
  }
2517
2491
  if (!parentNode.leaf) {
2518
2492
  for (const key2 of parentNode.keys) {
2519
- const n = this.getNode(key2);
2493
+ const n = this._cloneNode(this.getNode(key2));
2520
2494
  n.parent = parentNode.id;
2521
2495
  this._updateNode(n);
2522
2496
  }
2523
2497
  }
2524
2498
  }
2525
2499
  } else {
2526
- this._updateNode(node);
2500
+ this._updateNode(this._cloneNode(node));
2527
2501
  }
2502
+ return node;
2528
2503
  }
2529
2504
  delete(key, value) {
2505
+ if (value === void 0) {
2506
+ value = this.get(key);
2507
+ }
2508
+ if (value === void 0) {
2509
+ return;
2510
+ }
2530
2511
  let node = this.insertableNodeByPrimary(value);
2531
2512
  let found = false;
2532
2513
  while (true) {
@@ -2537,13 +2518,15 @@ var require_cjs = __commonJS({
2537
2518
  const keys = node.keys[i];
2538
2519
  const keyIndex = keys.indexOf(key);
2539
2520
  if (keyIndex !== -1) {
2540
- keys.splice(keyIndex, 1);
2541
- if (keys.length === 0) {
2521
+ node = this._cloneNode(node);
2522
+ const freshKeys = node.keys[i];
2523
+ freshKeys.splice(keyIndex, 1);
2524
+ if (freshKeys.length === 0) {
2542
2525
  node.keys.splice(i, 1);
2543
2526
  node.values.splice(i, 1);
2544
2527
  }
2545
2528
  this._updateNode(node);
2546
- this._deleteEntry(node, key);
2529
+ node = this._deleteEntry(node, key);
2547
2530
  found = true;
2548
2531
  break;
2549
2532
  }
@@ -2578,110 +2561,359 @@ var require_cjs = __commonJS({
2578
2561
  commit(label) {
2579
2562
  let result = this.mvcc.commit(label);
2580
2563
  if (result.success) {
2581
- result = this.mvccRoot.commit(label);
2582
- if (result.success && this.rootTx !== this) {
2583
- this.rootTx.rootId = this.rootId;
2584
- }
2585
- if (result.success) {
2586
- for (const r of result.created) {
2587
- this.nodes.set(r.key, r.data);
2588
- }
2589
- for (const r of result.updated) {
2590
- this.nodes.set(r.key, r.data);
2564
+ const isRootTx = this.rootTx === this;
2565
+ if (!isRootTx) {
2566
+ result = this.rootTx.commit(label);
2567
+ if (result.success) {
2568
+ this.rootTx.rootId = this.rootId;
2591
2569
  }
2592
- for (const r of result.deleted) {
2593
- this.nodes.delete(r.key);
2570
+ }
2571
+ }
2572
+ return result;
2573
+ }
2574
+ rollback() {
2575
+ return this.mvcc.rollback();
2576
+ }
2577
+ };
2578
+ var BPTreeMVCCStrategySync = class extends SyncMVCCStrategy {
2579
+ constructor(strategy) {
2580
+ super();
2581
+ this.strategy = strategy;
2582
+ }
2583
+ read(key) {
2584
+ if (key === "__HEAD__") {
2585
+ return this.strategy.readHead();
2586
+ }
2587
+ return this.strategy.read(key);
2588
+ }
2589
+ write(key, value) {
2590
+ if (key === "__HEAD__") {
2591
+ this.strategy.writeHead(value);
2592
+ } else {
2593
+ this.strategy.write(key, value);
2594
+ }
2595
+ }
2596
+ delete(key) {
2597
+ this.strategy.delete(key);
2598
+ }
2599
+ exists(key) {
2600
+ if (key === "__HEAD__") {
2601
+ return this.strategy.readHead() !== null;
2602
+ }
2603
+ try {
2604
+ const node = this.strategy.read(key);
2605
+ return node !== null && node !== void 0;
2606
+ } catch {
2607
+ return false;
2608
+ }
2609
+ }
2610
+ };
2611
+ var BPTreeSync = class extends BPTreeSyncTransaction {
2612
+ constructor(strategy, comparator, option) {
2613
+ const mvccRoot = new SyncMVCCTransaction(new BPTreeMVCCStrategySync(strategy), {
2614
+ cacheCapacity: option?.capacity ?? void 0
2615
+ });
2616
+ super(
2617
+ null,
2618
+ mvccRoot,
2619
+ mvccRoot,
2620
+ strategy,
2621
+ comparator,
2622
+ option
2623
+ );
2624
+ }
2625
+ /**
2626
+ * Creates a new synchronous transaction.
2627
+ * @returns A new BPTreeSyncTransaction.
2628
+ */
2629
+ createTransaction() {
2630
+ const nestedTx = this.mvcc.createNested();
2631
+ const tx = new BPTreeSyncTransaction(
2632
+ this,
2633
+ this.mvcc,
2634
+ nestedTx,
2635
+ this.strategy,
2636
+ this.comparator,
2637
+ this.option
2638
+ );
2639
+ tx._initInternal();
2640
+ return tx;
2641
+ }
2642
+ insert(key, value) {
2643
+ const tx = this.createTransaction();
2644
+ tx.insert(key, value);
2645
+ const result = tx.commit();
2646
+ if (!result.success) {
2647
+ throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
2648
+ }
2649
+ }
2650
+ delete(key, value) {
2651
+ const tx = this.createTransaction();
2652
+ tx.delete(key, value);
2653
+ const result = tx.commit();
2654
+ if (!result.success) {
2655
+ throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
2656
+ }
2657
+ }
2658
+ };
2659
+ var Ryoiki22 = class _Ryoiki2 {
2660
+ readings;
2661
+ writings;
2662
+ readQueue;
2663
+ writeQueue;
2664
+ static async CatchError(promise) {
2665
+ return await promise.then((v) => [void 0, v]).catch((err) => [err]);
2666
+ }
2667
+ static IsRangeOverlap(a, b) {
2668
+ const [start1, end1] = a;
2669
+ const [start2, end2] = b;
2670
+ if (end1 <= start2 || end2 <= start1) {
2671
+ return false;
2672
+ }
2673
+ return true;
2674
+ }
2675
+ static ERR_ALREADY_EXISTS(lockId) {
2676
+ return new Error(`The '${lockId}' task already existing in queue or running.`);
2677
+ }
2678
+ static ERR_NOT_EXISTS(lockId) {
2679
+ return new Error(`The '${lockId}' task not existing in task queue.`);
2680
+ }
2681
+ static ERR_TIMEOUT(lockId, timeout) {
2682
+ return new Error(`The task with ID '${lockId}' failed to acquire the lock within the timeout(${timeout}ms).`);
2683
+ }
2684
+ /**
2685
+ * Constructs a new instance of the Ryoiki class.
2686
+ */
2687
+ constructor() {
2688
+ this.readings = /* @__PURE__ */ new Map();
2689
+ this.writings = /* @__PURE__ */ new Map();
2690
+ this.readQueue = /* @__PURE__ */ new Map();
2691
+ this.writeQueue = /* @__PURE__ */ new Map();
2692
+ }
2693
+ /**
2694
+ * Creates a range based on a start value and length.
2695
+ * @param start - The starting value of the range.
2696
+ * @param length - The length of the range.
2697
+ * @returns A range tuple [start, start + length].
2698
+ */
2699
+ range(start, length) {
2700
+ return [start, start + length];
2701
+ }
2702
+ rangeOverlapping(tasks, range) {
2703
+ return Array.from(tasks.values()).some((t) => _Ryoiki2.IsRangeOverlap(t.range, range));
2704
+ }
2705
+ isSameRange(a, b) {
2706
+ const [a1, a2] = a;
2707
+ const [b1, b2] = b;
2708
+ return a1 === b1 && a2 === b2;
2709
+ }
2710
+ fetchUnitAndRun(queue, workspaces) {
2711
+ for (const [id, unit] of queue) {
2712
+ if (!unit.condition()) {
2713
+ continue;
2714
+ }
2715
+ this._alloc(queue, workspaces, id);
2716
+ }
2717
+ }
2718
+ _handleOverload(args, handlers, argPatterns) {
2719
+ for (const [key, pattern] of Object.entries(argPatterns)) {
2720
+ if (this._matchArgs(args, pattern)) {
2721
+ return handlers[key](...args);
2722
+ }
2723
+ }
2724
+ throw new Error("Invalid arguments");
2725
+ }
2726
+ _matchArgs(args, pattern) {
2727
+ return args.every((arg, index) => {
2728
+ const expectedType = pattern[index];
2729
+ if (expectedType === void 0) return typeof arg === "undefined";
2730
+ if (expectedType === Function) return typeof arg === "function";
2731
+ if (expectedType === Number) return typeof arg === "number";
2732
+ if (expectedType === Array) return Array.isArray(arg);
2733
+ return false;
2734
+ });
2735
+ }
2736
+ _createRandomId() {
2737
+ const timestamp = Date.now().toString(36);
2738
+ const random = Math.random().toString(36).substring(2);
2739
+ return `${timestamp}${random}`;
2740
+ }
2741
+ _alloc(queue, workspaces, lockId) {
2742
+ const unit = queue.get(lockId);
2743
+ if (!unit) {
2744
+ throw _Ryoiki2.ERR_NOT_EXISTS(lockId);
2745
+ }
2746
+ workspaces.set(lockId, unit);
2747
+ queue.delete(lockId);
2748
+ unit.alloc();
2749
+ }
2750
+ _free(workspaces, lockId) {
2751
+ const unit = workspaces.get(lockId);
2752
+ if (!unit) {
2753
+ throw _Ryoiki2.ERR_NOT_EXISTS(lockId);
2754
+ }
2755
+ workspaces.delete(lockId);
2756
+ unit.free();
2757
+ }
2758
+ _lock(queue, range, timeout, task, condition) {
2759
+ return new Promise((resolve, reject) => {
2760
+ let timeoutId = null;
2761
+ if (timeout >= 0) {
2762
+ timeoutId = setTimeout(() => {
2763
+ reject(_Ryoiki2.ERR_TIMEOUT(id, timeout));
2764
+ }, timeout);
2765
+ }
2766
+ const id = this._createRandomId();
2767
+ const alloc = async () => {
2768
+ if (timeoutId !== null) {
2769
+ clearTimeout(timeoutId);
2594
2770
  }
2771
+ const [err, v] = await _Ryoiki2.CatchError(task(id));
2772
+ if (err) reject(err);
2773
+ else resolve(v);
2774
+ };
2775
+ const fetch = () => {
2776
+ this.fetchUnitAndRun(this.readQueue, this.readings);
2777
+ this.fetchUnitAndRun(this.writeQueue, this.writings);
2778
+ };
2779
+ queue.set(id, { id, range, condition, alloc, free: fetch });
2780
+ fetch();
2781
+ });
2782
+ }
2783
+ _checkWorking(range, workspaces) {
2784
+ let isLocked = false;
2785
+ for (const lock of workspaces.values()) {
2786
+ if (_Ryoiki2.IsRangeOverlap(range, lock.range)) {
2787
+ isLocked = true;
2788
+ break;
2595
2789
  }
2596
2790
  }
2597
- return result;
2598
- }
2599
- rollback() {
2600
- return this.mvcc.rollback();
2601
- }
2602
- };
2603
- var BPTreeMVCCStrategySync = class extends SyncMVCCStrategy {
2604
- constructor(strategy) {
2605
- super();
2606
- this.strategy = strategy;
2791
+ return isLocked;
2607
2792
  }
2608
- read(key) {
2609
- if (key === "__HEAD__") {
2610
- return this.strategy.readHead();
2611
- }
2612
- return this.strategy.read(key);
2793
+ /**
2794
+ * Checks if there is any active read lock within the specified range.
2795
+ * @param range The range to check for active read locks.
2796
+ * @returns `true` if there is an active read lock within the range, `false` otherwise.
2797
+ */
2798
+ isReading(range) {
2799
+ return this._checkWorking(range, this.readings);
2613
2800
  }
2614
- write(key, value) {
2615
- if (key === "__HEAD__") {
2616
- this.strategy.writeHead(value);
2617
- } else {
2618
- this.strategy.write(key, value);
2619
- }
2801
+ /**
2802
+ * Checks if there is any active write lock within the specified range.
2803
+ * @param range The range to check for active write locks.
2804
+ * @returns `true` if there is an active write lock within the range, `false` otherwise.
2805
+ */
2806
+ isWriting(range) {
2807
+ return this._checkWorking(range, this.writings);
2620
2808
  }
2621
- delete(key) {
2622
- this.strategy.delete(key);
2809
+ /**
2810
+ * Checks if a read lock can be acquired within the specified range.
2811
+ * @param range The range to check for read lock availability.
2812
+ * @returns `true` if a read lock can be acquired, `false` otherwise.
2813
+ */
2814
+ canRead(range) {
2815
+ const writing = this.isWriting(range);
2816
+ return !writing;
2623
2817
  }
2624
- exists(key) {
2625
- if (key === "__HEAD__") {
2626
- return this.strategy.readHead() !== null;
2627
- }
2628
- try {
2629
- const node = this.strategy.read(key);
2630
- return node !== null && node !== void 0;
2631
- } catch {
2632
- return false;
2633
- }
2818
+ /**
2819
+ * Checks if a write lock can be acquired within the specified range.
2820
+ * @param range The range to check for write lock availability.
2821
+ * @returns `true` if a write lock can be acquired, `false` otherwise.
2822
+ */
2823
+ canWrite(range) {
2824
+ const reading = this.isReading(range);
2825
+ const writing = this.isWriting(range);
2826
+ return !reading && !writing;
2634
2827
  }
2635
- };
2636
- var BPTreeSync = class extends BPTreeSyncTransaction {
2637
- constructor(strategy, comparator, option) {
2638
- const mvccRoot = new SyncMVCCTransaction(new BPTreeMVCCStrategySync(strategy));
2639
- super(
2640
- null,
2641
- mvccRoot,
2642
- mvccRoot,
2643
- strategy,
2644
- comparator,
2645
- option
2828
+ /**
2829
+ * Internal implementation of the read lock. Handles both overloads.
2830
+ * @template T - The return type of the task.
2831
+ * @param arg0 - Either a range or a task callback.
2832
+ * If a range is provided, the task is the second argument.
2833
+ * @param arg1 - The task to execute, required if a range is provided.
2834
+ * @param arg2 - The timeout for acquiring the lock.
2835
+ * If the lock cannot be acquired within this period, an error will be thrown.
2836
+ * If this value is not provided, no timeout will be set.
2837
+ * @returns A promise resolving to the result of the task execution.
2838
+ */
2839
+ readLock(arg0, arg1, arg2) {
2840
+ const [range, task, timeout] = this._handleOverload(
2841
+ [arg0, arg1, arg2],
2842
+ {
2843
+ rangeTask: (range2, task2) => [range2, task2, -1],
2844
+ rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
2845
+ task: (task2) => [[-Infinity, Infinity], task2, -1],
2846
+ taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
2847
+ },
2848
+ {
2849
+ task: [Function],
2850
+ taskTimeout: [Function, Number],
2851
+ rangeTask: [Array, Function],
2852
+ rangeTaskTimeout: [Array, Function, Number]
2853
+ }
2854
+ );
2855
+ return this._lock(
2856
+ this.readQueue,
2857
+ range,
2858
+ timeout,
2859
+ task,
2860
+ () => !this.rangeOverlapping(this.writings, range)
2646
2861
  );
2647
2862
  }
2648
2863
  /**
2649
- * Creates a new synchronous transaction.
2650
- * @returns A new BPTreeSyncTransaction.
2864
+ * Internal implementation of the write lock. Handles both overloads.
2865
+ * @template T - The return type of the task.
2866
+ * @param arg0 - Either a range or a task callback.
2867
+ * If a range is provided, the task is the second argument.
2868
+ * @param arg1 - The task to execute, required if a range is provided.
2869
+ * @param arg2 - The timeout for acquiring the lock.
2870
+ * If the lock cannot be acquired within this period, an error will be thrown.
2871
+ * If this value is not provided, no timeout will be set.
2872
+ * @returns A promise resolving to the result of the task execution.
2651
2873
  */
2652
- createTransaction() {
2653
- const nestedTx = this.mvcc.createNested();
2654
- const tx = new BPTreeSyncTransaction(
2655
- this,
2656
- this.mvcc,
2657
- nestedTx,
2658
- this.strategy,
2659
- this.comparator,
2660
- this.option
2874
+ writeLock(arg0, arg1, arg2) {
2875
+ const [range, task, timeout] = this._handleOverload(
2876
+ [arg0, arg1, arg2],
2877
+ {
2878
+ rangeTask: (range2, task2) => [range2, task2, -1],
2879
+ rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
2880
+ task: (task2) => [[-Infinity, Infinity], task2, -1],
2881
+ taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
2882
+ },
2883
+ {
2884
+ task: [Function],
2885
+ taskTimeout: [Function, Number],
2886
+ rangeTask: [Array, Function],
2887
+ rangeTaskTimeout: [Array, Function, Number]
2888
+ }
2889
+ );
2890
+ return this._lock(
2891
+ this.writeQueue,
2892
+ range,
2893
+ timeout,
2894
+ task,
2895
+ () => {
2896
+ return !this.rangeOverlapping(this.writings, range) && !this.rangeOverlapping(this.readings, range);
2897
+ }
2661
2898
  );
2662
- tx.init();
2663
- return tx;
2664
2899
  }
2665
- insert(key, value) {
2666
- const tx = this.createTransaction();
2667
- tx.insert(key, value);
2668
- const result = tx.commit();
2669
- if (!result.success) {
2670
- throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
2671
- }
2672
- this.rootId = tx.getRootId();
2900
+ /**
2901
+ * Releases a read lock by its lock ID.
2902
+ * @param lockId - The unique identifier for the lock to release.
2903
+ */
2904
+ readUnlock(lockId) {
2905
+ this._free(this.readings, lockId);
2673
2906
  }
2674
- delete(key, value) {
2675
- const tx = this.createTransaction();
2676
- tx.delete(key, value);
2677
- const result = tx.commit();
2678
- if (!result.success) {
2679
- throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
2680
- }
2681
- this.rootId = tx.getRootId();
2907
+ /**
2908
+ * Releases a write lock by its lock ID.
2909
+ * @param lockId - The unique identifier for the lock to release.
2910
+ */
2911
+ writeUnlock(lockId) {
2912
+ this._free(this.writings, lockId);
2682
2913
  }
2683
2914
  };
2684
2915
  var BPTreeAsyncTransaction2 = class extends BPTreeTransaction {
2916
+ lock;
2685
2917
  constructor(rootTx, mvccRoot, mvcc, strategy, comparator, option) {
2686
2918
  super(
2687
2919
  rootTx,
@@ -2691,11 +2923,18 @@ var require_cjs = __commonJS({
2691
2923
  comparator,
2692
2924
  option
2693
2925
  );
2926
+ this.lock = new Ryoiki22();
2927
+ }
2928
+ async writeLock(id, fn) {
2929
+ let lockId;
2930
+ return this.lock.writeLock([id, id + 0.1], async (_lockId) => {
2931
+ lockId = _lockId;
2932
+ return fn();
2933
+ }).finally(() => {
2934
+ this.lock.writeUnlock(lockId);
2935
+ });
2694
2936
  }
2695
2937
  async getNode(id) {
2696
- if (this.nodes.has(id)) {
2697
- return this.nodes.get(id);
2698
- }
2699
2938
  return await this.mvcc.read(id);
2700
2939
  }
2701
2940
  /**
@@ -2713,23 +2952,22 @@ var require_cjs = __commonJS({
2713
2952
  prev
2714
2953
  };
2715
2954
  await this.mvcc.create(id, node);
2716
- this.nodes.set(id, node);
2717
2955
  return node;
2718
2956
  }
2719
2957
  async _updateNode(node) {
2958
+ if (this.mvcc.isDeleted(node.id)) {
2959
+ return;
2960
+ }
2720
2961
  await this.mvcc.write(node.id, node);
2721
- this.nodes.set(node.id, node);
2722
2962
  }
2723
2963
  async _deleteNode(node) {
2964
+ if (this.mvcc.isDeleted(node.id)) {
2965
+ return;
2966
+ }
2724
2967
  await this.mvcc.delete(node.id);
2725
- this.nodes.delete(node.id);
2726
2968
  }
2727
2969
  async _readHead() {
2728
- if (this.nodes.has("__HEAD__")) {
2729
- return this.nodes.get("__HEAD__") ?? null;
2730
- }
2731
- const head = await this.mvcc.read("__HEAD__");
2732
- return head ?? null;
2970
+ return await this.mvcc.read("__HEAD__");
2733
2971
  }
2734
2972
  async _writeHead(head) {
2735
2973
  if (!await this.mvcc.exists("__HEAD__")) {
@@ -2737,49 +2975,56 @@ var require_cjs = __commonJS({
2737
2975
  } else {
2738
2976
  await this.mvcc.write("__HEAD__", head);
2739
2977
  }
2740
- this.nodes.set("__HEAD__", head);
2741
2978
  this.rootId = head.root;
2742
2979
  }
2743
2980
  async _insertAtLeaf(node, key, value) {
2744
- if (node.values.length) {
2745
- for (let i = 0, len = node.values.length; i < len; i++) {
2746
- const nValue = node.values[i];
2981
+ let leaf = node;
2982
+ if (leaf.values.length) {
2983
+ for (let i = 0, len = leaf.values.length; i < len; i++) {
2984
+ const nValue = leaf.values[i];
2747
2985
  if (this.comparator.isSame(value, nValue)) {
2748
- const keys = node.keys[i];
2986
+ const keys = leaf.keys[i];
2749
2987
  if (keys.includes(key)) {
2750
2988
  break;
2751
2989
  }
2752
- keys.push(key);
2753
- await this._updateNode(node);
2754
- return;
2990
+ leaf = this._cloneNode(leaf);
2991
+ leaf.keys[i].push(key);
2992
+ await this._updateNode(leaf);
2993
+ return leaf;
2755
2994
  } else if (this.comparator.isLower(value, nValue)) {
2756
- node.values.splice(i, 0, value);
2757
- node.keys.splice(i, 0, [key]);
2758
- await this._updateNode(node);
2759
- return;
2760
- } else if (i + 1 === node.values.length) {
2761
- node.values.push(value);
2762
- node.keys.push([key]);
2763
- await this._updateNode(node);
2764
- return;
2995
+ leaf = this._cloneNode(leaf);
2996
+ leaf.values.splice(i, 0, value);
2997
+ leaf.keys.splice(i, 0, [key]);
2998
+ await this._updateNode(leaf);
2999
+ return leaf;
3000
+ } else if (i + 1 === leaf.values.length) {
3001
+ leaf = this._cloneNode(leaf);
3002
+ leaf.values.push(value);
3003
+ leaf.keys.push([key]);
3004
+ await this._updateNode(leaf);
3005
+ return leaf;
2765
3006
  }
2766
3007
  }
2767
3008
  } else {
2768
- node.values = [value];
2769
- node.keys = [[key]];
2770
- await this._updateNode(node);
2771
- return;
3009
+ leaf = this._cloneNode(leaf);
3010
+ leaf.values = [value];
3011
+ leaf.keys = [[key]];
3012
+ await this._updateNode(leaf);
3013
+ return leaf;
2772
3014
  }
3015
+ return leaf;
2773
3016
  }
2774
- async _insertInParent(node, value, pointer) {
3017
+ async _insertInParent(node, value, newSiblingNode) {
2775
3018
  if (this.rootId === node.id) {
2776
- const root = await this._createNode(false, [node.id, pointer.id], [value]);
3019
+ node = this._cloneNode(node);
3020
+ newSiblingNode = this._cloneNode(newSiblingNode);
3021
+ const root = await this._createNode(false, [node.id, newSiblingNode.id], [value]);
2777
3022
  this.rootId = root.id;
2778
3023
  node.parent = root.id;
2779
- pointer.parent = root.id;
2780
- if (pointer.leaf) {
2781
- node.next = pointer.id;
2782
- pointer.prev = node.id;
3024
+ newSiblingNode.parent = root.id;
3025
+ if (newSiblingNode.leaf) {
3026
+ node.next = newSiblingNode.id;
3027
+ newSiblingNode.prev = node.id;
2783
3028
  }
2784
3029
  await this._writeHead({
2785
3030
  root: root.id,
@@ -2787,53 +3032,54 @@ var require_cjs = __commonJS({
2787
3032
  data: this.strategy.head.data
2788
3033
  });
2789
3034
  await this._updateNode(node);
2790
- await this._updateNode(pointer);
3035
+ await this._updateNode(newSiblingNode);
2791
3036
  return;
2792
3037
  }
2793
- const parentNode = await this.getNode(node.parent);
3038
+ const parentNode = this._cloneNode(await this.getNode(node.parent));
2794
3039
  const nodeIndex = parentNode.keys.indexOf(node.id);
2795
3040
  if (nodeIndex === -1) {
2796
3041
  throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
2797
3042
  }
2798
3043
  parentNode.values.splice(nodeIndex, 0, value);
2799
- parentNode.keys.splice(nodeIndex + 1, 0, pointer.id);
2800
- pointer.parent = parentNode.id;
2801
- if (pointer.leaf) {
2802
- const leftSibling = node;
3044
+ parentNode.keys.splice(nodeIndex + 1, 0, newSiblingNode.id);
3045
+ newSiblingNode = this._cloneNode(newSiblingNode);
3046
+ newSiblingNode.parent = parentNode.id;
3047
+ if (newSiblingNode.leaf) {
3048
+ const leftSibling = this._cloneNode(node);
2803
3049
  const oldNextId = leftSibling.next;
2804
- pointer.prev = leftSibling.id;
2805
- pointer.next = oldNextId;
2806
- leftSibling.next = pointer.id;
3050
+ newSiblingNode.prev = leftSibling.id;
3051
+ newSiblingNode.next = oldNextId;
3052
+ leftSibling.next = newSiblingNode.id;
2807
3053
  await this._updateNode(leftSibling);
2808
3054
  if (oldNextId) {
2809
- const oldNext = await this.getNode(oldNextId);
2810
- oldNext.prev = pointer.id;
3055
+ const oldNext = this._cloneNode(await this.getNode(oldNextId));
3056
+ oldNext.prev = newSiblingNode.id;
2811
3057
  await this._updateNode(oldNext);
2812
3058
  }
2813
3059
  }
2814
3060
  await this._updateNode(parentNode);
2815
- await this._updateNode(pointer);
3061
+ await this._updateNode(newSiblingNode);
2816
3062
  if (parentNode.keys.length > this.order) {
2817
- const parentPointer = await this._createNode(false, [], []);
2818
- parentPointer.parent = parentNode.parent;
3063
+ const newSiblingNodeRecursive = await this._createNode(false, [], []);
3064
+ newSiblingNodeRecursive.parent = parentNode.parent;
2819
3065
  const mid = Math.ceil(this.order / 2) - 1;
2820
- parentPointer.values = parentNode.values.slice(mid + 1);
2821
- parentPointer.keys = parentNode.keys.slice(mid + 1);
3066
+ newSiblingNodeRecursive.values = parentNode.values.slice(mid + 1);
3067
+ newSiblingNodeRecursive.keys = parentNode.keys.slice(mid + 1);
2822
3068
  const midValue = parentNode.values[mid];
2823
3069
  parentNode.values = parentNode.values.slice(0, mid);
2824
3070
  parentNode.keys = parentNode.keys.slice(0, mid + 1);
2825
3071
  for (const k of parentNode.keys) {
2826
- const n = await this.getNode(k);
3072
+ const n = this._cloneNode(await this.getNode(k));
2827
3073
  n.parent = parentNode.id;
2828
3074
  await this._updateNode(n);
2829
3075
  }
2830
- for (const k of parentPointer.keys) {
2831
- const n = await this.getNode(k);
2832
- n.parent = parentPointer.id;
3076
+ for (const k of newSiblingNodeRecursive.keys) {
3077
+ const n = this._cloneNode(await this.getNode(k));
3078
+ n.parent = newSiblingNodeRecursive.id;
2833
3079
  await this._updateNode(n);
2834
3080
  }
2835
3081
  await this._updateNode(parentNode);
2836
- await this._insertInParent(parentNode, midValue, parentPointer);
3082
+ await this._insertInParent(parentNode, midValue, newSiblingNodeRecursive);
2837
3083
  }
2838
3084
  }
2839
3085
  async insertableNode(value) {
@@ -2969,28 +3215,42 @@ var require_cjs = __commonJS({
2969
3215
  }
2970
3216
  }
2971
3217
  async init() {
2972
- this.clear();
2973
- const head = await this._readHead();
2974
- if (head === null) {
2975
- this.order = this.strategy.order;
2976
- const root = await this._createNode(true, [], []);
2977
- await this._writeHead({
2978
- root: root.id,
2979
- order: this.order,
2980
- data: this.strategy.head.data
2981
- });
2982
- } else {
2983
- const { root, order } = head;
2984
- this.strategy.head = head;
2985
- this.order = order;
2986
- await this._writeHead({
2987
- root,
2988
- order: this.order,
2989
- data: this.strategy.head.data
2990
- });
3218
+ if (this.rootTx !== this) {
3219
+ throw new Error("Cannot call init on a nested transaction");
3220
+ }
3221
+ return await this._initInternal();
3222
+ }
3223
+ async _initInternal() {
3224
+ if (this.isInitialized) {
3225
+ throw new Error("Transaction already initialized");
3226
+ }
3227
+ if (this.isDestroyed) {
3228
+ throw new Error("Transaction already destroyed");
2991
3229
  }
2992
- if (this.order < 3) {
2993
- throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
3230
+ this.isInitialized = true;
3231
+ try {
3232
+ this._clearCache();
3233
+ const head = await this._readHead();
3234
+ if (head === null) {
3235
+ this.order = this.strategy.order;
3236
+ const root = await this._createNode(true, [], []);
3237
+ await this._writeHead({
3238
+ root: root.id,
3239
+ order: this.order,
3240
+ data: this.strategy.head.data
3241
+ });
3242
+ } else {
3243
+ const { root, order } = head;
3244
+ this.strategy.head = head;
3245
+ this.order = order;
3246
+ this.rootId = root;
3247
+ }
3248
+ if (this.order < 3) {
3249
+ throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
3250
+ }
3251
+ } catch (e) {
3252
+ this.isInitialized = false;
3253
+ throw e;
2994
3254
  }
2995
3255
  }
2996
3256
  async exists(key, value) {
@@ -3004,21 +3264,6 @@ var require_cjs = __commonJS({
3004
3264
  }
3005
3265
  return false;
3006
3266
  }
3007
- async forceUpdate(id) {
3008
- if (id) {
3009
- this.nodes.delete(id);
3010
- await this.getNode(id);
3011
- return 1;
3012
- }
3013
- const keys = Array.from(this.nodes.keys());
3014
- for (const key of keys) {
3015
- this.nodes.delete(key);
3016
- }
3017
- for (const key of keys) {
3018
- await this.getNode(key);
3019
- }
3020
- return keys.length;
3021
- }
3022
3267
  async get(key) {
3023
3268
  let node = await this.leftestNode();
3024
3269
  while (true) {
@@ -3099,29 +3344,34 @@ var require_cjs = __commonJS({
3099
3344
  async where(condition, order = "asc") {
3100
3345
  const map = /* @__PURE__ */ new Map();
3101
3346
  for await (const [key, value] of this.whereStream(condition, void 0, order)) {
3102
- map.set(key, value);
3103
- }
3104
- return map;
3105
- }
3106
- async insert(key, value) {
3107
- const before = await this.insertableNode(value);
3108
- await this._insertAtLeaf(before, key, value);
3109
- if (before.values.length === this.order) {
3110
- const after = await this._createNode(
3111
- true,
3112
- [],
3113
- [],
3114
- before.parent,
3115
- null,
3116
- null
3117
- );
3118
- const mid = Math.ceil(this.order / 2) - 1;
3119
- after.values = before.values.slice(mid + 1);
3120
- after.keys = before.keys.slice(mid + 1);
3121
- before.values = before.values.slice(0, mid + 1);
3122
- before.keys = before.keys.slice(0, mid + 1);
3123
- await this._insertInParent(before, after.values[0], after);
3347
+ map.set(key, value);
3124
3348
  }
3349
+ return map;
3350
+ }
3351
+ async insert(key, value) {
3352
+ return this.writeLock(0, async () => {
3353
+ let before = await this.insertableNode(value);
3354
+ before = await this._insertAtLeaf(before, key, value);
3355
+ if (before.values.length === this.order) {
3356
+ let after = await this._createNode(
3357
+ true,
3358
+ [],
3359
+ [],
3360
+ before.parent,
3361
+ null,
3362
+ null
3363
+ );
3364
+ const mid = Math.ceil(this.order / 2) - 1;
3365
+ after = this._cloneNode(after);
3366
+ after.values = before.values.slice(mid + 1);
3367
+ after.keys = before.keys.slice(mid + 1);
3368
+ before.values = before.values.slice(0, mid + 1);
3369
+ before.keys = before.keys.slice(0, mid + 1);
3370
+ await this._updateNode(before);
3371
+ await this._updateNode(after);
3372
+ await this._insertInParent(before, after.values[0], after);
3373
+ }
3374
+ });
3125
3375
  }
3126
3376
  async _deleteEntry(node, key) {
3127
3377
  if (!node.leaf) {
@@ -3133,6 +3383,7 @@ var require_cjs = __commonJS({
3133
3383
  }
3134
3384
  }
3135
3385
  if (keyIndex !== -1) {
3386
+ node = this._cloneNode(node);
3136
3387
  node.keys.splice(keyIndex, 1);
3137
3388
  const valueIndex = keyIndex > 0 ? keyIndex - 1 : 0;
3138
3389
  node.values.splice(valueIndex, 1);
@@ -3142,7 +3393,7 @@ var require_cjs = __commonJS({
3142
3393
  if (this.rootId === node.id && node.keys.length === 1 && !node.leaf) {
3143
3394
  const keys = node.keys;
3144
3395
  this._deleteNode(node);
3145
- const newRoot = await this.getNode(keys[0]);
3396
+ const newRoot = this._cloneNode(await this.getNode(keys[0]));
3146
3397
  newRoot.parent = null;
3147
3398
  await this._updateNode(newRoot);
3148
3399
  await this._writeHead({
@@ -3150,14 +3401,17 @@ var require_cjs = __commonJS({
3150
3401
  order: this.order,
3151
3402
  data: this.strategy.head.data
3152
3403
  });
3153
- return;
3404
+ return node;
3154
3405
  } else if (this.rootId === node.id) {
3155
- const root = await this.getNode(this.rootId);
3156
- await this._updateNode(root);
3157
- return;
3406
+ await this._writeHead({
3407
+ root: node.id,
3408
+ order: this.order,
3409
+ data: this.strategy.head.data
3410
+ });
3411
+ return node;
3158
3412
  } else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
3159
3413
  if (node.parent === null) {
3160
- return;
3414
+ return node;
3161
3415
  }
3162
3416
  let isPredecessor = false;
3163
3417
  let parentNode = await this.getNode(node.parent);
@@ -3178,78 +3432,80 @@ var require_cjs = __commonJS({
3178
3432
  }
3179
3433
  }
3180
3434
  }
3181
- let pointer;
3435
+ let siblingNode;
3182
3436
  let guess;
3183
3437
  if (prevNode === null) {
3184
- pointer = nextNode;
3438
+ siblingNode = nextNode;
3185
3439
  guess = postValue;
3186
3440
  } else if (nextNode === null) {
3187
3441
  isPredecessor = true;
3188
- pointer = prevNode;
3442
+ siblingNode = prevNode;
3189
3443
  guess = prevValue;
3190
3444
  } else {
3191
3445
  if (node.values.length + nextNode.values.length < this.order) {
3192
- pointer = nextNode;
3446
+ siblingNode = nextNode;
3193
3447
  guess = postValue;
3194
3448
  } else {
3195
3449
  isPredecessor = true;
3196
- pointer = prevNode;
3450
+ siblingNode = prevNode;
3197
3451
  guess = prevValue;
3198
3452
  }
3199
3453
  }
3200
- if (!pointer) {
3201
- return;
3454
+ if (!siblingNode) {
3455
+ return node;
3202
3456
  }
3203
- if (node.values.length + pointer.values.length < this.order) {
3457
+ node = this._cloneNode(node);
3458
+ siblingNode = this._cloneNode(siblingNode);
3459
+ if (node.values.length + siblingNode.values.length < this.order) {
3204
3460
  if (!isPredecessor) {
3205
- const pTemp = pointer;
3206
- pointer = node;
3461
+ const pTemp = siblingNode;
3462
+ siblingNode = node;
3207
3463
  node = pTemp;
3208
3464
  }
3209
- pointer.keys.push(...node.keys);
3465
+ siblingNode.keys.push(...node.keys);
3210
3466
  if (!node.leaf) {
3211
- pointer.values.push(guess);
3467
+ siblingNode.values.push(guess);
3212
3468
  } else {
3213
- pointer.next = node.next;
3214
- if (pointer.next) {
3215
- const n = await this.getNode(pointer.next);
3216
- n.prev = pointer.id;
3469
+ siblingNode.next = node.next;
3470
+ if (siblingNode.next) {
3471
+ const n = this._cloneNode(await this.getNode(siblingNode.next));
3472
+ n.prev = siblingNode.id;
3217
3473
  await this._updateNode(n);
3218
3474
  }
3219
3475
  }
3220
- pointer.values.push(...node.values);
3221
- if (!pointer.leaf) {
3222
- const keys = pointer.keys;
3476
+ siblingNode.values.push(...node.values);
3477
+ if (!siblingNode.leaf) {
3478
+ const keys = siblingNode.keys;
3223
3479
  for (const key2 of keys) {
3224
- const node2 = await this.getNode(key2);
3225
- node2.parent = pointer.id;
3480
+ const node2 = this._cloneNode(await this.getNode(key2));
3481
+ node2.parent = siblingNode.id;
3226
3482
  await this._updateNode(node2);
3227
3483
  }
3228
3484
  }
3229
3485
  this._deleteNode(node);
3230
- await this._updateNode(pointer);
3486
+ await this._updateNode(siblingNode);
3231
3487
  await this._deleteEntry(await this.getNode(node.parent), node.id);
3232
3488
  } else {
3233
3489
  if (isPredecessor) {
3234
3490
  let pointerPm;
3235
3491
  let pointerKm;
3236
3492
  if (!node.leaf) {
3237
- pointerPm = pointer.keys.splice(-1)[0];
3238
- pointerKm = pointer.values.splice(-1)[0];
3493
+ pointerPm = siblingNode.keys.splice(-1)[0];
3494
+ pointerKm = siblingNode.values.splice(-1)[0];
3239
3495
  node.keys = [pointerPm, ...node.keys];
3240
3496
  node.values = [guess, ...node.values];
3241
- parentNode = await this.getNode(node.parent);
3497
+ parentNode = this._cloneNode(await this.getNode(node.parent));
3242
3498
  const nodeIndex = parentNode.keys.indexOf(node.id);
3243
3499
  if (nodeIndex > 0) {
3244
3500
  parentNode.values[nodeIndex - 1] = pointerKm;
3245
3501
  await this._updateNode(parentNode);
3246
3502
  }
3247
3503
  } else {
3248
- pointerPm = pointer.keys.splice(-1)[0];
3249
- pointerKm = pointer.values.splice(-1)[0];
3504
+ pointerPm = siblingNode.keys.splice(-1)[0];
3505
+ pointerKm = siblingNode.values.splice(-1)[0];
3250
3506
  node.keys = [pointerPm, ...node.keys];
3251
3507
  node.values = [pointerKm, ...node.values];
3252
- parentNode = await this.getNode(node.parent);
3508
+ parentNode = this._cloneNode(await this.getNode(node.parent));
3253
3509
  const nodeIndex = parentNode.keys.indexOf(node.id);
3254
3510
  if (nodeIndex > 0) {
3255
3511
  parentNode.values[nodeIndex - 1] = pointerKm;
@@ -3257,92 +3513,103 @@ var require_cjs = __commonJS({
3257
3513
  }
3258
3514
  }
3259
3515
  await this._updateNode(node);
3260
- await this._updateNode(pointer);
3516
+ await this._updateNode(siblingNode);
3261
3517
  } else {
3262
3518
  let pointerP0;
3263
3519
  let pointerK0;
3264
3520
  if (!node.leaf) {
3265
- pointerP0 = pointer.keys.splice(0, 1)[0];
3266
- pointerK0 = pointer.values.splice(0, 1)[0];
3521
+ pointerP0 = siblingNode.keys.splice(0, 1)[0];
3522
+ pointerK0 = siblingNode.values.splice(0, 1)[0];
3267
3523
  node.keys = [...node.keys, pointerP0];
3268
3524
  node.values = [...node.values, guess];
3269
- parentNode = await this.getNode(node.parent);
3270
- const pointerIndex = parentNode.keys.indexOf(pointer.id);
3525
+ parentNode = this._cloneNode(await this.getNode(node.parent));
3526
+ const pointerIndex = parentNode.keys.indexOf(siblingNode.id);
3271
3527
  if (pointerIndex > 0) {
3272
3528
  parentNode.values[pointerIndex - 1] = pointerK0;
3273
3529
  await this._updateNode(parentNode);
3274
3530
  }
3275
3531
  } else {
3276
- pointerP0 = pointer.keys.splice(0, 1)[0];
3277
- pointerK0 = pointer.values.splice(0, 1)[0];
3532
+ pointerP0 = siblingNode.keys.splice(0, 1)[0];
3533
+ pointerK0 = siblingNode.values.splice(0, 1)[0];
3278
3534
  node.keys = [...node.keys, pointerP0];
3279
3535
  node.values = [...node.values, pointerK0];
3280
- parentNode = await this.getNode(node.parent);
3281
- const pointerIndex = parentNode.keys.indexOf(pointer.id);
3536
+ parentNode = this._cloneNode(await this.getNode(node.parent));
3537
+ const pointerIndex = parentNode.keys.indexOf(siblingNode.id);
3282
3538
  if (pointerIndex > 0) {
3283
- parentNode.values[pointerIndex - 1] = pointer.values[0];
3539
+ parentNode.values[pointerIndex - 1] = siblingNode.values[0];
3284
3540
  await this._updateNode(parentNode);
3285
3541
  }
3286
3542
  }
3287
3543
  await this._updateNode(node);
3288
- await this._updateNode(pointer);
3544
+ await this._updateNode(siblingNode);
3289
3545
  }
3290
- if (!pointer.leaf) {
3291
- for (const key2 of pointer.keys) {
3292
- const n = await this.getNode(key2);
3293
- n.parent = pointer.id;
3546
+ if (!siblingNode.leaf) {
3547
+ for (const key2 of siblingNode.keys) {
3548
+ const n = this._cloneNode(await this.getNode(key2));
3549
+ n.parent = siblingNode.id;
3294
3550
  await this._updateNode(n);
3295
3551
  }
3296
3552
  }
3297
3553
  if (!node.leaf) {
3298
3554
  for (const key2 of node.keys) {
3299
- const n = await this.getNode(key2);
3555
+ const n = this._cloneNode(await this.getNode(key2));
3300
3556
  n.parent = node.id;
3301
3557
  await this._updateNode(n);
3302
3558
  }
3303
3559
  }
3304
3560
  if (!parentNode.leaf) {
3305
3561
  for (const key2 of parentNode.keys) {
3306
- const n = await this.getNode(key2);
3562
+ const n = this._cloneNode(await this.getNode(key2));
3307
3563
  n.parent = parentNode.id;
3308
3564
  await this._updateNode(n);
3309
3565
  }
3310
3566
  }
3311
3567
  }
3312
3568
  } else {
3313
- await this._updateNode(node);
3569
+ await this._updateNode(this._cloneNode(node));
3314
3570
  }
3571
+ return node;
3315
3572
  }
3316
3573
  async delete(key, value) {
3317
- let node = await this.insertableNodeByPrimary(value);
3318
- let found = false;
3319
- while (true) {
3320
- let i = node.values.length;
3321
- while (i--) {
3322
- const nValue = node.values[i];
3323
- if (this.comparator.isSame(value, nValue)) {
3324
- const keys = node.keys[i];
3325
- const keyIndex = keys.indexOf(key);
3326
- if (keyIndex !== -1) {
3327
- keys.splice(keyIndex, 1);
3328
- if (keys.length === 0) {
3329
- node.keys.splice(i, 1);
3330
- node.values.splice(i, 1);
3574
+ return this.writeLock(0, async () => {
3575
+ if (value === void 0) {
3576
+ value = await this.get(key);
3577
+ }
3578
+ if (value === void 0) {
3579
+ return;
3580
+ }
3581
+ let node = await this.insertableNodeByPrimary(value);
3582
+ let found = false;
3583
+ while (true) {
3584
+ let i = node.values.length;
3585
+ while (i--) {
3586
+ const nValue = node.values[i];
3587
+ if (this.comparator.isSame(value, nValue)) {
3588
+ const keys = node.keys[i];
3589
+ const keyIndex = keys.indexOf(key);
3590
+ if (keyIndex !== -1) {
3591
+ node = this._cloneNode(node);
3592
+ const freshKeys = node.keys[i];
3593
+ freshKeys.splice(keyIndex, 1);
3594
+ if (freshKeys.length === 0) {
3595
+ node.keys.splice(i, 1);
3596
+ node.values.splice(i, 1);
3597
+ }
3598
+ await this._updateNode(node);
3599
+ node = await this._deleteEntry(node, key);
3600
+ found = true;
3601
+ break;
3331
3602
  }
3332
- await this._updateNode(node);
3333
- await this._deleteEntry(node, key);
3334
- found = true;
3335
- break;
3336
3603
  }
3337
3604
  }
3605
+ if (found) break;
3606
+ if (node.next) {
3607
+ node = await this.getNode(node.next);
3608
+ continue;
3609
+ }
3610
+ break;
3338
3611
  }
3339
- if (found) break;
3340
- if (node.next) {
3341
- node = await this.getNode(node.next);
3342
- continue;
3343
- }
3344
- break;
3345
- }
3612
+ });
3346
3613
  }
3347
3614
  async getHeadData() {
3348
3615
  const head = await this._readHead();
@@ -3362,428 +3629,168 @@ var require_cjs = __commonJS({
3362
3629
  data
3363
3630
  });
3364
3631
  }
3365
- async commit(label) {
3366
- let result = await this.mvcc.commit(label);
3367
- if (result.success) {
3368
- result = await this.mvccRoot.commit(label);
3369
- if (result.success && this.rootTx !== this) {
3370
- this.rootTx.rootId = this.rootId;
3371
- }
3372
- if (result.success) {
3373
- for (const r of result.created) {
3374
- this.nodes.set(r.key, r.data);
3375
- }
3376
- for (const r of result.updated) {
3377
- this.nodes.set(r.key, r.data);
3378
- }
3379
- for (const r of result.deleted) {
3380
- this.nodes.delete(r.key);
3381
- }
3382
- }
3383
- }
3384
- return result;
3385
- }
3386
- rollback() {
3387
- return this.mvcc.rollback();
3388
- }
3389
- };
3390
- var BPTreeMVCCStrategyAsync = class extends AsyncMVCCStrategy {
3391
- constructor(strategy) {
3392
- super();
3393
- this.strategy = strategy;
3394
- }
3395
- async read(key) {
3396
- if (key === "__HEAD__") {
3397
- return await this.strategy.readHead();
3398
- }
3399
- return await this.strategy.read(key);
3400
- }
3401
- async write(key, value) {
3402
- if (key === "__HEAD__") {
3403
- await this.strategy.writeHead(value);
3404
- } else {
3405
- await this.strategy.write(key, value);
3406
- }
3407
- }
3408
- async delete(key) {
3409
- await this.strategy.delete(key);
3410
- }
3411
- async exists(key) {
3412
- if (key === "__HEAD__") {
3413
- return await this.strategy.readHead() !== null;
3414
- }
3415
- try {
3416
- const node = await this.strategy.read(key);
3417
- return node !== null && node !== void 0;
3418
- } catch {
3419
- return false;
3420
- }
3421
- }
3422
- };
3423
- var BPTreeAsync2 = class extends BPTreeAsyncTransaction2 {
3424
- constructor(strategy, comparator, option) {
3425
- const mvccRoot = new AsyncMVCCTransaction(new BPTreeMVCCStrategyAsync(strategy));
3426
- super(
3427
- null,
3428
- mvccRoot,
3429
- mvccRoot,
3430
- strategy,
3431
- comparator,
3432
- option
3433
- );
3434
- }
3435
- /**
3436
- * Creates a new asynchronous transaction.
3437
- * @returns A new BPTreeAsyncTransaction.
3438
- */
3439
- async createTransaction() {
3440
- const nestedTx = await this.mvcc.createNested();
3441
- const tx = new BPTreeAsyncTransaction2(
3442
- this,
3443
- this.mvcc,
3444
- nestedTx,
3445
- this.strategy,
3446
- this.comparator,
3447
- this.option
3448
- );
3449
- await tx.init();
3450
- return tx;
3451
- }
3452
- async insert(key, value) {
3453
- const tx = await this.createTransaction();
3454
- await tx.insert(key, value);
3455
- const result = await tx.commit();
3456
- if (!result.success) {
3457
- throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
3458
- }
3459
- this.rootId = tx.getRootId();
3460
- }
3461
- async delete(key, value) {
3462
- const tx = await this.createTransaction();
3463
- await tx.delete(key, value);
3464
- const result = await tx.commit();
3465
- if (!result.success) {
3466
- throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
3467
- }
3468
- this.rootId = tx.getRootId();
3469
- }
3470
- };
3471
- var SerializeStrategy = class {
3472
- order;
3473
- head;
3474
- constructor(order) {
3475
- this.order = order;
3476
- this.head = {
3477
- order,
3478
- root: null,
3479
- data: {}
3480
- };
3481
- }
3482
- };
3483
- var SerializeStrategySync = class extends SerializeStrategy {
3484
- getHeadData(key, defaultValue) {
3485
- if (!Object.hasOwn(this.head.data, key)) {
3486
- this.setHeadData(key, defaultValue);
3487
- }
3488
- return this.head.data[key];
3489
- }
3490
- setHeadData(key, data) {
3491
- this.head.data[key] = data;
3492
- this.writeHead(this.head);
3493
- }
3494
- autoIncrement(key, defaultValue) {
3495
- const current = this.getHeadData(key, defaultValue);
3496
- const next = current + 1;
3497
- this.setHeadData(key, next);
3498
- return current;
3499
- }
3500
- };
3501
- var InMemoryStoreStrategySync = class extends SerializeStrategySync {
3502
- node;
3503
- constructor(order) {
3504
- super(order);
3505
- this.node = {};
3506
- }
3507
- id(isLeaf) {
3508
- return this.autoIncrement("index", 1).toString();
3509
- }
3510
- read(id) {
3511
- if (!Object.hasOwn(this.node, id)) {
3512
- throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
3513
- }
3514
- const node = this.node[id];
3515
- return JSON.parse(JSON.stringify(node));
3516
- }
3517
- write(id, node) {
3518
- this.node[id] = node;
3519
- }
3520
- delete(id) {
3521
- delete this.node[id];
3522
- }
3523
- readHead() {
3524
- if (this.head.root === null) {
3525
- return null;
3526
- }
3527
- return this.head;
3528
- }
3529
- writeHead(head) {
3530
- this.head = head;
3531
- }
3532
- };
3533
- var Ryoiki22 = class _Ryoiki2 {
3534
- readings;
3535
- writings;
3536
- readQueue;
3537
- writeQueue;
3538
- static async CatchError(promise) {
3539
- return await promise.then((v) => [void 0, v]).catch((err) => [err]);
3540
- }
3541
- static IsRangeOverlap(a, b) {
3542
- const [start1, end1] = a;
3543
- const [start2, end2] = b;
3544
- if (end1 <= start2 || end2 <= start1) {
3545
- return false;
3546
- }
3547
- return true;
3548
- }
3549
- static ERR_ALREADY_EXISTS(lockId) {
3550
- return new Error(`The '${lockId}' task already existing in queue or running.`);
3551
- }
3552
- static ERR_NOT_EXISTS(lockId) {
3553
- return new Error(`The '${lockId}' task not existing in task queue.`);
3554
- }
3555
- static ERR_TIMEOUT(lockId, timeout) {
3556
- return new Error(`The task with ID '${lockId}' failed to acquire the lock within the timeout(${timeout}ms).`);
3557
- }
3558
- /**
3559
- * Constructs a new instance of the Ryoiki class.
3560
- */
3561
- constructor() {
3562
- this.readings = /* @__PURE__ */ new Map();
3563
- this.writings = /* @__PURE__ */ new Map();
3564
- this.readQueue = /* @__PURE__ */ new Map();
3565
- this.writeQueue = /* @__PURE__ */ new Map();
3566
- }
3567
- /**
3568
- * Creates a range based on a start value and length.
3569
- * @param start - The starting value of the range.
3570
- * @param length - The length of the range.
3571
- * @returns A range tuple [start, start + length].
3572
- */
3573
- range(start, length) {
3574
- return [start, start + length];
3575
- }
3576
- rangeOverlapping(tasks, range) {
3577
- return Array.from(tasks.values()).some((t) => _Ryoiki2.IsRangeOverlap(t.range, range));
3578
- }
3579
- isSameRange(a, b) {
3580
- const [a1, a2] = a;
3581
- const [b1, b2] = b;
3582
- return a1 === b1 && a2 === b2;
3583
- }
3584
- fetchUnitAndRun(queue, workspaces) {
3585
- for (const [id, unit] of queue) {
3586
- if (!unit.condition()) {
3587
- continue;
3588
- }
3589
- this._alloc(queue, workspaces, id);
3590
- }
3591
- }
3592
- _handleOverload(args, handlers, argPatterns) {
3593
- for (const [key, pattern] of Object.entries(argPatterns)) {
3594
- if (this._matchArgs(args, pattern)) {
3595
- return handlers[key](...args);
3632
+ async commit(label) {
3633
+ let result = await this.mvcc.commit(label);
3634
+ if (result.success) {
3635
+ const isRootTx = this.rootTx === this;
3636
+ if (!isRootTx) {
3637
+ result = await this.rootTx.commit(label);
3638
+ if (result.success) {
3639
+ this.rootTx.rootId = this.rootId;
3640
+ }
3596
3641
  }
3597
3642
  }
3598
- throw new Error("Invalid arguments");
3643
+ return result;
3599
3644
  }
3600
- _matchArgs(args, pattern) {
3601
- return args.every((arg, index) => {
3602
- const expectedType = pattern[index];
3603
- if (expectedType === void 0) return typeof arg === "undefined";
3604
- if (expectedType === Function) return typeof arg === "function";
3605
- if (expectedType === Number) return typeof arg === "number";
3606
- if (expectedType === Array) return Array.isArray(arg);
3607
- return false;
3608
- });
3645
+ async rollback() {
3646
+ return this.mvcc.rollback();
3609
3647
  }
3610
- _createRandomId() {
3611
- const timestamp = Date.now().toString(36);
3612
- const random = Math.random().toString(36).substring(2);
3613
- return `${timestamp}${random}`;
3648
+ };
3649
+ var BPTreeMVCCStrategyAsync = class extends AsyncMVCCStrategy {
3650
+ constructor(strategy) {
3651
+ super();
3652
+ this.strategy = strategy;
3614
3653
  }
3615
- _alloc(queue, workspaces, lockId) {
3616
- const unit = queue.get(lockId);
3617
- if (!unit) {
3618
- throw _Ryoiki2.ERR_NOT_EXISTS(lockId);
3654
+ async read(key) {
3655
+ if (key === "__HEAD__") {
3656
+ return await this.strategy.readHead();
3619
3657
  }
3620
- workspaces.set(lockId, unit);
3621
- queue.delete(lockId);
3622
- unit.alloc();
3658
+ return await this.strategy.read(key);
3623
3659
  }
3624
- _free(workspaces, lockId) {
3625
- const unit = workspaces.get(lockId);
3626
- if (!unit) {
3627
- throw _Ryoiki2.ERR_NOT_EXISTS(lockId);
3660
+ async write(key, value) {
3661
+ if (key === "__HEAD__") {
3662
+ await this.strategy.writeHead(value);
3663
+ } else {
3664
+ await this.strategy.write(key, value);
3628
3665
  }
3629
- workspaces.delete(lockId);
3630
- unit.free();
3631
3666
  }
3632
- _lock(queue, range, timeout, task, condition) {
3633
- return new Promise((resolve, reject) => {
3634
- let timeoutId = null;
3635
- if (timeout >= 0) {
3636
- timeoutId = setTimeout(() => {
3637
- reject(_Ryoiki2.ERR_TIMEOUT(id, timeout));
3638
- }, timeout);
3639
- }
3640
- const id = this._createRandomId();
3641
- const alloc = async () => {
3642
- if (timeoutId !== null) {
3643
- clearTimeout(timeoutId);
3644
- }
3645
- const [err, v] = await _Ryoiki2.CatchError(task(id));
3646
- if (err) reject(err);
3647
- else resolve(v);
3648
- };
3649
- const fetch = () => {
3650
- this.fetchUnitAndRun(this.readQueue, this.readings);
3651
- this.fetchUnitAndRun(this.writeQueue, this.writings);
3652
- };
3653
- queue.set(id, { id, range, condition, alloc, free: fetch });
3654
- fetch();
3655
- });
3667
+ async delete(key) {
3668
+ await this.strategy.delete(key);
3656
3669
  }
3657
- _checkWorking(range, workspaces) {
3658
- let isLocked = false;
3659
- for (const lock of workspaces.values()) {
3660
- if (_Ryoiki2.IsRangeOverlap(range, lock.range)) {
3661
- isLocked = true;
3662
- break;
3663
- }
3670
+ async exists(key) {
3671
+ if (key === "__HEAD__") {
3672
+ return await this.strategy.readHead() !== null;
3673
+ }
3674
+ try {
3675
+ const node = await this.strategy.read(key);
3676
+ return node !== null && node !== void 0;
3677
+ } catch {
3678
+ return false;
3664
3679
  }
3665
- return isLocked;
3666
- }
3667
- /**
3668
- * Checks if there is any active read lock within the specified range.
3669
- * @param range The range to check for active read locks.
3670
- * @returns `true` if there is an active read lock within the range, `false` otherwise.
3671
- */
3672
- isReading(range) {
3673
- return this._checkWorking(range, this.readings);
3674
- }
3675
- /**
3676
- * Checks if there is any active write lock within the specified range.
3677
- * @param range The range to check for active write locks.
3678
- * @returns `true` if there is an active write lock within the range, `false` otherwise.
3679
- */
3680
- isWriting(range) {
3681
- return this._checkWorking(range, this.writings);
3682
- }
3683
- /**
3684
- * Checks if a read lock can be acquired within the specified range.
3685
- * @param range The range to check for read lock availability.
3686
- * @returns `true` if a read lock can be acquired, `false` otherwise.
3687
- */
3688
- canRead(range) {
3689
- const writing = this.isWriting(range);
3690
- return !writing;
3691
3680
  }
3692
- /**
3693
- * Checks if a write lock can be acquired within the specified range.
3694
- * @param range The range to check for write lock availability.
3695
- * @returns `true` if a write lock can be acquired, `false` otherwise.
3696
- */
3697
- canWrite(range) {
3698
- const reading = this.isReading(range);
3699
- const writing = this.isWriting(range);
3700
- return !reading && !writing;
3681
+ };
3682
+ var BPTreeAsync2 = class extends BPTreeAsyncTransaction2 {
3683
+ constructor(strategy, comparator, option) {
3684
+ const mvccRoot = new AsyncMVCCTransaction(new BPTreeMVCCStrategyAsync(strategy), {
3685
+ cacheCapacity: option?.capacity ?? void 0
3686
+ });
3687
+ super(
3688
+ null,
3689
+ mvccRoot,
3690
+ mvccRoot,
3691
+ strategy,
3692
+ comparator,
3693
+ option
3694
+ );
3701
3695
  }
3702
3696
  /**
3703
- * Internal implementation of the read lock. Handles both overloads.
3704
- * @template T - The return type of the task.
3705
- * @param arg0 - Either a range or a task callback.
3706
- * If a range is provided, the task is the second argument.
3707
- * @param arg1 - The task to execute, required if a range is provided.
3708
- * @param arg2 - The timeout for acquiring the lock.
3709
- * If the lock cannot be acquired within this period, an error will be thrown.
3710
- * If this value is not provided, no timeout will be set.
3711
- * @returns A promise resolving to the result of the task execution.
3697
+ * Creates a new asynchronous transaction.
3698
+ * @returns A new BPTreeAsyncTransaction.
3712
3699
  */
3713
- readLock(arg0, arg1, arg2) {
3714
- const [range, task, timeout] = this._handleOverload(
3715
- [arg0, arg1, arg2],
3716
- {
3717
- rangeTask: (range2, task2) => [range2, task2, -1],
3718
- rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
3719
- task: (task2) => [[-Infinity, Infinity], task2, -1],
3720
- taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
3721
- },
3722
- {
3723
- task: [Function],
3724
- taskTimeout: [Function, Number],
3725
- rangeTask: [Array, Function],
3726
- rangeTaskTimeout: [Array, Function, Number]
3727
- }
3728
- );
3729
- return this._lock(
3730
- this.readQueue,
3731
- range,
3732
- timeout,
3733
- task,
3734
- () => !this.rangeOverlapping(this.writings, range)
3700
+ async createTransaction() {
3701
+ const nestedTx = this.mvcc.createNested();
3702
+ const tx = new BPTreeAsyncTransaction2(
3703
+ this,
3704
+ this.mvcc,
3705
+ nestedTx,
3706
+ this.strategy,
3707
+ this.comparator,
3708
+ this.option
3735
3709
  );
3710
+ await tx._initInternal();
3711
+ return tx;
3736
3712
  }
3737
- /**
3738
- * Internal implementation of the write lock. Handles both overloads.
3739
- * @template T - The return type of the task.
3740
- * @param arg0 - Either a range or a task callback.
3741
- * If a range is provided, the task is the second argument.
3742
- * @param arg1 - The task to execute, required if a range is provided.
3743
- * @param arg2 - The timeout for acquiring the lock.
3744
- * If the lock cannot be acquired within this period, an error will be thrown.
3745
- * If this value is not provided, no timeout will be set.
3746
- * @returns A promise resolving to the result of the task execution.
3747
- */
3748
- writeLock(arg0, arg1, arg2) {
3749
- const [range, task, timeout] = this._handleOverload(
3750
- [arg0, arg1, arg2],
3751
- {
3752
- rangeTask: (range2, task2) => [range2, task2, -1],
3753
- rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
3754
- task: (task2) => [[-Infinity, Infinity], task2, -1],
3755
- taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
3756
- },
3757
- {
3758
- task: [Function],
3759
- taskTimeout: [Function, Number],
3760
- rangeTask: [Array, Function],
3761
- rangeTaskTimeout: [Array, Function, Number]
3713
+ async insert(key, value) {
3714
+ return this.writeLock(1, async () => {
3715
+ const tx = await this.createTransaction();
3716
+ await tx.insert(key, value);
3717
+ const result = await tx.commit();
3718
+ if (!result.success) {
3719
+ throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
3762
3720
  }
3763
- );
3764
- return this._lock(
3765
- this.writeQueue,
3766
- range,
3767
- timeout,
3768
- task,
3769
- () => {
3770
- return !this.rangeOverlapping(this.writings, range) && !this.rangeOverlapping(this.readings, range);
3721
+ });
3722
+ }
3723
+ async delete(key, value) {
3724
+ return this.writeLock(1, async () => {
3725
+ const tx = await this.createTransaction();
3726
+ await tx.delete(key, value);
3727
+ const result = await tx.commit();
3728
+ if (!result.success) {
3729
+ throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
3771
3730
  }
3772
- );
3731
+ });
3732
+ }
3733
+ };
3734
+ var SerializeStrategy = class {
3735
+ order;
3736
+ head;
3737
+ constructor(order) {
3738
+ this.order = order;
3739
+ this.head = {
3740
+ order,
3741
+ root: null,
3742
+ data: {}
3743
+ };
3744
+ }
3745
+ };
3746
+ var SerializeStrategySync = class extends SerializeStrategy {
3747
+ getHeadData(key, defaultValue) {
3748
+ if (!Object.hasOwn(this.head.data, key)) {
3749
+ this.setHeadData(key, defaultValue);
3750
+ }
3751
+ return this.head.data[key];
3752
+ }
3753
+ setHeadData(key, data) {
3754
+ this.head.data[key] = data;
3755
+ this.writeHead(this.head);
3756
+ }
3757
+ autoIncrement(key, defaultValue) {
3758
+ const current = this.getHeadData(key, defaultValue);
3759
+ const next = current + 1;
3760
+ this.setHeadData(key, next);
3761
+ return current;
3762
+ }
3763
+ };
3764
+ var InMemoryStoreStrategySync = class extends SerializeStrategySync {
3765
+ node;
3766
+ constructor(order) {
3767
+ super(order);
3768
+ this.node = {};
3773
3769
  }
3774
- /**
3775
- * Releases a read lock by its lock ID.
3776
- * @param lockId - The unique identifier for the lock to release.
3777
- */
3778
- readUnlock(lockId) {
3779
- this._free(this.readings, lockId);
3770
+ id(isLeaf) {
3771
+ return this.autoIncrement("index", 1).toString();
3780
3772
  }
3781
- /**
3782
- * Releases a write lock by its lock ID.
3783
- * @param lockId - The unique identifier for the lock to release.
3784
- */
3785
- writeUnlock(lockId) {
3786
- this._free(this.writings, lockId);
3773
+ read(id) {
3774
+ if (!Object.hasOwn(this.node, id)) {
3775
+ throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
3776
+ }
3777
+ const node = this.node[id];
3778
+ return JSON.parse(JSON.stringify(node));
3779
+ }
3780
+ write(id, node) {
3781
+ this.node[id] = node;
3782
+ }
3783
+ delete(id) {
3784
+ delete this.node[id];
3785
+ }
3786
+ readHead() {
3787
+ if (this.head.root === null) {
3788
+ return null;
3789
+ }
3790
+ return this.head;
3791
+ }
3792
+ writeHead(head) {
3793
+ this.head = head;
3787
3794
  }
3788
3795
  };
3789
3796
  var SerializeStrategyAsync2 = class extends SerializeStrategy {
@@ -4224,7 +4231,7 @@ var require_cjs = __commonJS({
4224
4231
  this.tail = null;
4225
4232
  }
4226
4233
  };
4227
- var CacheEntanglement2 = class {
4234
+ var CacheEntanglement = class {
4228
4235
  creation;
4229
4236
  beforeUpdateHook;
4230
4237
  capacity;
@@ -4325,7 +4332,7 @@ var require_cjs = __commonJS({
4325
4332
  }
4326
4333
  }
4327
4334
  };
4328
- var CacheData2 = class _CacheData2 {
4335
+ var CacheData = class _CacheData {
4329
4336
  static StructuredClone = globalThis.structuredClone.bind(globalThis);
4330
4337
  _value;
4331
4338
  constructor(value) {
@@ -4365,11 +4372,11 @@ var require_cjs = __commonJS({
4365
4372
  return Object.assign({}, this.raw);
4366
4373
  case "deep-copy":
4367
4374
  default:
4368
- return _CacheData2.StructuredClone(this.raw);
4375
+ return _CacheData.StructuredClone(this.raw);
4369
4376
  }
4370
4377
  }
4371
4378
  };
4372
- var CacheEntanglementSync2 = class extends CacheEntanglement2 {
4379
+ var CacheEntanglementSync = class extends CacheEntanglement {
4373
4380
  constructor(creation, option) {
4374
4381
  super(creation, option);
4375
4382
  }
@@ -4399,7 +4406,7 @@ var require_cjs = __commonJS({
4399
4406
  const dependencyValue = dependency.recache(key) ?? dependency.recache(dependencyKey);
4400
4407
  resolved[name] = dependencyValue;
4401
4408
  }
4402
- const value = new CacheData2(this.creation(key, resolved, ...parameter));
4409
+ const value = new CacheData(this.creation(key, resolved, ...parameter));
4403
4410
  this.updateRequirements.delete(key);
4404
4411
  this.parameters.set(key, parameter);
4405
4412
  this.caches.set(key, value);
@@ -4423,7 +4430,7 @@ var require_cjs = __commonJS({
4423
4430
  return this.caches.get(key);
4424
4431
  }
4425
4432
  };
4426
- var CacheEntanglementAsync = class extends CacheEntanglement2 {
4433
+ var CacheEntanglementAsync = class extends CacheEntanglement {
4427
4434
  constructor(creation, option) {
4428
4435
  super(creation, option);
4429
4436
  }
@@ -4453,7 +4460,7 @@ var require_cjs = __commonJS({
4453
4460
  const dependencyValue = await dependency.recache(key) ?? await dependency.recache(dependencyKey);
4454
4461
  resolved[name] = dependencyValue;
4455
4462
  }
4456
- const value = new CacheData2(await this.creation(key, resolved, ...parameter));
4463
+ const value = new CacheData(await this.creation(key, resolved, ...parameter));
4457
4464
  this.updateRequirements.delete(key);
4458
4465
  this.parameters.set(key, parameter);
4459
4466
  this.caches.set(key, value);
@@ -4556,6 +4563,42 @@ var require_cjs = __commonJS({
4556
4563
  };
4557
4564
  var MVCCStrategy2 = class {
4558
4565
  };
4566
+ var LRUMap3 = class {
4567
+ cache = /* @__PURE__ */ new Map();
4568
+ capacity;
4569
+ constructor(capacity) {
4570
+ this.capacity = capacity;
4571
+ }
4572
+ get(key) {
4573
+ if (!this.cache.has(key)) return void 0;
4574
+ const value = this.cache.get(key);
4575
+ this.cache.delete(key);
4576
+ this.cache.set(key, value);
4577
+ return value;
4578
+ }
4579
+ set(key, value) {
4580
+ if (this.cache.has(key)) {
4581
+ this.cache.delete(key);
4582
+ } else if (this.cache.size >= this.capacity) {
4583
+ const oldestKey = this.cache.keys().next().value;
4584
+ if (oldestKey !== void 0) this.cache.delete(oldestKey);
4585
+ }
4586
+ this.cache.set(key, value);
4587
+ return this;
4588
+ }
4589
+ has(key) {
4590
+ return this.cache.has(key);
4591
+ }
4592
+ delete(key) {
4593
+ return this.cache.delete(key);
4594
+ }
4595
+ clear() {
4596
+ this.cache.clear();
4597
+ }
4598
+ get size() {
4599
+ return this.cache.size;
4600
+ }
4601
+ };
4559
4602
  var MVCCTransaction2 = class {
4560
4603
  committed;
4561
4604
  snapshotVersion;
@@ -4563,11 +4606,11 @@ var require_cjs = __commonJS({
4563
4606
  writeBuffer;
4564
4607
  deleteBuffer;
4565
4608
  createdKeys;
4566
- // create()로 생성된 키 추적
4567
4609
  deletedValues;
4568
4610
  // delete 시 삭제 전 값 저장
4569
4611
  originallyExisted;
4570
4612
  // 트랜잭션 시작 시점에 디스크에 존재했던 키 (deleted 결과 필터링용)
4613
+ bufferHistory = /* @__PURE__ */ new Map();
4571
4614
  // Nested Transaction Properties
4572
4615
  parent;
4573
4616
  localVersion;
@@ -4581,7 +4624,8 @@ var require_cjs = __commonJS({
4581
4624
  versionIndex = /* @__PURE__ */ new Map();
4582
4625
  deletedCache = /* @__PURE__ */ new Map();
4583
4626
  activeTransactions = /* @__PURE__ */ new Set();
4584
- constructor(strategy, parent, snapshotVersion) {
4627
+ diskCache;
4628
+ constructor(strategy, options, parent, snapshotVersion) {
4585
4629
  this.snapshotVersion = snapshotVersion ?? 0;
4586
4630
  this.writeBuffer = /* @__PURE__ */ new Map();
4587
4631
  this.deleteBuffer = /* @__PURE__ */ new Set();
@@ -4596,6 +4640,7 @@ var require_cjs = __commonJS({
4596
4640
  this.snapshotLocalVersion = parent.localVersion;
4597
4641
  this.strategy = void 0;
4598
4642
  this.root = parent.root;
4643
+ this.diskCache = parent.diskCache;
4599
4644
  } else {
4600
4645
  if (!strategy) throw new Error("Root Transaction must get Strategy");
4601
4646
  this.strategy = strategy;
@@ -4603,8 +4648,13 @@ var require_cjs = __commonJS({
4603
4648
  this.localVersion = 0;
4604
4649
  this.snapshotLocalVersion = 0;
4605
4650
  this.root = this;
4651
+ this.diskCache = new LRUMap3(options?.cacheCapacity ?? 1e3);
4606
4652
  }
4607
4653
  }
4654
+ /**
4655
+ * Checks if the transaction is a root transaction.
4656
+ * @returns True if the transaction is a root transaction, false otherwise.
4657
+ */
4608
4658
  isRoot() {
4609
4659
  return !this.parent;
4610
4660
  }
@@ -4621,27 +4671,96 @@ var require_cjs = __commonJS({
4621
4671
  }
4622
4672
  return false;
4623
4673
  }
4624
- // --- Internal buffer manipulation helpers ---
4625
- _bufferCreate(key, value) {
4626
- this.localVersion++;
4674
+ /**
4675
+ * Checks if a key was written in this transaction.
4676
+ * @param key The key to check.
4677
+ * @returns True if the key was written in this transaction, false otherwise.
4678
+ */
4679
+ isWrote(key) {
4680
+ return this.writeBuffer.has(key);
4681
+ }
4682
+ /**
4683
+ * Checks if a key was deleted in this transaction.
4684
+ * @param key The key to check.
4685
+ * @returns True if the key was deleted in this transaction, false otherwise.
4686
+ */
4687
+ isDeleted(key) {
4688
+ return this.deleteBuffer.has(key);
4689
+ }
4690
+ _recordHistory(key) {
4691
+ const existsInWriteBuffer = this.writeBuffer.has(key);
4692
+ const existsInDeleteBuffer = this.deleteBuffer.has(key);
4693
+ const currentVer = this.keyVersions.get(key);
4694
+ if (currentVer !== void 0) {
4695
+ if (!this.bufferHistory.has(key)) this.bufferHistory.set(key, []);
4696
+ this.bufferHistory.get(key).push({
4697
+ value: existsInWriteBuffer ? this.writeBuffer.get(key) : this.deletedValues.get(key) ?? null,
4698
+ exists: existsInWriteBuffer || !existsInDeleteBuffer,
4699
+ version: currentVer
4700
+ });
4701
+ }
4702
+ }
4703
+ /**
4704
+ * BINARY SEARCH HELPER: Finds the index of the last element in the array
4705
+ * where item[key] <= target. Assumes the array is sorted by 'key' ascending.
4706
+ */
4707
+ _findLastLE(array, target, property) {
4708
+ let left = 0;
4709
+ let right = array.length - 1;
4710
+ let result = -1;
4711
+ while (left <= right) {
4712
+ const mid = left + right >> 1;
4713
+ if (array[mid][property] <= target) {
4714
+ result = mid;
4715
+ left = mid + 1;
4716
+ } else {
4717
+ right = mid - 1;
4718
+ }
4719
+ }
4720
+ return result;
4721
+ }
4722
+ /**
4723
+ * BINARY SEARCH HELPER: Finds the index of the element in the array
4724
+ * where item[key] === target. Assumes the array is sorted by 'key' ascending.
4725
+ */
4726
+ _findExact(array, target, property) {
4727
+ let left = 0;
4728
+ let right = array.length - 1;
4729
+ while (left <= right) {
4730
+ const mid = left + right >> 1;
4731
+ const val = array[mid][property];
4732
+ if (val === target) return mid;
4733
+ if (val < target) left = mid + 1;
4734
+ else right = mid - 1;
4735
+ }
4736
+ return -1;
4737
+ }
4738
+ _bufferCreate(key, value, version) {
4739
+ if (version === void 0) this.localVersion++;
4740
+ const targetVersion = version ?? this.localVersion;
4741
+ this._recordHistory(key);
4627
4742
  this.writeBuffer.set(key, value);
4628
4743
  this.createdKeys.add(key);
4629
4744
  this.deleteBuffer.delete(key);
4630
4745
  this.originallyExisted.delete(key);
4631
- this.keyVersions.set(key, this.localVersion);
4746
+ this.keyVersions.set(key, targetVersion);
4632
4747
  }
4633
- _bufferWrite(key, value) {
4634
- this.localVersion++;
4748
+ _bufferWrite(key, value, version) {
4749
+ if (version === void 0) this.localVersion++;
4750
+ const targetVersion = version ?? this.localVersion;
4751
+ this._recordHistory(key);
4635
4752
  this.writeBuffer.set(key, value);
4636
4753
  this.deleteBuffer.delete(key);
4637
- this.keyVersions.set(key, this.localVersion);
4754
+ this.keyVersions.set(key, targetVersion);
4638
4755
  }
4639
- _bufferDelete(key) {
4640
- this.localVersion++;
4756
+ _bufferDelete(key, version) {
4757
+ if (version === void 0) this.localVersion++;
4758
+ const targetVersion = version ?? this.localVersion;
4759
+ this._recordHistory(key);
4641
4760
  this.deleteBuffer.add(key);
4642
4761
  this.writeBuffer.delete(key);
4643
4762
  this.createdKeys.delete(key);
4644
- this.keyVersions.set(key, this.localVersion);
4763
+ this.keyVersions.set(key, targetVersion);
4645
4764
  }
4646
4765
  /**
4647
4766
  * Returns the entries that will be created, updated, and deleted by this transaction.
@@ -4665,7 +4784,11 @@ var require_cjs = __commonJS({
4665
4784
  deleted.push({ key, data });
4666
4785
  }
4667
4786
  }
4668
- return { created, updated, deleted };
4787
+ return {
4788
+ created,
4789
+ updated,
4790
+ deleted
4791
+ };
4669
4792
  }
4670
4793
  /**
4671
4794
  * Rolls back the transaction.
@@ -4683,7 +4806,36 @@ var require_cjs = __commonJS({
4683
4806
  if (this.root !== this) {
4684
4807
  this.root.activeTransactions.delete(this);
4685
4808
  }
4686
- return { success: true, created, updated, deleted };
4809
+ return {
4810
+ success: true,
4811
+ created,
4812
+ updated,
4813
+ deleted
4814
+ };
4815
+ }
4816
+ /**
4817
+ * Checks for conflicts among multiple transactions.
4818
+ * A conflict occurs if two or more transactions modify (write or delete) the same key.
4819
+ * @param transactions Array of transactions to check.
4820
+ * @returns An array of keys that are in conflict.
4821
+ */
4822
+ static CheckConflicts(transactions) {
4823
+ const modifiedKeys = /* @__PURE__ */ new Map();
4824
+ const conflicts = /* @__PURE__ */ new Set();
4825
+ for (const tx of transactions) {
4826
+ const txModified = /* @__PURE__ */ new Set([
4827
+ ...tx.writeBuffer.keys(),
4828
+ ...tx.deleteBuffer
4829
+ ]);
4830
+ for (const key of txModified) {
4831
+ const count = modifiedKeys.get(key) ?? 0;
4832
+ if (count > 0) {
4833
+ conflicts.add(key);
4834
+ }
4835
+ modifiedKeys.set(key, count + 1);
4836
+ }
4837
+ }
4838
+ return Array.from(conflicts);
4687
4839
  }
4688
4840
  /**
4689
4841
  * Cleans up both deletedCache and versionIndex based on minActiveVersion.
@@ -4718,7 +4870,9 @@ var require_cjs = __commonJS({
4718
4870
  break;
4719
4871
  }
4720
4872
  }
4721
- if (latestInSnapshotIdx > 0) {
4873
+ if (latestInSnapshotIdx === versions.length - 1) {
4874
+ this.versionIndex.delete(key);
4875
+ } else if (latestInSnapshotIdx > 0) {
4722
4876
  versions.splice(0, latestInSnapshotIdx);
4723
4877
  }
4724
4878
  }
@@ -4767,7 +4921,7 @@ var require_cjs = __commonJS({
4767
4921
  createNested() {
4768
4922
  if (this.committed) throw new Error("Transaction already committed");
4769
4923
  const childVersion = this.isRoot() ? this.version : this.snapshotVersion;
4770
- const child = new _SyncMVCCTransaction2(void 0, this, childVersion);
4924
+ const child = new _SyncMVCCTransaction2(void 0, void 0, this, childVersion);
4771
4925
  this.root.activeTransactions.add(child);
4772
4926
  return child;
4773
4927
  }
@@ -4775,32 +4929,77 @@ var require_cjs = __commonJS({
4775
4929
  if (this.committed) throw new Error("Transaction already committed");
4776
4930
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
4777
4931
  if (this.deleteBuffer.has(key)) return null;
4778
- return this.root._diskRead(key, this.snapshotVersion);
4932
+ if (this.parent) {
4933
+ return this.parent._readSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
4934
+ }
4935
+ return this._diskRead(key, this.snapshotVersion);
4779
4936
  }
4780
4937
  exists(key) {
4781
4938
  if (this.committed) throw new Error("Transaction already committed");
4782
4939
  if (this.deleteBuffer.has(key)) return false;
4783
4940
  if (this.writeBuffer.has(key)) return true;
4784
- return this.root._diskExists(key, this.snapshotVersion);
4941
+ if (this.parent) {
4942
+ return this.parent._existsSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
4943
+ }
4944
+ return this._diskExists(key, this.snapshotVersion);
4785
4945
  }
4786
- _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
4787
- if (this.writeBuffer.has(key)) {
4788
- const keyModVersion = this.keyVersions.get(key);
4789
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
4790
- return this.writeBuffer.get(key);
4946
+ _existsSnapshot(key, snapshotVersion, snapshotLocalVersion) {
4947
+ let current = this;
4948
+ let slVer = snapshotLocalVersion;
4949
+ while (current) {
4950
+ if (current.writeBuffer.has(key)) {
4951
+ const keyModVersion = current.keyVersions.get(key);
4952
+ if (slVer === void 0 || keyModVersion <= slVer) return true;
4953
+ }
4954
+ if (current.deleteBuffer.has(key)) {
4955
+ const keyModVersion = current.keyVersions.get(key);
4956
+ if (slVer === void 0 || keyModVersion <= slVer) return false;
4957
+ }
4958
+ const history = current.bufferHistory.get(key);
4959
+ if (history && slVer !== void 0) {
4960
+ const idx = current._findLastLE(history, slVer, "version");
4961
+ if (idx >= 0) return history[idx].exists;
4962
+ }
4963
+ if (current.parent) {
4964
+ slVer = current.snapshotLocalVersion;
4965
+ current = current.parent;
4966
+ } else {
4967
+ return current._diskExists(key, snapshotVersion);
4791
4968
  }
4792
4969
  }
4793
- if (this.deleteBuffer.has(key)) {
4794
- const keyModVersion = this.keyVersions.get(key);
4795
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
4796
- return null;
4970
+ return false;
4971
+ }
4972
+ _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
4973
+ let current = this;
4974
+ let slVer = snapshotLocalVersion;
4975
+ while (current) {
4976
+ if (current.writeBuffer.has(key)) {
4977
+ const keyModVersion = current.keyVersions.get(key);
4978
+ if (slVer === void 0 || keyModVersion <= slVer) {
4979
+ return current.writeBuffer.get(key);
4980
+ }
4981
+ }
4982
+ if (current.deleteBuffer.has(key)) {
4983
+ const keyModVersion = current.keyVersions.get(key);
4984
+ if (slVer === void 0 || keyModVersion <= slVer) {
4985
+ return null;
4986
+ }
4987
+ }
4988
+ const history = current.bufferHistory.get(key);
4989
+ if (history && slVer !== void 0) {
4990
+ const idx = current._findLastLE(history, slVer, "version");
4991
+ if (idx >= 0) {
4992
+ return history[idx].exists ? history[idx].value : null;
4993
+ }
4994
+ }
4995
+ if (current.parent) {
4996
+ slVer = current.snapshotLocalVersion;
4997
+ current = current.parent;
4998
+ } else {
4999
+ return current._diskRead(key, snapshotVersion);
4797
5000
  }
4798
5001
  }
4799
- if (this.parent) {
4800
- return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
4801
- } else {
4802
- return this._diskRead(key, snapshotVersion);
4803
- }
5002
+ return null;
4804
5003
  }
4805
5004
  commit(label) {
4806
5005
  const { created, updated, deleted } = this.getResultEntries();
@@ -4860,6 +5059,7 @@ var require_cjs = __commonJS({
4860
5059
  this.deletedValues.clear();
4861
5060
  this.originallyExisted.clear();
4862
5061
  this.keyVersions.clear();
5062
+ this.bufferHistory.clear();
4863
5063
  this.localVersion = 0;
4864
5064
  this.snapshotVersion = this.version;
4865
5065
  }
@@ -4900,32 +5100,22 @@ var require_cjs = __commonJS({
4900
5100
  };
4901
5101
  }
4902
5102
  }
4903
- const newLocalVersion = this.localVersion + 1;
4904
- for (const key of child.writeBuffer.keys()) {
4905
- this.writeBuffer.set(key, child.writeBuffer.get(key));
4906
- this.deleteBuffer.delete(key);
4907
- this.keyVersions.set(key, newLocalVersion);
4908
- if (child.createdKeys.has(key)) {
4909
- this.createdKeys.add(key);
4910
- }
5103
+ const mergeVersion = ++this.localVersion;
5104
+ for (const [key, value] of child.writeBuffer) {
5105
+ const wasCreated = child.createdKeys.has(key);
5106
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
5107
+ else this._bufferWrite(key, value, mergeVersion);
4911
5108
  }
4912
5109
  for (const key of child.deleteBuffer) {
4913
- this.deleteBuffer.add(key);
4914
- this.writeBuffer.delete(key);
4915
- this.createdKeys.delete(key);
4916
- this.keyVersions.set(key, newLocalVersion);
4917
5110
  const deletedValue = child.deletedValues.get(key);
4918
- if (deletedValue !== void 0) {
4919
- this.deletedValues.set(key, deletedValue);
4920
- }
4921
- if (child.originallyExisted.has(key)) {
5111
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
5112
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
4922
5113
  this.originallyExisted.add(key);
4923
5114
  }
5115
+ this._bufferDelete(key, mergeVersion);
4924
5116
  }
4925
- this.localVersion = newLocalVersion;
4926
5117
  this.root.activeTransactions.delete(child);
4927
5118
  } else {
4928
- const newVersion = this.version + 1;
4929
5119
  if (child !== this) {
4930
5120
  const modifiedKeys = /* @__PURE__ */ new Set([...child.writeBuffer.keys(), ...child.deleteBuffer]);
4931
5121
  for (const key of modifiedKeys) {
@@ -4943,50 +5133,57 @@ var require_cjs = __commonJS({
4943
5133
  };
4944
5134
  }
4945
5135
  }
5136
+ const lastModLocalVer = this.keyVersions.get(key);
5137
+ if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
5138
+ return {
5139
+ error: `Commit conflict: Key '${key}' was modified by a newer transaction in the same session (Local v${lastModLocalVer})`,
5140
+ conflict: {
5141
+ key,
5142
+ parent: this.read(key),
5143
+ child: child.read(key)
5144
+ }
5145
+ };
5146
+ }
4946
5147
  }
4947
- }
4948
- for (const [key, value] of child.writeBuffer) {
4949
- this.writeBuffer.set(key, value);
4950
- this.deleteBuffer.delete(key);
4951
- if (child.createdKeys.has(key)) {
4952
- this.createdKeys.add(key);
4953
- }
4954
- }
4955
- for (const key of child.deleteBuffer) {
4956
- this.deleteBuffer.add(key);
4957
- this.writeBuffer.delete(key);
4958
- this.createdKeys.delete(key);
4959
- const deletedValue = child.deletedValues.get(key);
4960
- if (deletedValue !== void 0) {
4961
- this.deletedValues.set(key, deletedValue);
5148
+ const mergeVersion = ++this.localVersion;
5149
+ for (const [key, value] of child.writeBuffer) {
5150
+ const wasCreated = child.createdKeys.has(key);
5151
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
5152
+ this.originallyExisted.add(key);
5153
+ }
5154
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
5155
+ else this._bufferWrite(key, value, mergeVersion);
4962
5156
  }
4963
- if (child.originallyExisted.has(key)) {
4964
- this.originallyExisted.add(key);
5157
+ for (const key of child.deleteBuffer) {
5158
+ const deletedValue = child.deletedValues.get(key);
5159
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
5160
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
5161
+ this.originallyExisted.add(key);
5162
+ }
5163
+ this._bufferDelete(key, mergeVersion);
4965
5164
  }
5165
+ this.root.activeTransactions.delete(child);
5166
+ } else {
5167
+ const newVersion = this.version + 1;
5168
+ for (const [key, value] of this.writeBuffer) this._diskWrite(key, value, newVersion);
5169
+ for (const key of this.deleteBuffer) this._diskDelete(key, newVersion);
5170
+ this.version = newVersion;
5171
+ this._cleanupDeletedCache();
4966
5172
  }
4967
- for (const [key, value] of child.writeBuffer) {
4968
- this._diskWrite(key, value, newVersion);
4969
- }
4970
- for (const key of child.deleteBuffer) {
4971
- this._diskDelete(key, newVersion);
4972
- }
4973
- this.version = newVersion;
4974
- this.root.activeTransactions.delete(child);
4975
- this._cleanupDeletedCache();
4976
5173
  }
4977
5174
  return null;
4978
5175
  }
4979
- // --- Internal IO Helpers (Root Only) ---
4980
5176
  _diskWrite(key, value, version) {
4981
5177
  const strategy = this.strategy;
4982
5178
  if (!strategy) throw new Error("Root Transaction missing strategy");
4983
- if (strategy.exists(key)) {
4984
- const currentVal = strategy.read(key);
5179
+ const rootAsAny = this.root;
5180
+ if (this._diskExists(key, version)) {
5181
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
4985
5182
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
4986
- this.deletedCache.get(key).push({
4987
- value: currentVal,
4988
- deletedAtVersion: version
4989
- });
5183
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
5184
+ rootAsAny.diskCache.set(key, value);
5185
+ } else {
5186
+ rootAsAny.diskCache.set(key, value);
4990
5187
  }
4991
5188
  strategy.write(key, value);
4992
5189
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -4997,36 +5194,44 @@ var require_cjs = __commonJS({
4997
5194
  if (!strategy) throw new Error("Root Transaction missing strategy");
4998
5195
  const versions = this.versionIndex.get(key);
4999
5196
  if (!versions) {
5000
- return strategy.exists(key) ? strategy.read(key) : null;
5197
+ const rootAsAny = this.root;
5198
+ if (this._diskExists(key, snapshotVersion)) {
5199
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
5200
+ rootAsAny.diskCache.set(key, val);
5201
+ return val;
5202
+ }
5203
+ return null;
5001
5204
  }
5002
5205
  let targetVerObj = null;
5003
5206
  let nextVerObj = null;
5004
- for (const v of versions) {
5005
- if (v.version <= snapshotVersion) {
5006
- targetVerObj = v;
5007
- } else {
5008
- nextVerObj = v;
5009
- break;
5010
- }
5011
- }
5207
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
5208
+ if (idx >= 0) targetVerObj = versions[idx];
5209
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
5012
5210
  if (!targetVerObj) {
5013
5211
  if (nextVerObj) {
5014
5212
  const cached2 = this.deletedCache.get(key);
5015
5213
  if (cached2) {
5016
- const match = cached2.find((c) => c.deletedAtVersion === nextVerObj.version);
5017
- if (match) return match.value;
5214
+ const cIdx = this._findExact(cached2, nextVerObj.version, "deletedAtVersion");
5215
+ if (cIdx >= 0) return cached2[cIdx].value;
5018
5216
  }
5019
5217
  }
5020
5218
  return null;
5021
5219
  }
5022
5220
  if (!targetVerObj.exists) return null;
5023
5221
  if (!nextVerObj) {
5024
- return strategy.read(key);
5222
+ if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
5223
+ if (this._diskExists(key, snapshotVersion)) {
5224
+ const rootAsAny = this.root;
5225
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
5226
+ rootAsAny.diskCache.set(key, val);
5227
+ return val;
5228
+ }
5229
+ return null;
5025
5230
  }
5026
5231
  const cached = this.deletedCache.get(key);
5027
5232
  if (cached) {
5028
- const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
5029
- if (match) return match.value;
5233
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
5234
+ if (cIdx >= 0) return cached[cIdx].value;
5030
5235
  }
5031
5236
  return null;
5032
5237
  }
@@ -5035,31 +5240,40 @@ var require_cjs = __commonJS({
5035
5240
  if (!strategy) throw new Error("Root Transaction missing strategy");
5036
5241
  const versions = this.versionIndex.get(key);
5037
5242
  if (!versions) {
5038
- return strategy.exists(key);
5243
+ const rootAsAny = this.root;
5244
+ if (rootAsAny.diskCache.has(key)) return rootAsAny.diskCache.get(key) !== null;
5245
+ const exists = strategy.exists(key);
5246
+ if (!exists) rootAsAny.diskCache.set(key, null);
5247
+ return exists;
5039
5248
  }
5040
5249
  let targetVerObj = null;
5041
- for (const v of versions) {
5042
- if (v.version <= snapshotVersion) {
5043
- targetVerObj = v;
5044
- } else {
5045
- break;
5250
+ let nextVerObj = null;
5251
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
5252
+ if (idx >= 0) targetVerObj = versions[idx];
5253
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
5254
+ if (!targetVerObj) {
5255
+ if (nextVerObj) {
5256
+ const cached = this.deletedCache.get(key);
5257
+ if (cached) {
5258
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
5259
+ if (cIdx >= 0) return true;
5260
+ }
5046
5261
  }
5262
+ return false;
5047
5263
  }
5048
- if (!targetVerObj) return strategy.exists(key);
5049
5264
  return targetVerObj.exists;
5050
5265
  }
5051
5266
  _diskDelete(key, snapshotVersion) {
5052
5267
  const strategy = this.strategy;
5053
5268
  if (!strategy) throw new Error("Root Transaction missing strategy");
5054
- if (strategy.exists(key)) {
5055
- const currentVal = strategy.read(key);
5269
+ const rootAsAny = this.root;
5270
+ if (this._diskExists(key, snapshotVersion)) {
5271
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : strategy.read(key);
5056
5272
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
5057
- this.deletedCache.get(key).push({
5058
- value: currentVal,
5059
- deletedAtVersion: snapshotVersion
5060
- });
5273
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
5274
+ strategy.delete(key);
5275
+ rootAsAny.diskCache.delete(key);
5061
5276
  }
5062
- strategy.delete(key);
5063
5277
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
5064
5278
  this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });
5065
5279
  }
@@ -5372,7 +5586,7 @@ var require_cjs = __commonJS({
5372
5586
  createNested() {
5373
5587
  if (this.committed) throw new Error("Transaction already committed");
5374
5588
  const childVersion = this.isRoot() ? this.version : this.snapshotVersion;
5375
- const child = new _AsyncMVCCTransaction2(void 0, this, childVersion);
5589
+ const child = new _AsyncMVCCTransaction2(void 0, void 0, this, childVersion);
5376
5590
  this.root.activeTransactions.add(child);
5377
5591
  return child;
5378
5592
  }
@@ -5380,32 +5594,77 @@ var require_cjs = __commonJS({
5380
5594
  if (this.committed) throw new Error("Transaction already committed");
5381
5595
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
5382
5596
  if (this.deleteBuffer.has(key)) return null;
5383
- return this.root._diskRead(key, this.snapshotVersion);
5597
+ if (this.parent) {
5598
+ return this.parent._readSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
5599
+ }
5600
+ return await this._diskRead(key, this.snapshotVersion);
5384
5601
  }
5385
5602
  async exists(key) {
5386
5603
  if (this.committed) throw new Error("Transaction already committed");
5387
5604
  if (this.deleteBuffer.has(key)) return false;
5388
5605
  if (this.writeBuffer.has(key)) return true;
5389
- return this.root._diskExists(key, this.snapshotVersion);
5606
+ if (this.parent) {
5607
+ return this.parent._existsSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
5608
+ }
5609
+ return await this._diskExists(key, this.snapshotVersion);
5390
5610
  }
5391
- async _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
5392
- if (this.writeBuffer.has(key)) {
5393
- const keyModVersion = this.keyVersions.get(key);
5394
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
5395
- return this.writeBuffer.get(key);
5611
+ async _existsSnapshot(key, snapshotVersion, snapshotLocalVersion) {
5612
+ let current = this;
5613
+ let slVer = snapshotLocalVersion;
5614
+ while (current) {
5615
+ if (current.writeBuffer.has(key)) {
5616
+ const keyModVersion = current.keyVersions.get(key);
5617
+ if (slVer === void 0 || keyModVersion <= slVer) return true;
5618
+ }
5619
+ if (current.deleteBuffer.has(key)) {
5620
+ const keyModVersion = current.keyVersions.get(key);
5621
+ if (slVer === void 0 || keyModVersion <= slVer) return false;
5622
+ }
5623
+ const history = current.bufferHistory.get(key);
5624
+ if (history && slVer !== void 0) {
5625
+ const idx = current._findLastLE(history, slVer, "version");
5626
+ if (idx >= 0) return history[idx].exists;
5627
+ }
5628
+ if (current.parent) {
5629
+ slVer = current.snapshotLocalVersion;
5630
+ current = current.parent;
5631
+ } else {
5632
+ return await current._diskExists(key, snapshotVersion);
5396
5633
  }
5397
5634
  }
5398
- if (this.deleteBuffer.has(key)) {
5399
- const keyModVersion = this.keyVersions.get(key);
5400
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
5401
- return null;
5635
+ return false;
5636
+ }
5637
+ async _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
5638
+ let current = this;
5639
+ let slVer = snapshotLocalVersion;
5640
+ while (current) {
5641
+ if (current.writeBuffer.has(key)) {
5642
+ const keyModVersion = current.keyVersions.get(key);
5643
+ if (slVer === void 0 || keyModVersion <= slVer) {
5644
+ return current.writeBuffer.get(key);
5645
+ }
5646
+ }
5647
+ if (current.deleteBuffer.has(key)) {
5648
+ const keyModVersion = current.keyVersions.get(key);
5649
+ if (slVer === void 0 || keyModVersion <= slVer) {
5650
+ return null;
5651
+ }
5652
+ }
5653
+ const history = current.bufferHistory.get(key);
5654
+ if (history && slVer !== void 0) {
5655
+ const idx = current._findLastLE(history, slVer, "version");
5656
+ if (idx >= 0) {
5657
+ return history[idx].exists ? history[idx].value : null;
5658
+ }
5659
+ }
5660
+ if (current.parent) {
5661
+ slVer = current.snapshotLocalVersion;
5662
+ current = current.parent;
5663
+ } else {
5664
+ return await current._diskRead(key, snapshotVersion);
5402
5665
  }
5403
5666
  }
5404
- if (this.parent) {
5405
- return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
5406
- } else {
5407
- return this._diskRead(key, snapshotVersion);
5408
- }
5667
+ return null;
5409
5668
  }
5410
5669
  async commit(label) {
5411
5670
  const { created, updated, deleted } = this.getResultEntries();
@@ -5465,6 +5724,7 @@ var require_cjs = __commonJS({
5465
5724
  this.deletedValues.clear();
5466
5725
  this.originallyExisted.clear();
5467
5726
  this.keyVersions.clear();
5727
+ this.bufferHistory.clear();
5468
5728
  this.localVersion = 0;
5469
5729
  this.snapshotVersion = this.version;
5470
5730
  }
@@ -5506,33 +5766,23 @@ var require_cjs = __commonJS({
5506
5766
  };
5507
5767
  }
5508
5768
  }
5509
- const newLocalVersion = this.localVersion + 1;
5510
- for (const key of child.writeBuffer.keys()) {
5511
- this.writeBuffer.set(key, child.writeBuffer.get(key));
5512
- this.deleteBuffer.delete(key);
5513
- this.keyVersions.set(key, newLocalVersion);
5514
- if (child.createdKeys.has(key)) {
5515
- this.createdKeys.add(key);
5516
- }
5769
+ const mergeVersion = ++this.localVersion;
5770
+ for (const [key, value] of child.writeBuffer) {
5771
+ const wasCreated = child.createdKeys.has(key);
5772
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
5773
+ else this._bufferWrite(key, value, mergeVersion);
5517
5774
  }
5518
5775
  for (const key of child.deleteBuffer) {
5519
- this.deleteBuffer.add(key);
5520
- this.writeBuffer.delete(key);
5521
- this.createdKeys.delete(key);
5522
- this.keyVersions.set(key, newLocalVersion);
5523
5776
  const deletedValue = child.deletedValues.get(key);
5524
- if (deletedValue !== void 0) {
5525
- this.deletedValues.set(key, deletedValue);
5526
- }
5527
- if (child.originallyExisted.has(key)) {
5777
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
5778
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
5528
5779
  this.originallyExisted.add(key);
5529
5780
  }
5781
+ this._bufferDelete(key, mergeVersion);
5530
5782
  }
5531
- this.localVersion = newLocalVersion;
5532
5783
  this.root.activeTransactions.delete(child);
5533
5784
  return null;
5534
5785
  } else {
5535
- const newVersion = this.version + 1;
5536
5786
  if (child !== this) {
5537
5787
  const modifiedKeys = /* @__PURE__ */ new Set([...child.writeBuffer.keys(), ...child.deleteBuffer]);
5538
5788
  for (const key of modifiedKeys) {
@@ -5550,51 +5800,58 @@ var require_cjs = __commonJS({
5550
5800
  };
5551
5801
  }
5552
5802
  }
5803
+ const lastModLocalVer = this.keyVersions.get(key);
5804
+ if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
5805
+ return {
5806
+ error: `Commit conflict: Key '${key}' was modified by a newer transaction in the same session (Local v${lastModLocalVer})`,
5807
+ conflict: {
5808
+ key,
5809
+ parent: await this.read(key),
5810
+ child: await child.read(key)
5811
+ }
5812
+ };
5813
+ }
5553
5814
  }
5554
- }
5555
- for (const [key, value] of child.writeBuffer) {
5556
- this.writeBuffer.set(key, value);
5557
- this.deleteBuffer.delete(key);
5558
- if (child.createdKeys.has(key)) {
5559
- this.createdKeys.add(key);
5560
- }
5561
- }
5562
- for (const key of child.deleteBuffer) {
5563
- this.deleteBuffer.add(key);
5564
- this.writeBuffer.delete(key);
5565
- this.createdKeys.delete(key);
5566
- const deletedValue = child.deletedValues.get(key);
5567
- if (deletedValue !== void 0) {
5568
- this.deletedValues.set(key, deletedValue);
5815
+ const mergeVersion = ++this.localVersion;
5816
+ for (const [key, value] of child.writeBuffer) {
5817
+ const wasCreated = child.createdKeys.has(key);
5818
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
5819
+ this.originallyExisted.add(key);
5820
+ }
5821
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
5822
+ else this._bufferWrite(key, value, mergeVersion);
5569
5823
  }
5570
- if (child.originallyExisted.has(key)) {
5571
- this.originallyExisted.add(key);
5824
+ for (const key of child.deleteBuffer) {
5825
+ const deletedValue = child.deletedValues.get(key);
5826
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
5827
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
5828
+ this.originallyExisted.add(key);
5829
+ }
5830
+ this._bufferDelete(key, mergeVersion);
5572
5831
  }
5832
+ this.root.activeTransactions.delete(child);
5833
+ } else {
5834
+ const newVersion = this.version + 1;
5835
+ for (const [key, value] of this.writeBuffer) await this._diskWrite(key, value, newVersion);
5836
+ for (const key of this.deleteBuffer) await this._diskDelete(key, newVersion);
5837
+ this.version = newVersion;
5838
+ this._cleanupDeletedCache();
5573
5839
  }
5574
- for (const [key, value] of child.writeBuffer) {
5575
- await this._diskWrite(key, value, newVersion);
5576
- }
5577
- for (const key of child.deleteBuffer) {
5578
- await this._diskDelete(key, newVersion);
5579
- }
5580
- this.version = newVersion;
5581
- this.root.activeTransactions.delete(child);
5582
- this._cleanupDeletedCache();
5583
5840
  return null;
5584
5841
  }
5585
5842
  });
5586
5843
  }
5587
- // --- Internal IO Helpers (Root Only) ---
5588
5844
  async _diskWrite(key, value, version) {
5589
5845
  const strategy = this.strategy;
5590
5846
  if (!strategy) throw new Error("Root Transaction missing strategy");
5591
- if (await strategy.exists(key)) {
5592
- const currentVal = await strategy.read(key);
5847
+ const rootAsAny = this.root;
5848
+ if (await this._diskExists(key, version)) {
5849
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
5593
5850
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
5594
- this.deletedCache.get(key).push({
5595
- value: currentVal,
5596
- deletedAtVersion: version
5597
- });
5851
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
5852
+ rootAsAny.diskCache.set(key, value);
5853
+ } else {
5854
+ rootAsAny.diskCache.set(key, value);
5598
5855
  }
5599
5856
  await strategy.write(key, value);
5600
5857
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -5605,36 +5862,44 @@ var require_cjs = __commonJS({
5605
5862
  if (!strategy) throw new Error("Root Transaction missing strategy");
5606
5863
  const versions = this.versionIndex.get(key);
5607
5864
  if (!versions) {
5608
- return await strategy.exists(key) ? strategy.read(key) : null;
5865
+ const rootAsAny = this.root;
5866
+ if (await this._diskExists(key, snapshotVersion)) {
5867
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
5868
+ rootAsAny.diskCache.set(key, val);
5869
+ return val;
5870
+ }
5871
+ return null;
5609
5872
  }
5610
5873
  let targetVerObj = null;
5611
5874
  let nextVerObj = null;
5612
- for (const v of versions) {
5613
- if (v.version <= snapshotVersion) {
5614
- targetVerObj = v;
5615
- } else {
5616
- nextVerObj = v;
5617
- break;
5618
- }
5619
- }
5875
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
5876
+ if (idx >= 0) targetVerObj = versions[idx];
5877
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
5620
5878
  if (!targetVerObj) {
5621
5879
  if (nextVerObj) {
5622
5880
  const cached2 = this.deletedCache.get(key);
5623
5881
  if (cached2) {
5624
- const match = cached2.find((c) => c.deletedAtVersion === nextVerObj.version);
5625
- if (match) return match.value;
5882
+ const cIdx = this._findExact(cached2, nextVerObj.version, "deletedAtVersion");
5883
+ if (cIdx >= 0) return cached2[cIdx].value;
5626
5884
  }
5627
5885
  }
5628
5886
  return null;
5629
5887
  }
5630
5888
  if (!targetVerObj.exists) return null;
5631
5889
  if (!nextVerObj) {
5632
- return strategy.read(key);
5890
+ if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
5891
+ if (await this._diskExists(key, snapshotVersion)) {
5892
+ const rootAsAny = this.root;
5893
+ const val = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
5894
+ rootAsAny.diskCache.set(key, val);
5895
+ return val;
5896
+ }
5897
+ return null;
5633
5898
  }
5634
5899
  const cached = this.deletedCache.get(key);
5635
5900
  if (cached) {
5636
- const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
5637
- if (match) return match.value;
5901
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
5902
+ if (cIdx >= 0) return cached[cIdx].value;
5638
5903
  }
5639
5904
  return null;
5640
5905
  }
@@ -5643,31 +5908,40 @@ var require_cjs = __commonJS({
5643
5908
  if (!strategy) throw new Error("Root Transaction missing strategy");
5644
5909
  const versions = this.versionIndex.get(key);
5645
5910
  if (!versions) {
5646
- return strategy.exists(key);
5911
+ const rootAsAny = this.root;
5912
+ if (rootAsAny.diskCache.has(key)) return rootAsAny.diskCache.get(key) !== null;
5913
+ const exists = await strategy.exists(key);
5914
+ if (!exists) rootAsAny.diskCache.set(key, null);
5915
+ return exists;
5647
5916
  }
5648
5917
  let targetVerObj = null;
5649
- for (const v of versions) {
5650
- if (v.version <= snapshotVersion) {
5651
- targetVerObj = v;
5652
- } else {
5653
- break;
5918
+ let nextVerObj = null;
5919
+ const idx = this._findLastLE(versions, snapshotVersion, "version");
5920
+ if (idx >= 0) targetVerObj = versions[idx];
5921
+ if (idx + 1 < versions.length) nextVerObj = versions[idx + 1];
5922
+ if (!targetVerObj) {
5923
+ if (nextVerObj) {
5924
+ const cached = this.deletedCache.get(key);
5925
+ if (cached) {
5926
+ const cIdx = this._findExact(cached, nextVerObj.version, "deletedAtVersion");
5927
+ if (cIdx >= 0) return true;
5928
+ }
5654
5929
  }
5930
+ return false;
5655
5931
  }
5656
- if (!targetVerObj) return strategy.exists(key);
5657
5932
  return targetVerObj.exists;
5658
5933
  }
5659
5934
  async _diskDelete(key, snapshotVersion) {
5660
5935
  const strategy = this.strategy;
5661
5936
  if (!strategy) throw new Error("Root Transaction missing strategy");
5662
- if (await strategy.exists(key)) {
5663
- const currentVal = await strategy.read(key);
5937
+ const rootAsAny = this.root;
5938
+ if (await this._diskExists(key, snapshotVersion)) {
5939
+ const currentVal = rootAsAny.diskCache.has(key) ? rootAsAny.diskCache.get(key) : await strategy.read(key);
5664
5940
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
5665
- this.deletedCache.get(key).push({
5666
- value: currentVal,
5667
- deletedAtVersion: snapshotVersion
5668
- });
5941
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
5942
+ await strategy.delete(key);
5943
+ rootAsAny.diskCache.delete(key);
5669
5944
  }
5670
- await strategy.delete(key);
5671
5945
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
5672
5946
  this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });
5673
5947
  }
@@ -7537,9 +7811,8 @@ var require_cjs = __commonJS({
7537
7811
  }
7538
7812
  };
7539
7813
  var import_node_fs2 = __toESM2(require("node:fs"));
7540
- var PageMVCCStrategy = class extends AsyncMVCCStrategy2 {
7814
+ var PageMVCCStrategy = class {
7541
7815
  constructor(fileHandle, pageSize, cacheCapacity) {
7542
- super();
7543
7816
  this.fileHandle = fileHandle;
7544
7817
  this.pageSize = pageSize;
7545
7818
  this.cache = new LRUMap2(cacheCapacity);
@@ -8336,7 +8609,6 @@ var require_cjs = __commonJS({
8336
8609
  if (!btx) return;
8337
8610
  const result = await btx.commit();
8338
8611
  if (result.success) {
8339
- await this.bptree.init();
8340
8612
  for (const entry of result.deleted) {
8341
8613
  await this.strategy.delete(entry.key);
8342
8614
  }
@@ -9813,6 +10085,7 @@ var DocumentDataplyAPI = class extends import_dataply3.DataplyAPI {
9813
10085
  return 0;
9814
10086
  }
9815
10087
  const fieldTxMap = {};
10088
+ const fieldMap = /* @__PURE__ */ new Map();
9816
10089
  for (const field of backfillTargets) {
9817
10090
  const tree = this.trees.get(field);
9818
10091
  if (tree && field !== "_id") {
@@ -9838,16 +10111,35 @@ var DocumentDataplyAPI = class extends import_dataply3.DataplyAPI {
9838
10111
  }
9839
10112
  const v = flatDoc[field];
9840
10113
  const btx = fieldTxMap[field];
9841
- await btx.insert(k, { k, v });
10114
+ const entry = { k, v };
10115
+ await btx.insert(k, entry);
10116
+ if (!fieldMap.has(btx)) {
10117
+ fieldMap.set(btx, []);
10118
+ }
10119
+ fieldMap.get(btx).push(entry);
9842
10120
  }
9843
10121
  backfilledCount++;
9844
10122
  }
9845
- const commits = Object.values(fieldTxMap).map((btx) => btx.commit());
9846
- await Promise.all(commits).catch(async (err) => {
9847
- const rollbacks = Object.values(fieldTxMap).map((btx) => btx.rollback());
9848
- await Promise.all(rollbacks);
10123
+ const btxs = Object.values(fieldTxMap);
10124
+ const success = [];
10125
+ try {
10126
+ for (const btx of btxs) {
10127
+ await btx.commit();
10128
+ success.push(btx);
10129
+ }
10130
+ } catch (err) {
10131
+ for (const btx of btxs) {
10132
+ await btx.rollback();
10133
+ }
10134
+ for (const btx of success) {
10135
+ const entries = fieldMap.get(btx);
10136
+ if (!entries) continue;
10137
+ for (const entry of entries) {
10138
+ await btx.delete(entry.k, entry);
10139
+ }
10140
+ }
9849
10141
  throw err;
9850
- });
10142
+ }
9851
10143
  this.pendingBackfillFields = [];
9852
10144
  return backfilledCount;
9853
10145
  }, tx);