dataply 0.0.21 → 0.0.22-alpha.0

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 +1375 -1308
  2. package/package.json +3 -3
package/dist/cjs/index.js CHANGED
@@ -137,6 +137,7 @@ var MVCCTransaction = class {
137
137
  // delete 시 삭제 전 값 저장
138
138
  originallyExisted;
139
139
  // 트랜잭션 시작 시점에 디스크에 존재했던 키 (deleted 결과 필터링용)
140
+ bufferHistory = /* @__PURE__ */ new Map();
140
141
  // Nested Transaction Properties
141
142
  parent;
142
143
  localVersion;
@@ -191,26 +192,45 @@ var MVCCTransaction = class {
191
192
  return false;
192
193
  }
193
194
  // --- Internal buffer manipulation helpers ---
194
- _bufferCreate(key, value) {
195
- this.localVersion++;
195
+ _recordHistory(key) {
196
+ const existsInWriteBuffer = this.writeBuffer.has(key);
197
+ const existsInDeleteBuffer = this.deleteBuffer.has(key);
198
+ const currentVer = this.keyVersions.get(key);
199
+ if (currentVer !== void 0) {
200
+ if (!this.bufferHistory.has(key)) this.bufferHistory.set(key, []);
201
+ this.bufferHistory.get(key).push({
202
+ value: existsInWriteBuffer ? this.writeBuffer.get(key) : this.deletedValues.get(key) ?? null,
203
+ exists: existsInWriteBuffer || !existsInDeleteBuffer,
204
+ version: currentVer
205
+ });
206
+ }
207
+ }
208
+ _bufferCreate(key, value, version) {
209
+ if (version === void 0) this.localVersion++;
210
+ const targetVersion = version ?? this.localVersion;
211
+ this._recordHistory(key);
196
212
  this.writeBuffer.set(key, value);
197
213
  this.createdKeys.add(key);
198
214
  this.deleteBuffer.delete(key);
199
215
  this.originallyExisted.delete(key);
200
- this.keyVersions.set(key, this.localVersion);
216
+ this.keyVersions.set(key, targetVersion);
201
217
  }
202
- _bufferWrite(key, value) {
203
- this.localVersion++;
218
+ _bufferWrite(key, value, version) {
219
+ if (version === void 0) this.localVersion++;
220
+ const targetVersion = version ?? this.localVersion;
221
+ this._recordHistory(key);
204
222
  this.writeBuffer.set(key, value);
205
223
  this.deleteBuffer.delete(key);
206
- this.keyVersions.set(key, this.localVersion);
224
+ this.keyVersions.set(key, targetVersion);
207
225
  }
208
- _bufferDelete(key) {
209
- this.localVersion++;
226
+ _bufferDelete(key, version) {
227
+ if (version === void 0) this.localVersion++;
228
+ const targetVersion = version ?? this.localVersion;
229
+ this._recordHistory(key);
210
230
  this.deleteBuffer.add(key);
211
231
  this.writeBuffer.delete(key);
212
232
  this.createdKeys.delete(key);
213
- this.keyVersions.set(key, this.localVersion);
233
+ this.keyVersions.set(key, targetVersion);
214
234
  }
215
235
  /**
216
236
  * Returns the entries that will be created, updated, and deleted by this transaction.
@@ -287,7 +307,9 @@ var MVCCTransaction = class {
287
307
  break;
288
308
  }
289
309
  }
290
- if (latestInSnapshotIdx > 0) {
310
+ if (latestInSnapshotIdx === versions.length - 1) {
311
+ this.versionIndex.delete(key);
312
+ } else if (latestInSnapshotIdx > 0) {
291
313
  versions.splice(0, latestInSnapshotIdx);
292
314
  }
293
315
  }
@@ -344,27 +366,68 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
344
366
  if (this.committed) throw new Error("Transaction already committed");
345
367
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
346
368
  if (this.deleteBuffer.has(key)) return null;
347
- return this.root._diskRead(key, this.snapshotVersion);
369
+ if (this.parent) {
370
+ return this.parent._readSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
371
+ }
372
+ return this._diskRead(key, this.snapshotVersion);
348
373
  }
349
374
  exists(key) {
350
375
  if (this.committed) throw new Error("Transaction already committed");
351
376
  if (this.deleteBuffer.has(key)) return false;
352
377
  if (this.writeBuffer.has(key)) return true;
353
- return this.root._diskExists(key, this.snapshotVersion);
378
+ if (this.parent) {
379
+ return this.parent._existsSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
380
+ }
381
+ return this._diskExists(key, this.snapshotVersion);
382
+ }
383
+ _existsSnapshot(key, snapshotVersion, snapshotLocalVersion) {
384
+ if (this.writeBuffer.has(key)) {
385
+ const keyModVersion = this.keyVersions.get(key);
386
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
387
+ return true;
388
+ }
389
+ }
390
+ if (this.deleteBuffer.has(key)) {
391
+ const keyModVersion = this.keyVersions.get(key);
392
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
393
+ return false;
394
+ }
395
+ }
396
+ const history = this.bufferHistory.get(key);
397
+ if (history && snapshotLocalVersion !== void 0) {
398
+ for (let i = history.length - 1; i >= 0; i--) {
399
+ if (history[i].version <= snapshotLocalVersion) {
400
+ return history[i].exists;
401
+ }
402
+ }
403
+ }
404
+ if (this.parent) {
405
+ return this.parent._existsSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
406
+ } else {
407
+ return this._diskExists(key, snapshotVersion);
408
+ }
354
409
  }
355
410
  _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
356
411
  if (this.writeBuffer.has(key)) {
357
412
  const keyModVersion = this.keyVersions.get(key);
358
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
413
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
359
414
  return this.writeBuffer.get(key);
360
415
  }
361
416
  }
362
417
  if (this.deleteBuffer.has(key)) {
363
418
  const keyModVersion = this.keyVersions.get(key);
364
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
419
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
365
420
  return null;
366
421
  }
367
422
  }
423
+ const history = this.bufferHistory.get(key);
424
+ if (history && snapshotLocalVersion !== void 0) {
425
+ for (let i = history.length - 1; i >= 0; i--) {
426
+ if (history[i].version <= snapshotLocalVersion) {
427
+ return history[i].exists ? history[i].value : null;
428
+ }
429
+ }
430
+ }
368
431
  if (this.parent) {
369
432
  return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
370
433
  } else {
@@ -374,54 +437,22 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
374
437
  commit(label) {
375
438
  const { created, updated, deleted } = this.getResultEntries();
376
439
  if (this.committed) {
377
- return {
378
- label,
379
- success: false,
380
- error: "Transaction already committed",
381
- conflict: void 0,
382
- created,
383
- updated,
384
- deleted
385
- };
440
+ return { label, success: false, error: "Transaction already committed", conflict: void 0, created, updated, deleted };
386
441
  }
387
442
  if (this.hasCommittedAncestor()) {
388
- return {
389
- label,
390
- success: false,
391
- error: "Ancestor transaction already committed",
392
- conflict: void 0,
393
- created,
394
- updated,
395
- deleted
396
- };
443
+ return { label, success: false, error: "Ancestor transaction already committed", conflict: void 0, created, updated, deleted };
397
444
  }
398
445
  if (this.parent) {
399
446
  const failure = this.parent._merge(this);
400
447
  if (failure) {
401
- return {
402
- label,
403
- success: false,
404
- error: failure.error,
405
- conflict: failure.conflict,
406
- created,
407
- updated,
408
- deleted
409
- };
448
+ return { label, success: false, error: failure.error, conflict: failure.conflict, created, updated, deleted };
410
449
  }
411
450
  this.committed = true;
412
451
  } else {
413
452
  if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
414
453
  const failure = this._merge(this);
415
454
  if (failure) {
416
- return {
417
- label,
418
- success: false,
419
- error: failure.error,
420
- conflict: failure.conflict,
421
- created: [],
422
- updated: [],
423
- deleted: []
424
- };
455
+ return { label, success: false, error: failure.error, conflict: failure.conflict, created: [], updated: [], deleted: [] };
425
456
  }
426
457
  this.writeBuffer.clear();
427
458
  this.deleteBuffer.clear();
@@ -429,17 +460,12 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
429
460
  this.deletedValues.clear();
430
461
  this.originallyExisted.clear();
431
462
  this.keyVersions.clear();
463
+ this.bufferHistory.clear();
432
464
  this.localVersion = 0;
433
465
  this.snapshotVersion = this.version;
434
466
  }
435
467
  }
436
- return {
437
- label,
438
- success: true,
439
- created,
440
- updated,
441
- deleted
442
- };
468
+ return { label, success: true, created, updated, deleted };
443
469
  }
444
470
  _merge(child) {
445
471
  if (this.parent) {
@@ -448,11 +474,7 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
448
474
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
449
475
  return {
450
476
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
451
- conflict: {
452
- key,
453
- parent: this.read(key),
454
- child: child.read(key)
455
- }
477
+ conflict: { key, parent: this.read(key), child: child.read(key) }
456
478
  };
457
479
  }
458
480
  }
@@ -461,40 +483,26 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
461
483
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
462
484
  return {
463
485
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
464
- conflict: {
465
- key,
466
- parent: this.read(key),
467
- child: child.read(key)
468
- }
486
+ conflict: { key, parent: this.read(key), child: child.read(key) }
469
487
  };
470
488
  }
471
489
  }
472
- const newLocalVersion = this.localVersion + 1;
473
- for (const key of child.writeBuffer.keys()) {
474
- this.writeBuffer.set(key, child.writeBuffer.get(key));
475
- this.deleteBuffer.delete(key);
476
- this.keyVersions.set(key, newLocalVersion);
477
- if (child.createdKeys.has(key)) {
478
- this.createdKeys.add(key);
479
- }
490
+ const mergeVersion = ++this.localVersion;
491
+ for (const [key, value] of child.writeBuffer) {
492
+ const wasCreated = child.createdKeys.has(key);
493
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
494
+ else this._bufferWrite(key, value, mergeVersion);
480
495
  }
481
496
  for (const key of child.deleteBuffer) {
482
- this.deleteBuffer.add(key);
483
- this.writeBuffer.delete(key);
484
- this.createdKeys.delete(key);
485
- this.keyVersions.set(key, newLocalVersion);
486
497
  const deletedValue = child.deletedValues.get(key);
487
- if (deletedValue !== void 0) {
488
- this.deletedValues.set(key, deletedValue);
489
- }
490
- if (child.originallyExisted.has(key)) {
498
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
499
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
491
500
  this.originallyExisted.add(key);
492
501
  }
502
+ this._bufferDelete(key, mergeVersion);
493
503
  }
494
- this.localVersion = newLocalVersion;
495
504
  this.root.activeTransactions.delete(child);
496
505
  } else {
497
- const newVersion = this.version + 1;
498
506
  if (child !== this) {
499
507
  const modifiedKeys = /* @__PURE__ */ new Set([...child.writeBuffer.keys(), ...child.deleteBuffer]);
500
508
  for (const key of modifiedKeys) {
@@ -504,58 +512,53 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
504
512
  if (lastVer > child.snapshotVersion) {
505
513
  return {
506
514
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (v${lastVer})`,
507
- conflict: {
508
- key,
509
- parent: this.read(key),
510
- child: child.read(key)
511
- }
515
+ conflict: { key, parent: this.read(key), child: child.read(key) }
512
516
  };
513
517
  }
514
518
  }
519
+ const lastModLocalVer = this.keyVersions.get(key);
520
+ if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
521
+ return {
522
+ error: `Commit conflict: Key '${key}' was modified by a newer transaction in the same session (Local v${lastModLocalVer})`,
523
+ conflict: { key, parent: this.read(key), child: child.read(key) }
524
+ };
525
+ }
515
526
  }
516
- }
517
- for (const [key, value] of child.writeBuffer) {
518
- this.writeBuffer.set(key, value);
519
- this.deleteBuffer.delete(key);
520
- if (child.createdKeys.has(key)) {
521
- this.createdKeys.add(key);
522
- }
523
- }
524
- for (const key of child.deleteBuffer) {
525
- this.deleteBuffer.add(key);
526
- this.writeBuffer.delete(key);
527
- this.createdKeys.delete(key);
528
- const deletedValue = child.deletedValues.get(key);
529
- if (deletedValue !== void 0) {
530
- this.deletedValues.set(key, deletedValue);
527
+ const mergeVersion = ++this.localVersion;
528
+ for (const [key, value] of child.writeBuffer) {
529
+ const wasCreated = child.createdKeys.has(key);
530
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
531
+ this.originallyExisted.add(key);
532
+ }
533
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
534
+ else this._bufferWrite(key, value, mergeVersion);
531
535
  }
532
- if (child.originallyExisted.has(key)) {
533
- this.originallyExisted.add(key);
536
+ for (const key of child.deleteBuffer) {
537
+ const deletedValue = child.deletedValues.get(key);
538
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
539
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
540
+ this.originallyExisted.add(key);
541
+ }
542
+ this._bufferDelete(key, mergeVersion);
534
543
  }
544
+ this.root.activeTransactions.delete(child);
545
+ } else {
546
+ const newVersion = this.version + 1;
547
+ for (const [key, value] of this.writeBuffer) this._diskWrite(key, value, newVersion);
548
+ for (const key of this.deleteBuffer) this._diskDelete(key, newVersion);
549
+ this.version = newVersion;
550
+ this._cleanupDeletedCache();
535
551
  }
536
- for (const [key, value] of child.writeBuffer) {
537
- this._diskWrite(key, value, newVersion);
538
- }
539
- for (const key of child.deleteBuffer) {
540
- this._diskDelete(key, newVersion);
541
- }
542
- this.version = newVersion;
543
- this.root.activeTransactions.delete(child);
544
- this._cleanupDeletedCache();
545
552
  }
546
553
  return null;
547
554
  }
548
- // --- Internal IO Helpers (Root Only) ---
549
555
  _diskWrite(key, value, version) {
550
556
  const strategy = this.strategy;
551
557
  if (!strategy) throw new Error("Root Transaction missing strategy");
552
558
  if (strategy.exists(key)) {
553
559
  const currentVal = strategy.read(key);
554
560
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
555
- this.deletedCache.get(key).push({
556
- value: currentVal,
557
- deletedAtVersion: version
558
- });
561
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
559
562
  }
560
563
  strategy.write(key, value);
561
564
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -571,9 +574,8 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
571
574
  let targetVerObj = null;
572
575
  let nextVerObj = null;
573
576
  for (const v of versions) {
574
- if (v.version <= snapshotVersion) {
575
- targetVerObj = v;
576
- } else {
577
+ if (v.version <= snapshotVersion) targetVerObj = v;
578
+ else {
577
579
  nextVerObj = v;
578
580
  break;
579
581
  }
@@ -590,6 +592,7 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
590
592
  }
591
593
  if (!targetVerObj.exists) return null;
592
594
  if (!nextVerObj) {
595
+ if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
593
596
  return strategy.read(key);
594
597
  }
595
598
  const cached = this.deletedCache.get(key);
@@ -607,14 +610,24 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
607
610
  return strategy.exists(key);
608
611
  }
609
612
  let targetVerObj = null;
613
+ let nextVerObj = null;
610
614
  for (const v of versions) {
611
- if (v.version <= snapshotVersion) {
612
- targetVerObj = v;
613
- } else {
615
+ if (v.version <= snapshotVersion) targetVerObj = v;
616
+ else {
617
+ nextVerObj = v;
614
618
  break;
615
619
  }
616
620
  }
617
- if (!targetVerObj) return strategy.exists(key);
621
+ if (!targetVerObj) {
622
+ if (nextVerObj) {
623
+ const cached = this.deletedCache.get(key);
624
+ if (cached) {
625
+ const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
626
+ if (match) return true;
627
+ }
628
+ }
629
+ return false;
630
+ }
618
631
  return targetVerObj.exists;
619
632
  }
620
633
  _diskDelete(key, snapshotVersion) {
@@ -623,12 +636,9 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
623
636
  if (strategy.exists(key)) {
624
637
  const currentVal = strategy.read(key);
625
638
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
626
- this.deletedCache.get(key).push({
627
- value: currentVal,
628
- deletedAtVersion: snapshotVersion
629
- });
639
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
640
+ strategy.delete(key);
630
641
  }
631
- strategy.delete(key);
632
642
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
633
643
  this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });
634
644
  }
@@ -949,84 +959,93 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
949
959
  if (this.committed) throw new Error("Transaction already committed");
950
960
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
951
961
  if (this.deleteBuffer.has(key)) return null;
952
- return this.root._diskRead(key, this.snapshotVersion);
962
+ if (this.parent) {
963
+ return this.parent._readSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
964
+ }
965
+ return await this._diskRead(key, this.snapshotVersion);
953
966
  }
954
967
  async exists(key) {
955
968
  if (this.committed) throw new Error("Transaction already committed");
956
969
  if (this.deleteBuffer.has(key)) return false;
957
970
  if (this.writeBuffer.has(key)) return true;
958
- return this.root._diskExists(key, this.snapshotVersion);
971
+ if (this.parent) {
972
+ return this.parent._existsSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
973
+ }
974
+ return await this._diskExists(key, this.snapshotVersion);
975
+ }
976
+ async _existsSnapshot(key, snapshotVersion, snapshotLocalVersion) {
977
+ if (this.writeBuffer.has(key)) {
978
+ const keyModVersion = this.keyVersions.get(key);
979
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
980
+ return true;
981
+ }
982
+ }
983
+ if (this.deleteBuffer.has(key)) {
984
+ const keyModVersion = this.keyVersions.get(key);
985
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
986
+ return false;
987
+ }
988
+ }
989
+ const history = this.bufferHistory.get(key);
990
+ if (history && snapshotLocalVersion !== void 0) {
991
+ for (let i = history.length - 1; i >= 0; i--) {
992
+ if (history[i].version <= snapshotLocalVersion) {
993
+ return history[i].exists;
994
+ }
995
+ }
996
+ }
997
+ if (this.parent) {
998
+ return this.parent._existsSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
999
+ } else {
1000
+ return await this._diskExists(key, snapshotVersion);
1001
+ }
959
1002
  }
960
1003
  async _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
961
1004
  if (this.writeBuffer.has(key)) {
962
1005
  const keyModVersion = this.keyVersions.get(key);
963
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
1006
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
964
1007
  return this.writeBuffer.get(key);
965
1008
  }
966
1009
  }
967
1010
  if (this.deleteBuffer.has(key)) {
968
1011
  const keyModVersion = this.keyVersions.get(key);
969
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
1012
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
970
1013
  return null;
971
1014
  }
972
1015
  }
1016
+ const history = this.bufferHistory.get(key);
1017
+ if (history && snapshotLocalVersion !== void 0) {
1018
+ for (let i = history.length - 1; i >= 0; i--) {
1019
+ if (history[i].version <= snapshotLocalVersion) {
1020
+ return history[i].exists ? history[i].value : null;
1021
+ }
1022
+ }
1023
+ }
973
1024
  if (this.parent) {
974
1025
  return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
975
1026
  } else {
976
- return this._diskRead(key, snapshotVersion);
1027
+ return await this._diskRead(key, snapshotVersion);
977
1028
  }
978
1029
  }
979
1030
  async commit(label) {
980
1031
  const { created, updated, deleted } = this.getResultEntries();
981
1032
  if (this.committed) {
982
- return {
983
- label,
984
- success: false,
985
- error: "Transaction already committed",
986
- conflict: void 0,
987
- created,
988
- updated,
989
- deleted
990
- };
1033
+ return { label, success: false, error: "Transaction already committed", conflict: void 0, created, updated, deleted };
991
1034
  }
992
1035
  if (this.hasCommittedAncestor()) {
993
- return {
994
- label,
995
- success: false,
996
- error: "Ancestor transaction already committed",
997
- conflict: void 0,
998
- created,
999
- updated,
1000
- deleted
1001
- };
1036
+ return { label, success: false, error: "Ancestor transaction already committed", conflict: void 0, created, updated, deleted };
1002
1037
  }
1003
1038
  if (this.parent) {
1004
1039
  const failure = await this.parent._merge(this);
1005
1040
  if (failure) {
1006
- return {
1007
- label,
1008
- success: false,
1009
- error: failure.error,
1010
- conflict: failure.conflict,
1011
- created,
1012
- updated,
1013
- deleted
1014
- };
1041
+ return { label, success: false, error: failure.error, conflict: failure.conflict, created, updated, deleted };
1015
1042
  }
1016
1043
  this.committed = true;
1017
1044
  } else {
1018
1045
  if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
1019
1046
  const failure = await this._merge(this);
1020
1047
  if (failure) {
1021
- return {
1022
- label,
1023
- success: false,
1024
- error: failure.error,
1025
- conflict: failure.conflict,
1026
- created: [],
1027
- updated: [],
1028
- deleted: []
1029
- };
1048
+ return { label, success: false, error: failure.error, conflict: failure.conflict, created: [], updated: [], deleted: [] };
1030
1049
  }
1031
1050
  this.writeBuffer.clear();
1032
1051
  this.deleteBuffer.clear();
@@ -1034,17 +1053,12 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1034
1053
  this.deletedValues.clear();
1035
1054
  this.originallyExisted.clear();
1036
1055
  this.keyVersions.clear();
1056
+ this.bufferHistory.clear();
1037
1057
  this.localVersion = 0;
1038
1058
  this.snapshotVersion = this.version;
1039
1059
  }
1040
1060
  }
1041
- return {
1042
- label,
1043
- success: true,
1044
- created,
1045
- updated,
1046
- deleted
1047
- };
1061
+ return { label, success: true, created, updated, deleted };
1048
1062
  }
1049
1063
  async _merge(child) {
1050
1064
  return this.writeLock(async () => {
@@ -1054,11 +1068,7 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1054
1068
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
1055
1069
  return {
1056
1070
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
1057
- conflict: {
1058
- key,
1059
- parent: await this.read(key),
1060
- child: await child.read(key)
1061
- }
1071
+ conflict: { key, parent: await this.read(key), child: await child.read(key) }
1062
1072
  };
1063
1073
  }
1064
1074
  }
@@ -1067,41 +1077,27 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1067
1077
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
1068
1078
  return {
1069
1079
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
1070
- conflict: {
1071
- key,
1072
- parent: await this.read(key),
1073
- child: await child.read(key)
1074
- }
1080
+ conflict: { key, parent: await this.read(key), child: await child.read(key) }
1075
1081
  };
1076
1082
  }
1077
1083
  }
1078
- const newLocalVersion = this.localVersion + 1;
1079
- for (const key of child.writeBuffer.keys()) {
1080
- this.writeBuffer.set(key, child.writeBuffer.get(key));
1081
- this.deleteBuffer.delete(key);
1082
- this.keyVersions.set(key, newLocalVersion);
1083
- if (child.createdKeys.has(key)) {
1084
- this.createdKeys.add(key);
1085
- }
1084
+ const mergeVersion = ++this.localVersion;
1085
+ for (const [key, value] of child.writeBuffer) {
1086
+ const wasCreated = child.createdKeys.has(key);
1087
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
1088
+ else this._bufferWrite(key, value, mergeVersion);
1086
1089
  }
1087
1090
  for (const key of child.deleteBuffer) {
1088
- this.deleteBuffer.add(key);
1089
- this.writeBuffer.delete(key);
1090
- this.createdKeys.delete(key);
1091
- this.keyVersions.set(key, newLocalVersion);
1092
1091
  const deletedValue = child.deletedValues.get(key);
1093
- if (deletedValue !== void 0) {
1094
- this.deletedValues.set(key, deletedValue);
1095
- }
1096
- if (child.originallyExisted.has(key)) {
1092
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
1093
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
1097
1094
  this.originallyExisted.add(key);
1098
1095
  }
1096
+ this._bufferDelete(key, mergeVersion);
1099
1097
  }
1100
- this.localVersion = newLocalVersion;
1101
1098
  this.root.activeTransactions.delete(child);
1102
1099
  return null;
1103
1100
  } else {
1104
- const newVersion = this.version + 1;
1105
1101
  if (child !== this) {
1106
1102
  const modifiedKeys = /* @__PURE__ */ new Set([...child.writeBuffer.keys(), ...child.deleteBuffer]);
1107
1103
  for (const key of modifiedKeys) {
@@ -1111,59 +1107,54 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1111
1107
  if (lastVer > child.snapshotVersion) {
1112
1108
  return {
1113
1109
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (v${lastVer})`,
1114
- conflict: {
1115
- key,
1116
- parent: await this.read(key),
1117
- child: await child.read(key)
1118
- }
1110
+ conflict: { key, parent: await this.read(key), child: await child.read(key) }
1119
1111
  };
1120
1112
  }
1121
1113
  }
1114
+ const lastModLocalVer = this.keyVersions.get(key);
1115
+ if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
1116
+ return {
1117
+ error: `Commit conflict: Key '${key}' was modified by a newer transaction in the same session (Local v${lastModLocalVer})`,
1118
+ conflict: { key, parent: await this.read(key), child: await child.read(key) }
1119
+ };
1120
+ }
1122
1121
  }
1123
- }
1124
- for (const [key, value] of child.writeBuffer) {
1125
- this.writeBuffer.set(key, value);
1126
- this.deleteBuffer.delete(key);
1127
- if (child.createdKeys.has(key)) {
1128
- this.createdKeys.add(key);
1129
- }
1130
- }
1131
- for (const key of child.deleteBuffer) {
1132
- this.deleteBuffer.add(key);
1133
- this.writeBuffer.delete(key);
1134
- this.createdKeys.delete(key);
1135
- const deletedValue = child.deletedValues.get(key);
1136
- if (deletedValue !== void 0) {
1137
- this.deletedValues.set(key, deletedValue);
1122
+ const mergeVersion = ++this.localVersion;
1123
+ for (const [key, value] of child.writeBuffer) {
1124
+ const wasCreated = child.createdKeys.has(key);
1125
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
1126
+ this.originallyExisted.add(key);
1127
+ }
1128
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
1129
+ else this._bufferWrite(key, value, mergeVersion);
1138
1130
  }
1139
- if (child.originallyExisted.has(key)) {
1140
- this.originallyExisted.add(key);
1131
+ for (const key of child.deleteBuffer) {
1132
+ const deletedValue = child.deletedValues.get(key);
1133
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
1134
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
1135
+ this.originallyExisted.add(key);
1136
+ }
1137
+ this._bufferDelete(key, mergeVersion);
1141
1138
  }
1139
+ this.root.activeTransactions.delete(child);
1140
+ } else {
1141
+ const newVersion = this.version + 1;
1142
+ for (const [key, value] of this.writeBuffer) await this._diskWrite(key, value, newVersion);
1143
+ for (const key of this.deleteBuffer) await this._diskDelete(key, newVersion);
1144
+ this.version = newVersion;
1145
+ this._cleanupDeletedCache();
1142
1146
  }
1143
- for (const [key, value] of child.writeBuffer) {
1144
- await this._diskWrite(key, value, newVersion);
1145
- }
1146
- for (const key of child.deleteBuffer) {
1147
- await this._diskDelete(key, newVersion);
1148
- }
1149
- this.version = newVersion;
1150
- this.root.activeTransactions.delete(child);
1151
- this._cleanupDeletedCache();
1152
1147
  return null;
1153
1148
  }
1154
1149
  });
1155
1150
  }
1156
- // --- Internal IO Helpers (Root Only) ---
1157
1151
  async _diskWrite(key, value, version) {
1158
1152
  const strategy = this.strategy;
1159
1153
  if (!strategy) throw new Error("Root Transaction missing strategy");
1160
1154
  if (await strategy.exists(key)) {
1161
1155
  const currentVal = await strategy.read(key);
1162
1156
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
1163
- this.deletedCache.get(key).push({
1164
- value: currentVal,
1165
- deletedAtVersion: version
1166
- });
1157
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
1167
1158
  }
1168
1159
  await strategy.write(key, value);
1169
1160
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -1174,14 +1165,13 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1174
1165
  if (!strategy) throw new Error("Root Transaction missing strategy");
1175
1166
  const versions = this.versionIndex.get(key);
1176
1167
  if (!versions) {
1177
- return await strategy.exists(key) ? strategy.read(key) : null;
1168
+ return await strategy.exists(key) ? await strategy.read(key) : null;
1178
1169
  }
1179
1170
  let targetVerObj = null;
1180
1171
  let nextVerObj = null;
1181
1172
  for (const v of versions) {
1182
- if (v.version <= snapshotVersion) {
1183
- targetVerObj = v;
1184
- } else {
1173
+ if (v.version <= snapshotVersion) targetVerObj = v;
1174
+ else {
1185
1175
  nextVerObj = v;
1186
1176
  break;
1187
1177
  }
@@ -1198,6 +1188,7 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1198
1188
  }
1199
1189
  if (!targetVerObj.exists) return null;
1200
1190
  if (!nextVerObj) {
1191
+ if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
1201
1192
  return strategy.read(key);
1202
1193
  }
1203
1194
  const cached = this.deletedCache.get(key);
@@ -1212,17 +1203,27 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1212
1203
  if (!strategy) throw new Error("Root Transaction missing strategy");
1213
1204
  const versions = this.versionIndex.get(key);
1214
1205
  if (!versions) {
1215
- return strategy.exists(key);
1206
+ return await strategy.exists(key);
1216
1207
  }
1217
1208
  let targetVerObj = null;
1209
+ let nextVerObj = null;
1218
1210
  for (const v of versions) {
1219
- if (v.version <= snapshotVersion) {
1220
- targetVerObj = v;
1221
- } else {
1211
+ if (v.version <= snapshotVersion) targetVerObj = v;
1212
+ else {
1213
+ nextVerObj = v;
1222
1214
  break;
1223
1215
  }
1224
1216
  }
1225
- if (!targetVerObj) return strategy.exists(key);
1217
+ if (!targetVerObj) {
1218
+ if (nextVerObj) {
1219
+ const cached = this.deletedCache.get(key);
1220
+ if (cached) {
1221
+ const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
1222
+ if (match) return true;
1223
+ }
1224
+ }
1225
+ return false;
1226
+ }
1226
1227
  return targetVerObj.exists;
1227
1228
  }
1228
1229
  async _diskDelete(key, snapshotVersion) {
@@ -1231,12 +1232,9 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1231
1232
  if (await strategy.exists(key)) {
1232
1233
  const currentVal = await strategy.read(key);
1233
1234
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
1234
- this.deletedCache.get(key).push({
1235
- value: currentVal,
1236
- deletedAtVersion: snapshotVersion
1237
- });
1235
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
1236
+ await strategy.delete(key);
1238
1237
  }
1239
- await strategy.delete(key);
1240
1238
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
1241
1239
  this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });
1242
1240
  }
@@ -1574,6 +1572,8 @@ var BPTreeTransaction = class _BPTreeTransaction {
1574
1572
  option;
1575
1573
  order;
1576
1574
  rootId;
1575
+ isInitialized = false;
1576
+ isDestroyed = false;
1577
1577
  verifierMap = {
1578
1578
  gt: (nv, v) => this.comparator.isHigher(nv, v),
1579
1579
  gte: (nv, v) => this.comparator.isHigher(nv, v) || this.comparator.isSame(nv, v),
@@ -1838,13 +1838,26 @@ var BPTreeTransaction = class _BPTreeTransaction {
1838
1838
  getResultEntries() {
1839
1839
  return this.mvcc.getResultEntries();
1840
1840
  }
1841
+ _clearCache() {
1842
+ this._cachedRegexp.clear();
1843
+ this.nodes.clear();
1844
+ }
1841
1845
  /**
1842
1846
  * Clears all cached nodes.
1843
1847
  * This method is useful for freeing up memory when the tree is no longer needed.
1844
1848
  */
1845
1849
  clear() {
1846
- this._cachedRegexp.clear();
1847
- this.nodes.clear();
1850
+ if (this.rootTx !== this) {
1851
+ throw new Error("Cannot call clear on a nested transaction");
1852
+ }
1853
+ this._clearInternal();
1854
+ }
1855
+ _clearInternal() {
1856
+ if (this.isDestroyed) {
1857
+ throw new Error("Transaction already destroyed");
1858
+ }
1859
+ this._clearCache();
1860
+ this.isDestroyed = true;
1848
1861
  }
1849
1862
  _binarySearchValues(values, target, usePrimary = false, upperBound = false) {
1850
1863
  let low = 0;
@@ -2148,28 +2161,46 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2148
2161
  }
2149
2162
  }
2150
2163
  init() {
2151
- this.clear();
2152
- const head = this._readHead();
2153
- if (head === null) {
2154
- this.order = this.strategy.order;
2155
- const root = this._createNode(true, [], []);
2156
- this._writeHead({
2157
- root: root.id,
2158
- order: this.order,
2159
- data: this.strategy.head.data
2160
- });
2161
- } else {
2162
- const { root, order } = head;
2163
- this.strategy.head = head;
2164
- this.order = order;
2165
- this._writeHead({
2166
- root,
2167
- order: this.order,
2168
- data: this.strategy.head.data
2169
- });
2164
+ if (this.rootTx !== this) {
2165
+ throw new Error("Cannot call init on a nested transaction");
2166
+ }
2167
+ this._initInternal();
2168
+ }
2169
+ _initInternal() {
2170
+ if (this.isInitialized) {
2171
+ throw new Error("Transaction already initialized");
2172
+ }
2173
+ if (this.isDestroyed) {
2174
+ throw new Error("Transaction already destroyed");
2170
2175
  }
2171
- if (this.order < 3) {
2172
- throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
2176
+ this.isInitialized = true;
2177
+ try {
2178
+ this._clearCache();
2179
+ const head = this._readHead();
2180
+ if (head === null) {
2181
+ this.order = this.strategy.order;
2182
+ const root = this._createNode(true, [], []);
2183
+ this._writeHead({
2184
+ root: root.id,
2185
+ order: this.order,
2186
+ data: this.strategy.head.data
2187
+ });
2188
+ } else {
2189
+ const { root, order } = head;
2190
+ this.strategy.head = head;
2191
+ this.order = order;
2192
+ this._writeHead({
2193
+ root,
2194
+ order: this.order,
2195
+ data: this.strategy.head.data
2196
+ });
2197
+ }
2198
+ if (this.order < 3) {
2199
+ throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
2200
+ }
2201
+ } catch (e) {
2202
+ this.isInitialized = false;
2203
+ throw e;
2173
2204
  }
2174
2205
  }
2175
2206
  exists(key, value) {
@@ -2547,9 +2578,12 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2547
2578
  commit(label) {
2548
2579
  let result = this.mvcc.commit(label);
2549
2580
  if (result.success) {
2550
- result = this.mvccRoot.commit(label);
2551
- if (result.success && this.rootTx !== this) {
2552
- this.rootTx.rootId = this.rootId;
2581
+ const isRootTx = this.rootTx !== this;
2582
+ if (isRootTx) {
2583
+ result = this.rootTx.commit(label);
2584
+ if (result.success) {
2585
+ this.rootTx.rootId = this.rootId;
2586
+ }
2553
2587
  }
2554
2588
  if (result.success) {
2555
2589
  for (const r of result.created) {
@@ -2628,7 +2662,7 @@ var BPTreeSync = class extends BPTreeSyncTransaction {
2628
2662
  this.comparator,
2629
2663
  this.option
2630
2664
  );
2631
- tx.init();
2665
+ tx._initInternal();
2632
2666
  return tx;
2633
2667
  }
2634
2668
  insert(key, value) {
@@ -2638,7 +2672,6 @@ var BPTreeSync = class extends BPTreeSyncTransaction {
2638
2672
  if (!result.success) {
2639
2673
  throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
2640
2674
  }
2641
- this.rootId = tx.getRootId();
2642
2675
  }
2643
2676
  delete(key, value) {
2644
2677
  const tx = this.createTransaction();
@@ -2647,319 +2680,603 @@ var BPTreeSync = class extends BPTreeSyncTransaction {
2647
2680
  if (!result.success) {
2648
2681
  throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
2649
2682
  }
2650
- this.rootId = tx.getRootId();
2651
2683
  }
2652
2684
  };
2653
- var BPTreeAsyncTransaction = class extends BPTreeTransaction {
2654
- constructor(rootTx, mvccRoot, mvcc, strategy, comparator, option) {
2655
- super(
2656
- rootTx,
2657
- mvccRoot,
2658
- mvcc,
2659
- strategy,
2660
- comparator,
2661
- option
2662
- );
2685
+ var Ryoiki2 = class _Ryoiki2 {
2686
+ readings;
2687
+ writings;
2688
+ readQueue;
2689
+ writeQueue;
2690
+ static async CatchError(promise) {
2691
+ return await promise.then((v) => [void 0, v]).catch((err) => [err]);
2663
2692
  }
2664
- async getNode(id) {
2665
- if (this.nodes.has(id)) {
2666
- return this.nodes.get(id);
2693
+ static IsRangeOverlap(a, b) {
2694
+ const [start1, end1] = a;
2695
+ const [start2, end2] = b;
2696
+ if (end1 <= start2 || end2 <= start1) {
2697
+ return false;
2667
2698
  }
2668
- return await this.mvcc.read(id);
2699
+ return true;
2700
+ }
2701
+ static ERR_ALREADY_EXISTS(lockId) {
2702
+ return new Error(`The '${lockId}' task already existing in queue or running.`);
2703
+ }
2704
+ static ERR_NOT_EXISTS(lockId) {
2705
+ return new Error(`The '${lockId}' task not existing in task queue.`);
2706
+ }
2707
+ static ERR_TIMEOUT(lockId, timeout) {
2708
+ return new Error(`The task with ID '${lockId}' failed to acquire the lock within the timeout(${timeout}ms).`);
2669
2709
  }
2670
2710
  /**
2671
- * Create a new node with a unique ID.
2711
+ * Constructs a new instance of the Ryoiki class.
2672
2712
  */
2673
- async _createNode(leaf, keys, values, parent = null, next = null, prev = null) {
2674
- const id = await this.strategy.id(leaf);
2675
- const node = {
2676
- id,
2677
- keys,
2678
- values,
2679
- leaf,
2680
- parent,
2681
- next,
2682
- prev
2683
- };
2684
- await this.mvcc.create(id, node);
2685
- this.nodes.set(id, node);
2686
- return node;
2713
+ constructor() {
2714
+ this.readings = /* @__PURE__ */ new Map();
2715
+ this.writings = /* @__PURE__ */ new Map();
2716
+ this.readQueue = /* @__PURE__ */ new Map();
2717
+ this.writeQueue = /* @__PURE__ */ new Map();
2687
2718
  }
2688
- async _updateNode(node) {
2689
- await this.mvcc.write(node.id, node);
2690
- this.nodes.set(node.id, node);
2719
+ /**
2720
+ * Creates a range based on a start value and length.
2721
+ * @param start - The starting value of the range.
2722
+ * @param length - The length of the range.
2723
+ * @returns A range tuple [start, start + length].
2724
+ */
2725
+ range(start, length) {
2726
+ return [start, start + length];
2691
2727
  }
2692
- async _deleteNode(node) {
2693
- await this.mvcc.delete(node.id);
2694
- this.nodes.delete(node.id);
2728
+ rangeOverlapping(tasks, range) {
2729
+ return Array.from(tasks.values()).some((t) => _Ryoiki2.IsRangeOverlap(t.range, range));
2695
2730
  }
2696
- async _readHead() {
2697
- if (this.nodes.has("__HEAD__")) {
2698
- return this.nodes.get("__HEAD__") ?? null;
2699
- }
2700
- const head = await this.mvcc.read("__HEAD__");
2701
- return head ?? null;
2702
- }
2703
- async _writeHead(head) {
2704
- if (!await this.mvcc.exists("__HEAD__")) {
2705
- await this.mvcc.create("__HEAD__", head);
2706
- } else {
2707
- await this.mvcc.write("__HEAD__", head);
2708
- }
2709
- this.nodes.set("__HEAD__", head);
2710
- this.rootId = head.root;
2731
+ isSameRange(a, b) {
2732
+ const [a1, a2] = a;
2733
+ const [b1, b2] = b;
2734
+ return a1 === b1 && a2 === b2;
2711
2735
  }
2712
- async _insertAtLeaf(node, key, value) {
2713
- if (node.values.length) {
2714
- for (let i = 0, len = node.values.length; i < len; i++) {
2715
- const nValue = node.values[i];
2716
- if (this.comparator.isSame(value, nValue)) {
2717
- const keys = node.keys[i];
2718
- if (keys.includes(key)) {
2719
- break;
2720
- }
2721
- keys.push(key);
2722
- await this._updateNode(node);
2723
- return;
2724
- } else if (this.comparator.isLower(value, nValue)) {
2725
- node.values.splice(i, 0, value);
2726
- node.keys.splice(i, 0, [key]);
2727
- await this._updateNode(node);
2728
- return;
2729
- } else if (i + 1 === node.values.length) {
2730
- node.values.push(value);
2731
- node.keys.push([key]);
2732
- await this._updateNode(node);
2733
- return;
2734
- }
2736
+ fetchUnitAndRun(queue, workspaces) {
2737
+ for (const [id, unit] of queue) {
2738
+ if (!unit.condition()) {
2739
+ continue;
2735
2740
  }
2736
- } else {
2737
- node.values = [value];
2738
- node.keys = [[key]];
2739
- await this._updateNode(node);
2740
- return;
2741
+ this._alloc(queue, workspaces, id);
2741
2742
  }
2742
2743
  }
2743
- async _insertInParent(node, value, pointer) {
2744
- if (this.rootId === node.id) {
2745
- const root = await this._createNode(false, [node.id, pointer.id], [value]);
2746
- this.rootId = root.id;
2747
- node.parent = root.id;
2748
- pointer.parent = root.id;
2749
- if (pointer.leaf) {
2750
- node.next = pointer.id;
2751
- pointer.prev = node.id;
2752
- }
2753
- await this._writeHead({
2754
- root: root.id,
2755
- order: this.order,
2756
- data: this.strategy.head.data
2757
- });
2758
- await this._updateNode(node);
2759
- await this._updateNode(pointer);
2760
- return;
2761
- }
2762
- const parentNode = await this.getNode(node.parent);
2763
- const nodeIndex = parentNode.keys.indexOf(node.id);
2764
- if (nodeIndex === -1) {
2765
- throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
2766
- }
2767
- parentNode.values.splice(nodeIndex, 0, value);
2768
- parentNode.keys.splice(nodeIndex + 1, 0, pointer.id);
2769
- pointer.parent = parentNode.id;
2770
- if (pointer.leaf) {
2771
- const leftSibling = node;
2772
- const oldNextId = leftSibling.next;
2773
- pointer.prev = leftSibling.id;
2774
- pointer.next = oldNextId;
2775
- leftSibling.next = pointer.id;
2776
- await this._updateNode(leftSibling);
2777
- if (oldNextId) {
2778
- const oldNext = await this.getNode(oldNextId);
2779
- oldNext.prev = pointer.id;
2780
- await this._updateNode(oldNext);
2781
- }
2782
- }
2783
- await this._updateNode(parentNode);
2784
- await this._updateNode(pointer);
2785
- if (parentNode.keys.length > this.order) {
2786
- const parentPointer = await this._createNode(false, [], []);
2787
- parentPointer.parent = parentNode.parent;
2788
- const mid = Math.ceil(this.order / 2) - 1;
2789
- parentPointer.values = parentNode.values.slice(mid + 1);
2790
- parentPointer.keys = parentNode.keys.slice(mid + 1);
2791
- const midValue = parentNode.values[mid];
2792
- parentNode.values = parentNode.values.slice(0, mid);
2793
- parentNode.keys = parentNode.keys.slice(0, mid + 1);
2794
- for (const k of parentNode.keys) {
2795
- const n = await this.getNode(k);
2796
- n.parent = parentNode.id;
2797
- await this._updateNode(n);
2798
- }
2799
- for (const k of parentPointer.keys) {
2800
- const n = await this.getNode(k);
2801
- n.parent = parentPointer.id;
2802
- await this._updateNode(n);
2744
+ _handleOverload(args, handlers, argPatterns) {
2745
+ for (const [key, pattern] of Object.entries(argPatterns)) {
2746
+ if (this._matchArgs(args, pattern)) {
2747
+ return handlers[key](...args);
2803
2748
  }
2804
- await this._updateNode(parentNode);
2805
- await this._insertInParent(parentNode, midValue, parentPointer);
2806
2749
  }
2750
+ throw new Error("Invalid arguments");
2807
2751
  }
2808
- async insertableNode(value) {
2809
- let node = await this.getNode(this.rootId);
2810
- while (!node.leaf) {
2811
- const { index } = this._binarySearchValues(node.values, value, false, true);
2812
- node = await this.getNode(node.keys[index]);
2813
- }
2814
- return node;
2752
+ _matchArgs(args, pattern) {
2753
+ return args.every((arg, index) => {
2754
+ const expectedType = pattern[index];
2755
+ if (expectedType === void 0) return typeof arg === "undefined";
2756
+ if (expectedType === Function) return typeof arg === "function";
2757
+ if (expectedType === Number) return typeof arg === "number";
2758
+ if (expectedType === Array) return Array.isArray(arg);
2759
+ return false;
2760
+ });
2815
2761
  }
2816
- async insertableNodeByPrimary(value) {
2817
- let node = await this.getNode(this.rootId);
2818
- while (!node.leaf) {
2819
- const { index } = this._binarySearchValues(node.values, value, true, false);
2820
- node = await this.getNode(node.keys[index]);
2821
- }
2822
- return node;
2762
+ _createRandomId() {
2763
+ const timestamp = Date.now().toString(36);
2764
+ const random = Math.random().toString(36).substring(2);
2765
+ return `${timestamp}${random}`;
2823
2766
  }
2824
- async insertableRightestNodeByPrimary(value) {
2825
- let node = await this.getNode(this.rootId);
2826
- while (!node.leaf) {
2827
- const { index } = this._binarySearchValues(node.values, value, true, true);
2828
- node = await this.getNode(node.keys[index]);
2767
+ _alloc(queue, workspaces, lockId) {
2768
+ const unit = queue.get(lockId);
2769
+ if (!unit) {
2770
+ throw _Ryoiki2.ERR_NOT_EXISTS(lockId);
2829
2771
  }
2830
- return node;
2772
+ workspaces.set(lockId, unit);
2773
+ queue.delete(lockId);
2774
+ unit.alloc();
2831
2775
  }
2832
- async insertableRightestEndNodeByPrimary(value) {
2833
- const node = await this.insertableRightestNodeByPrimary(value);
2834
- if (!node.next) {
2835
- return null;
2776
+ _free(workspaces, lockId) {
2777
+ const unit = workspaces.get(lockId);
2778
+ if (!unit) {
2779
+ throw _Ryoiki2.ERR_NOT_EXISTS(lockId);
2836
2780
  }
2837
- return await this.getNode(node.next);
2781
+ workspaces.delete(lockId);
2782
+ unit.free();
2838
2783
  }
2839
- async insertableEndNode(value, direction) {
2840
- const insertableNode = await this.insertableNode(value);
2841
- let key;
2842
- switch (direction) {
2843
- case -1:
2844
- key = "prev";
2845
- break;
2846
- case 1:
2847
- key = "next";
2784
+ _lock(queue, range, timeout, task, condition) {
2785
+ return new Promise((resolve, reject) => {
2786
+ let timeoutId = null;
2787
+ if (timeout >= 0) {
2788
+ timeoutId = setTimeout(() => {
2789
+ reject(_Ryoiki2.ERR_TIMEOUT(id, timeout));
2790
+ }, timeout);
2791
+ }
2792
+ const id = this._createRandomId();
2793
+ const alloc = async () => {
2794
+ if (timeoutId !== null) {
2795
+ clearTimeout(timeoutId);
2796
+ }
2797
+ const [err, v] = await _Ryoiki2.CatchError(task(id));
2798
+ if (err) reject(err);
2799
+ else resolve(v);
2800
+ };
2801
+ const fetch = () => {
2802
+ this.fetchUnitAndRun(this.readQueue, this.readings);
2803
+ this.fetchUnitAndRun(this.writeQueue, this.writings);
2804
+ };
2805
+ queue.set(id, { id, range, condition, alloc, free: fetch });
2806
+ fetch();
2807
+ });
2808
+ }
2809
+ _checkWorking(range, workspaces) {
2810
+ let isLocked = false;
2811
+ for (const lock of workspaces.values()) {
2812
+ if (_Ryoiki2.IsRangeOverlap(range, lock.range)) {
2813
+ isLocked = true;
2848
2814
  break;
2849
- default:
2850
- throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
2851
- }
2852
- const guessNode = insertableNode[key];
2853
- if (!guessNode) {
2854
- return null;
2815
+ }
2855
2816
  }
2856
- return await this.getNode(guessNode);
2817
+ return isLocked;
2857
2818
  }
2858
- async leftestNode() {
2859
- let node = await this.getNode(this.rootId);
2860
- if (node === null) {
2861
- debugger;
2862
- }
2863
- while (!node.leaf) {
2864
- const keys = node.keys;
2865
- node = await this.getNode(keys[0]);
2866
- }
2867
- return node;
2819
+ /**
2820
+ * Checks if there is any active read lock within the specified range.
2821
+ * @param range The range to check for active read locks.
2822
+ * @returns `true` if there is an active read lock within the range, `false` otherwise.
2823
+ */
2824
+ isReading(range) {
2825
+ return this._checkWorking(range, this.readings);
2868
2826
  }
2869
- async rightestNode() {
2870
- let node = await this.getNode(this.rootId);
2871
- while (!node.leaf) {
2872
- const keys = node.keys;
2873
- node = await this.getNode(keys[keys.length - 1]);
2874
- }
2875
- return node;
2827
+ /**
2828
+ * Checks if there is any active write lock within the specified range.
2829
+ * @param range The range to check for active write locks.
2830
+ * @returns `true` if there is an active write lock within the range, `false` otherwise.
2831
+ */
2832
+ isWriting(range) {
2833
+ return this._checkWorking(range, this.writings);
2876
2834
  }
2877
- async *getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
2878
- let node = startNode;
2879
- let done = false;
2880
- let hasMatched = false;
2881
- let nextNodePromise = null;
2882
- while (!done) {
2883
- if (endNode && node.id === endNode.id) {
2884
- done = true;
2885
- break;
2835
+ /**
2836
+ * Checks if a read lock can be acquired within the specified range.
2837
+ * @param range The range to check for read lock availability.
2838
+ * @returns `true` if a read lock can be acquired, `false` otherwise.
2839
+ */
2840
+ canRead(range) {
2841
+ const writing = this.isWriting(range);
2842
+ return !writing;
2843
+ }
2844
+ /**
2845
+ * Checks if a write lock can be acquired within the specified range.
2846
+ * @param range The range to check for write lock availability.
2847
+ * @returns `true` if a write lock can be acquired, `false` otherwise.
2848
+ */
2849
+ canWrite(range) {
2850
+ const reading = this.isReading(range);
2851
+ const writing = this.isWriting(range);
2852
+ return !reading && !writing;
2853
+ }
2854
+ /**
2855
+ * Internal implementation of the read lock. Handles both overloads.
2856
+ * @template T - The return type of the task.
2857
+ * @param arg0 - Either a range or a task callback.
2858
+ * If a range is provided, the task is the second argument.
2859
+ * @param arg1 - The task to execute, required if a range is provided.
2860
+ * @param arg2 - The timeout for acquiring the lock.
2861
+ * If the lock cannot be acquired within this period, an error will be thrown.
2862
+ * If this value is not provided, no timeout will be set.
2863
+ * @returns A promise resolving to the result of the task execution.
2864
+ */
2865
+ readLock(arg0, arg1, arg2) {
2866
+ const [range, task, timeout] = this._handleOverload(
2867
+ [arg0, arg1, arg2],
2868
+ {
2869
+ rangeTask: (range2, task2) => [range2, task2, -1],
2870
+ rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
2871
+ task: (task2) => [[-Infinity, Infinity], task2, -1],
2872
+ taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
2873
+ },
2874
+ {
2875
+ task: [Function],
2876
+ taskTimeout: [Function, Number],
2877
+ rangeTask: [Array, Function],
2878
+ rangeTaskTimeout: [Array, Function, Number]
2886
2879
  }
2887
- if (direction === 1) {
2888
- if (node.next && !done) {
2889
- nextNodePromise = this.getNode(node.next);
2890
- }
2891
- } else {
2892
- if (node.prev && !done) {
2893
- nextNodePromise = this.getNode(node.prev);
2894
- }
2880
+ );
2881
+ return this._lock(
2882
+ this.readQueue,
2883
+ range,
2884
+ timeout,
2885
+ task,
2886
+ () => !this.rangeOverlapping(this.writings, range)
2887
+ );
2888
+ }
2889
+ /**
2890
+ * Internal implementation of the write lock. Handles both overloads.
2891
+ * @template T - The return type of the task.
2892
+ * @param arg0 - Either a range or a task callback.
2893
+ * If a range is provided, the task is the second argument.
2894
+ * @param arg1 - The task to execute, required if a range is provided.
2895
+ * @param arg2 - The timeout for acquiring the lock.
2896
+ * If the lock cannot be acquired within this period, an error will be thrown.
2897
+ * If this value is not provided, no timeout will be set.
2898
+ * @returns A promise resolving to the result of the task execution.
2899
+ */
2900
+ writeLock(arg0, arg1, arg2) {
2901
+ const [range, task, timeout] = this._handleOverload(
2902
+ [arg0, arg1, arg2],
2903
+ {
2904
+ rangeTask: (range2, task2) => [range2, task2, -1],
2905
+ rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
2906
+ task: (task2) => [[-Infinity, Infinity], task2, -1],
2907
+ taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
2908
+ },
2909
+ {
2910
+ task: [Function],
2911
+ taskTimeout: [Function, Number],
2912
+ rangeTask: [Array, Function],
2913
+ rangeTaskTimeout: [Array, Function, Number]
2895
2914
  }
2896
- const len = node.values.length;
2897
- if (direction === 1) {
2898
- for (let i = 0; i < len; i++) {
2899
- const nValue = node.values[i];
2900
- const keys = node.keys[i];
2901
- if (comparator(nValue, value)) {
2902
- hasMatched = true;
2903
- for (let j = 0; j < keys.length; j++) {
2904
- yield [keys[j], nValue];
2905
- }
2906
- } else if (earlyTerminate && hasMatched) {
2907
- done = true;
2908
- break;
2909
- }
2910
- }
2911
- } else {
2912
- let i = len;
2913
- while (i--) {
2914
- const nValue = node.values[i];
2915
+ );
2916
+ return this._lock(
2917
+ this.writeQueue,
2918
+ range,
2919
+ timeout,
2920
+ task,
2921
+ () => {
2922
+ return !this.rangeOverlapping(this.writings, range) && !this.rangeOverlapping(this.readings, range);
2923
+ }
2924
+ );
2925
+ }
2926
+ /**
2927
+ * Releases a read lock by its lock ID.
2928
+ * @param lockId - The unique identifier for the lock to release.
2929
+ */
2930
+ readUnlock(lockId) {
2931
+ this._free(this.readings, lockId);
2932
+ }
2933
+ /**
2934
+ * Releases a write lock by its lock ID.
2935
+ * @param lockId - The unique identifier for the lock to release.
2936
+ */
2937
+ writeUnlock(lockId) {
2938
+ this._free(this.writings, lockId);
2939
+ }
2940
+ };
2941
+ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
2942
+ lock;
2943
+ constructor(rootTx, mvccRoot, mvcc, strategy, comparator, option) {
2944
+ super(
2945
+ rootTx,
2946
+ mvccRoot,
2947
+ mvcc,
2948
+ strategy,
2949
+ comparator,
2950
+ option
2951
+ );
2952
+ this.lock = new Ryoiki2();
2953
+ }
2954
+ async writeLock(id, fn) {
2955
+ let lockId;
2956
+ return this.lock.writeLock([id, id + 0.1], async (_lockId) => {
2957
+ lockId = _lockId;
2958
+ return fn();
2959
+ }).finally(() => {
2960
+ this.lock.writeUnlock(lockId);
2961
+ });
2962
+ }
2963
+ async getNode(id) {
2964
+ if (this.nodes.has(id)) {
2965
+ return this.nodes.get(id);
2966
+ }
2967
+ return await this.mvcc.read(id);
2968
+ }
2969
+ /**
2970
+ * Create a new node with a unique ID.
2971
+ */
2972
+ async _createNode(leaf, keys, values, parent = null, next = null, prev = null) {
2973
+ const id = await this.strategy.id(leaf);
2974
+ const node = {
2975
+ id,
2976
+ keys,
2977
+ values,
2978
+ leaf,
2979
+ parent,
2980
+ next,
2981
+ prev
2982
+ };
2983
+ await this.mvcc.create(id, node);
2984
+ this.nodes.set(id, node);
2985
+ return node;
2986
+ }
2987
+ async _updateNode(node) {
2988
+ await this.mvcc.write(node.id, node);
2989
+ this.nodes.set(node.id, node);
2990
+ }
2991
+ async _deleteNode(node) {
2992
+ await this.mvcc.delete(node.id);
2993
+ this.nodes.delete(node.id);
2994
+ }
2995
+ async _readHead() {
2996
+ if (this.nodes.has("__HEAD__")) {
2997
+ return this.nodes.get("__HEAD__") ?? null;
2998
+ }
2999
+ const head = await this.mvcc.read("__HEAD__");
3000
+ return head ?? null;
3001
+ }
3002
+ async _writeHead(head) {
3003
+ if (!await this.mvcc.exists("__HEAD__")) {
3004
+ await this.mvcc.create("__HEAD__", head);
3005
+ } else {
3006
+ await this.mvcc.write("__HEAD__", head);
3007
+ }
3008
+ this.nodes.set("__HEAD__", head);
3009
+ this.rootId = head.root;
3010
+ }
3011
+ async _insertAtLeaf(node, key, value) {
3012
+ if (node.values.length) {
3013
+ for (let i = 0, len = node.values.length; i < len; i++) {
3014
+ const nValue = node.values[i];
3015
+ if (this.comparator.isSame(value, nValue)) {
2915
3016
  const keys = node.keys[i];
2916
- if (comparator(nValue, value)) {
2917
- hasMatched = true;
2918
- let j = keys.length;
2919
- while (j--) {
2920
- yield [keys[j], nValue];
2921
- }
2922
- } else if (earlyTerminate && hasMatched) {
2923
- done = true;
3017
+ if (keys.includes(key)) {
2924
3018
  break;
2925
3019
  }
3020
+ keys.push(key);
3021
+ await this._updateNode(node);
3022
+ return;
3023
+ } else if (this.comparator.isLower(value, nValue)) {
3024
+ node.values.splice(i, 0, value);
3025
+ node.keys.splice(i, 0, [key]);
3026
+ await this._updateNode(node);
3027
+ return;
3028
+ } else if (i + 1 === node.values.length) {
3029
+ node.values.push(value);
3030
+ node.keys.push([key]);
3031
+ await this._updateNode(node);
3032
+ return;
2926
3033
  }
2927
3034
  }
2928
- if (done) {
2929
- if (nextNodePromise) await nextNodePromise;
2930
- break;
2931
- }
2932
- if (nextNodePromise) {
2933
- node = await nextNodePromise;
2934
- nextNodePromise = null;
2935
- } else {
2936
- done = true;
2937
- }
3035
+ } else {
3036
+ node.values = [value];
3037
+ node.keys = [[key]];
3038
+ await this._updateNode(node);
3039
+ return;
2938
3040
  }
2939
3041
  }
2940
- async init() {
2941
- this.clear();
2942
- const head = await this._readHead();
2943
- if (head === null) {
2944
- this.order = this.strategy.order;
2945
- const root = await this._createNode(true, [], []);
3042
+ async _insertInParent(node, value, pointer) {
3043
+ if (this.rootId === node.id) {
3044
+ const root = await this._createNode(false, [node.id, pointer.id], [value]);
3045
+ this.rootId = root.id;
3046
+ node.parent = root.id;
3047
+ pointer.parent = root.id;
3048
+ if (pointer.leaf) {
3049
+ node.next = pointer.id;
3050
+ pointer.prev = node.id;
3051
+ }
2946
3052
  await this._writeHead({
2947
3053
  root: root.id,
2948
3054
  order: this.order,
2949
3055
  data: this.strategy.head.data
2950
3056
  });
2951
- } else {
2952
- const { root, order } = head;
2953
- this.strategy.head = head;
2954
- this.order = order;
2955
- await this._writeHead({
2956
- root,
2957
- order: this.order,
2958
- data: this.strategy.head.data
2959
- });
3057
+ await this._updateNode(node);
3058
+ await this._updateNode(pointer);
3059
+ return;
3060
+ }
3061
+ const parentNode = await this.getNode(node.parent);
3062
+ const nodeIndex = parentNode.keys.indexOf(node.id);
3063
+ if (nodeIndex === -1) {
3064
+ throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
3065
+ }
3066
+ parentNode.values.splice(nodeIndex, 0, value);
3067
+ parentNode.keys.splice(nodeIndex + 1, 0, pointer.id);
3068
+ pointer.parent = parentNode.id;
3069
+ if (pointer.leaf) {
3070
+ const leftSibling = node;
3071
+ const oldNextId = leftSibling.next;
3072
+ pointer.prev = leftSibling.id;
3073
+ pointer.next = oldNextId;
3074
+ leftSibling.next = pointer.id;
3075
+ await this._updateNode(leftSibling);
3076
+ if (oldNextId) {
3077
+ const oldNext = await this.getNode(oldNextId);
3078
+ oldNext.prev = pointer.id;
3079
+ await this._updateNode(oldNext);
3080
+ }
3081
+ }
3082
+ await this._updateNode(parentNode);
3083
+ await this._updateNode(pointer);
3084
+ if (parentNode.keys.length > this.order) {
3085
+ const parentPointer = await this._createNode(false, [], []);
3086
+ parentPointer.parent = parentNode.parent;
3087
+ const mid = Math.ceil(this.order / 2) - 1;
3088
+ parentPointer.values = parentNode.values.slice(mid + 1);
3089
+ parentPointer.keys = parentNode.keys.slice(mid + 1);
3090
+ const midValue = parentNode.values[mid];
3091
+ parentNode.values = parentNode.values.slice(0, mid);
3092
+ parentNode.keys = parentNode.keys.slice(0, mid + 1);
3093
+ for (const k of parentNode.keys) {
3094
+ const n = await this.getNode(k);
3095
+ n.parent = parentNode.id;
3096
+ await this._updateNode(n);
3097
+ }
3098
+ for (const k of parentPointer.keys) {
3099
+ const n = await this.getNode(k);
3100
+ n.parent = parentPointer.id;
3101
+ await this._updateNode(n);
3102
+ }
3103
+ await this._updateNode(parentNode);
3104
+ await this._insertInParent(parentNode, midValue, parentPointer);
3105
+ }
3106
+ }
3107
+ async insertableNode(value) {
3108
+ let node = await this.getNode(this.rootId);
3109
+ while (!node.leaf) {
3110
+ const { index } = this._binarySearchValues(node.values, value, false, true);
3111
+ node = await this.getNode(node.keys[index]);
3112
+ }
3113
+ return node;
3114
+ }
3115
+ async insertableNodeByPrimary(value) {
3116
+ let node = await this.getNode(this.rootId);
3117
+ while (!node.leaf) {
3118
+ const { index } = this._binarySearchValues(node.values, value, true, false);
3119
+ node = await this.getNode(node.keys[index]);
3120
+ }
3121
+ return node;
3122
+ }
3123
+ async insertableRightestNodeByPrimary(value) {
3124
+ let node = await this.getNode(this.rootId);
3125
+ while (!node.leaf) {
3126
+ const { index } = this._binarySearchValues(node.values, value, true, true);
3127
+ node = await this.getNode(node.keys[index]);
3128
+ }
3129
+ return node;
3130
+ }
3131
+ async insertableRightestEndNodeByPrimary(value) {
3132
+ const node = await this.insertableRightestNodeByPrimary(value);
3133
+ if (!node.next) {
3134
+ return null;
3135
+ }
3136
+ return await this.getNode(node.next);
3137
+ }
3138
+ async insertableEndNode(value, direction) {
3139
+ const insertableNode = await this.insertableNode(value);
3140
+ let key;
3141
+ switch (direction) {
3142
+ case -1:
3143
+ key = "prev";
3144
+ break;
3145
+ case 1:
3146
+ key = "next";
3147
+ break;
3148
+ default:
3149
+ throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
3150
+ }
3151
+ const guessNode = insertableNode[key];
3152
+ if (!guessNode) {
3153
+ return null;
3154
+ }
3155
+ return await this.getNode(guessNode);
3156
+ }
3157
+ async leftestNode() {
3158
+ let node = await this.getNode(this.rootId);
3159
+ if (node === null) {
3160
+ debugger;
3161
+ }
3162
+ while (!node.leaf) {
3163
+ const keys = node.keys;
3164
+ node = await this.getNode(keys[0]);
3165
+ }
3166
+ return node;
3167
+ }
3168
+ async rightestNode() {
3169
+ let node = await this.getNode(this.rootId);
3170
+ while (!node.leaf) {
3171
+ const keys = node.keys;
3172
+ node = await this.getNode(keys[keys.length - 1]);
3173
+ }
3174
+ return node;
3175
+ }
3176
+ async *getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
3177
+ let node = startNode;
3178
+ let done = false;
3179
+ let hasMatched = false;
3180
+ let nextNodePromise = null;
3181
+ while (!done) {
3182
+ if (endNode && node.id === endNode.id) {
3183
+ done = true;
3184
+ break;
3185
+ }
3186
+ if (direction === 1) {
3187
+ if (node.next && !done) {
3188
+ nextNodePromise = this.getNode(node.next);
3189
+ }
3190
+ } else {
3191
+ if (node.prev && !done) {
3192
+ nextNodePromise = this.getNode(node.prev);
3193
+ }
3194
+ }
3195
+ const len = node.values.length;
3196
+ if (direction === 1) {
3197
+ for (let i = 0; i < len; i++) {
3198
+ const nValue = node.values[i];
3199
+ const keys = node.keys[i];
3200
+ if (comparator(nValue, value)) {
3201
+ hasMatched = true;
3202
+ for (let j = 0; j < keys.length; j++) {
3203
+ yield [keys[j], nValue];
3204
+ }
3205
+ } else if (earlyTerminate && hasMatched) {
3206
+ done = true;
3207
+ break;
3208
+ }
3209
+ }
3210
+ } else {
3211
+ let i = len;
3212
+ while (i--) {
3213
+ const nValue = node.values[i];
3214
+ const keys = node.keys[i];
3215
+ if (comparator(nValue, value)) {
3216
+ hasMatched = true;
3217
+ let j = keys.length;
3218
+ while (j--) {
3219
+ yield [keys[j], nValue];
3220
+ }
3221
+ } else if (earlyTerminate && hasMatched) {
3222
+ done = true;
3223
+ break;
3224
+ }
3225
+ }
3226
+ }
3227
+ if (done) {
3228
+ if (nextNodePromise) await nextNodePromise;
3229
+ break;
3230
+ }
3231
+ if (nextNodePromise) {
3232
+ node = await nextNodePromise;
3233
+ nextNodePromise = null;
3234
+ } else {
3235
+ done = true;
3236
+ }
3237
+ }
3238
+ }
3239
+ async init() {
3240
+ if (this.rootTx !== this) {
3241
+ throw new Error("Cannot call init on a nested transaction");
3242
+ }
3243
+ return await this._initInternal();
3244
+ }
3245
+ async _initInternal() {
3246
+ if (this.isInitialized) {
3247
+ throw new Error("Transaction already initialized");
3248
+ }
3249
+ if (this.isDestroyed) {
3250
+ throw new Error("Transaction already destroyed");
2960
3251
  }
2961
- if (this.order < 3) {
2962
- throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
3252
+ this.isInitialized = true;
3253
+ try {
3254
+ this._clearCache();
3255
+ const head = await this._readHead();
3256
+ if (head === null) {
3257
+ this.order = this.strategy.order;
3258
+ const root = await this._createNode(true, [], []);
3259
+ await this._writeHead({
3260
+ root: root.id,
3261
+ order: this.order,
3262
+ data: this.strategy.head.data
3263
+ });
3264
+ } else {
3265
+ const { root, order } = head;
3266
+ this.strategy.head = head;
3267
+ this.order = order;
3268
+ await this._writeHead({
3269
+ root,
3270
+ order: this.order,
3271
+ data: this.strategy.head.data
3272
+ });
3273
+ }
3274
+ if (this.order < 3) {
3275
+ throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
3276
+ }
3277
+ } catch (e) {
3278
+ this.isInitialized = false;
3279
+ throw e;
2963
3280
  }
2964
3281
  }
2965
3282
  async exists(key, value) {
@@ -3073,24 +3390,26 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3073
3390
  return map;
3074
3391
  }
3075
3392
  async insert(key, value) {
3076
- const before = await this.insertableNode(value);
3077
- await this._insertAtLeaf(before, key, value);
3078
- if (before.values.length === this.order) {
3079
- const after = await this._createNode(
3080
- true,
3081
- [],
3082
- [],
3083
- before.parent,
3084
- null,
3085
- null
3086
- );
3087
- const mid = Math.ceil(this.order / 2) - 1;
3088
- after.values = before.values.slice(mid + 1);
3089
- after.keys = before.keys.slice(mid + 1);
3090
- before.values = before.values.slice(0, mid + 1);
3091
- before.keys = before.keys.slice(0, mid + 1);
3092
- await this._insertInParent(before, after.values[0], after);
3093
- }
3393
+ return this.writeLock(0, async () => {
3394
+ const before = await this.insertableNode(value);
3395
+ await this._insertAtLeaf(before, key, value);
3396
+ if (before.values.length === this.order) {
3397
+ const after = await this._createNode(
3398
+ true,
3399
+ [],
3400
+ [],
3401
+ before.parent,
3402
+ null,
3403
+ null
3404
+ );
3405
+ const mid = Math.ceil(this.order / 2) - 1;
3406
+ after.values = before.values.slice(mid + 1);
3407
+ after.keys = before.keys.slice(mid + 1);
3408
+ before.values = before.values.slice(0, mid + 1);
3409
+ before.keys = before.keys.slice(0, mid + 1);
3410
+ await this._insertInParent(before, after.values[0], after);
3411
+ }
3412
+ });
3094
3413
  }
3095
3414
  async _deleteEntry(node, key) {
3096
3415
  if (!node.leaf) {
@@ -3255,504 +3574,255 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3255
3574
  }
3256
3575
  await this._updateNode(node);
3257
3576
  await this._updateNode(pointer);
3258
- }
3259
- if (!pointer.leaf) {
3260
- for (const key2 of pointer.keys) {
3261
- const n = await this.getNode(key2);
3262
- n.parent = pointer.id;
3263
- await this._updateNode(n);
3264
- }
3265
- }
3266
- if (!node.leaf) {
3267
- for (const key2 of node.keys) {
3268
- const n = await this.getNode(key2);
3269
- n.parent = node.id;
3270
- await this._updateNode(n);
3271
- }
3272
- }
3273
- if (!parentNode.leaf) {
3274
- for (const key2 of parentNode.keys) {
3275
- const n = await this.getNode(key2);
3276
- n.parent = parentNode.id;
3277
- await this._updateNode(n);
3278
- }
3279
- }
3280
- }
3281
- } else {
3282
- await this._updateNode(node);
3283
- }
3284
- }
3285
- async delete(key, value) {
3286
- let node = await this.insertableNodeByPrimary(value);
3287
- let found = false;
3288
- while (true) {
3289
- let i = node.values.length;
3290
- while (i--) {
3291
- const nValue = node.values[i];
3292
- if (this.comparator.isSame(value, nValue)) {
3293
- const keys = node.keys[i];
3294
- const keyIndex = keys.indexOf(key);
3295
- if (keyIndex !== -1) {
3296
- keys.splice(keyIndex, 1);
3297
- if (keys.length === 0) {
3298
- node.keys.splice(i, 1);
3299
- node.values.splice(i, 1);
3300
- }
3301
- await this._updateNode(node);
3302
- await this._deleteEntry(node, key);
3303
- found = true;
3304
- break;
3305
- }
3306
- }
3307
- }
3308
- if (found) break;
3309
- if (node.next) {
3310
- node = await this.getNode(node.next);
3311
- continue;
3312
- }
3313
- break;
3314
- }
3315
- }
3316
- async getHeadData() {
3317
- const head = await this._readHead();
3318
- if (head === null) {
3319
- throw new Error("Head not found");
3320
- }
3321
- return head.data;
3322
- }
3323
- async setHeadData(data) {
3324
- const head = await this._readHead();
3325
- if (head === null) {
3326
- throw new Error("Head not found");
3327
- }
3328
- await this._writeHead({
3329
- root: head.root,
3330
- order: head.order,
3331
- data
3332
- });
3333
- }
3334
- async commit(label) {
3335
- let result = await this.mvcc.commit(label);
3336
- if (result.success) {
3337
- result = await this.mvccRoot.commit(label);
3338
- if (result.success && this.rootTx !== this) {
3339
- this.rootTx.rootId = this.rootId;
3340
- }
3341
- if (result.success) {
3342
- for (const r of result.created) {
3343
- this.nodes.set(r.key, r.data);
3344
- }
3345
- for (const r of result.updated) {
3346
- this.nodes.set(r.key, r.data);
3347
- }
3348
- for (const r of result.deleted) {
3349
- this.nodes.delete(r.key);
3350
- }
3351
- }
3352
- }
3353
- return result;
3354
- }
3355
- rollback() {
3356
- return this.mvcc.rollback();
3357
- }
3358
- };
3359
- var BPTreeMVCCStrategyAsync = class extends AsyncMVCCStrategy {
3360
- constructor(strategy) {
3361
- super();
3362
- this.strategy = strategy;
3363
- }
3364
- async read(key) {
3365
- if (key === "__HEAD__") {
3366
- return await this.strategy.readHead();
3367
- }
3368
- return await this.strategy.read(key);
3369
- }
3370
- async write(key, value) {
3371
- if (key === "__HEAD__") {
3372
- await this.strategy.writeHead(value);
3373
- } else {
3374
- await this.strategy.write(key, value);
3375
- }
3376
- }
3377
- async delete(key) {
3378
- await this.strategy.delete(key);
3379
- }
3380
- async exists(key) {
3381
- if (key === "__HEAD__") {
3382
- return await this.strategy.readHead() !== null;
3383
- }
3384
- try {
3385
- const node = await this.strategy.read(key);
3386
- return node !== null && node !== void 0;
3387
- } catch {
3388
- return false;
3389
- }
3390
- }
3391
- };
3392
- var BPTreeAsync = class extends BPTreeAsyncTransaction {
3393
- constructor(strategy, comparator, option) {
3394
- const mvccRoot = new AsyncMVCCTransaction(new BPTreeMVCCStrategyAsync(strategy));
3395
- super(
3396
- null,
3397
- mvccRoot,
3398
- mvccRoot,
3399
- strategy,
3400
- comparator,
3401
- option
3402
- );
3403
- }
3404
- /**
3405
- * Creates a new asynchronous transaction.
3406
- * @returns A new BPTreeAsyncTransaction.
3407
- */
3408
- async createTransaction() {
3409
- const nestedTx = await this.mvcc.createNested();
3410
- const tx = new BPTreeAsyncTransaction(
3411
- this,
3412
- this.mvcc,
3413
- nestedTx,
3414
- this.strategy,
3415
- this.comparator,
3416
- this.option
3417
- );
3418
- await tx.init();
3419
- return tx;
3420
- }
3421
- async insert(key, value) {
3422
- const tx = await this.createTransaction();
3423
- await tx.insert(key, value);
3424
- const result = await tx.commit();
3425
- if (!result.success) {
3426
- throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
3427
- }
3428
- this.rootId = tx.getRootId();
3429
- }
3430
- async delete(key, value) {
3431
- const tx = await this.createTransaction();
3432
- await tx.delete(key, value);
3433
- const result = await tx.commit();
3434
- if (!result.success) {
3435
- throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
3436
- }
3437
- this.rootId = tx.getRootId();
3438
- }
3439
- };
3440
- var SerializeStrategy = class {
3441
- order;
3442
- head;
3443
- constructor(order) {
3444
- this.order = order;
3445
- this.head = {
3446
- order,
3447
- root: null,
3448
- data: {}
3449
- };
3450
- }
3451
- };
3452
- var SerializeStrategySync = class extends SerializeStrategy {
3453
- getHeadData(key, defaultValue) {
3454
- if (!Object.hasOwn(this.head.data, key)) {
3455
- this.setHeadData(key, defaultValue);
3456
- }
3457
- return this.head.data[key];
3458
- }
3459
- setHeadData(key, data) {
3460
- this.head.data[key] = data;
3461
- this.writeHead(this.head);
3462
- }
3463
- autoIncrement(key, defaultValue) {
3464
- const current = this.getHeadData(key, defaultValue);
3465
- const next = current + 1;
3466
- this.setHeadData(key, next);
3467
- return current;
3468
- }
3469
- };
3470
- var InMemoryStoreStrategySync = class extends SerializeStrategySync {
3471
- node;
3472
- constructor(order) {
3473
- super(order);
3474
- this.node = {};
3475
- }
3476
- id(isLeaf) {
3477
- return this.autoIncrement("index", 1).toString();
3478
- }
3479
- read(id) {
3480
- if (!Object.hasOwn(this.node, id)) {
3481
- throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
3482
- }
3483
- const node = this.node[id];
3484
- return JSON.parse(JSON.stringify(node));
3485
- }
3486
- write(id, node) {
3487
- this.node[id] = node;
3488
- }
3489
- delete(id) {
3490
- delete this.node[id];
3491
- }
3492
- readHead() {
3493
- if (this.head.root === null) {
3494
- return null;
3495
- }
3496
- return this.head;
3497
- }
3498
- writeHead(head) {
3499
- this.head = head;
3500
- }
3501
- };
3502
- var Ryoiki2 = class _Ryoiki2 {
3503
- readings;
3504
- writings;
3505
- readQueue;
3506
- writeQueue;
3507
- static async CatchError(promise) {
3508
- return await promise.then((v) => [void 0, v]).catch((err) => [err]);
3509
- }
3510
- static IsRangeOverlap(a, b) {
3511
- const [start1, end1] = a;
3512
- const [start2, end2] = b;
3513
- if (end1 <= start2 || end2 <= start1) {
3514
- return false;
3515
- }
3516
- return true;
3517
- }
3518
- static ERR_ALREADY_EXISTS(lockId) {
3519
- return new Error(`The '${lockId}' task already existing in queue or running.`);
3520
- }
3521
- static ERR_NOT_EXISTS(lockId) {
3522
- return new Error(`The '${lockId}' task not existing in task queue.`);
3523
- }
3524
- static ERR_TIMEOUT(lockId, timeout) {
3525
- return new Error(`The task with ID '${lockId}' failed to acquire the lock within the timeout(${timeout}ms).`);
3526
- }
3527
- /**
3528
- * Constructs a new instance of the Ryoiki class.
3529
- */
3530
- constructor() {
3531
- this.readings = /* @__PURE__ */ new Map();
3532
- this.writings = /* @__PURE__ */ new Map();
3533
- this.readQueue = /* @__PURE__ */ new Map();
3534
- this.writeQueue = /* @__PURE__ */ new Map();
3535
- }
3536
- /**
3537
- * Creates a range based on a start value and length.
3538
- * @param start - The starting value of the range.
3539
- * @param length - The length of the range.
3540
- * @returns A range tuple [start, start + length].
3541
- */
3542
- range(start, length) {
3543
- return [start, start + length];
3544
- }
3545
- rangeOverlapping(tasks, range) {
3546
- return Array.from(tasks.values()).some((t) => _Ryoiki2.IsRangeOverlap(t.range, range));
3547
- }
3548
- isSameRange(a, b) {
3549
- const [a1, a2] = a;
3550
- const [b1, b2] = b;
3551
- return a1 === b1 && a2 === b2;
3552
- }
3553
- fetchUnitAndRun(queue, workspaces) {
3554
- for (const [id, unit] of queue) {
3555
- if (!unit.condition()) {
3556
- continue;
3577
+ }
3578
+ if (!pointer.leaf) {
3579
+ for (const key2 of pointer.keys) {
3580
+ const n = await this.getNode(key2);
3581
+ n.parent = pointer.id;
3582
+ await this._updateNode(n);
3583
+ }
3584
+ }
3585
+ if (!node.leaf) {
3586
+ for (const key2 of node.keys) {
3587
+ const n = await this.getNode(key2);
3588
+ n.parent = node.id;
3589
+ await this._updateNode(n);
3590
+ }
3591
+ }
3592
+ if (!parentNode.leaf) {
3593
+ for (const key2 of parentNode.keys) {
3594
+ const n = await this.getNode(key2);
3595
+ n.parent = parentNode.id;
3596
+ await this._updateNode(n);
3597
+ }
3598
+ }
3557
3599
  }
3558
- this._alloc(queue, workspaces, id);
3600
+ } else {
3601
+ await this._updateNode(node);
3559
3602
  }
3560
3603
  }
3561
- _handleOverload(args, handlers, argPatterns) {
3562
- for (const [key, pattern] of Object.entries(argPatterns)) {
3563
- if (this._matchArgs(args, pattern)) {
3564
- return handlers[key](...args);
3604
+ async delete(key, value) {
3605
+ return this.writeLock(0, async () => {
3606
+ let node = await this.insertableNodeByPrimary(value);
3607
+ let found = false;
3608
+ while (true) {
3609
+ let i = node.values.length;
3610
+ while (i--) {
3611
+ const nValue = node.values[i];
3612
+ if (this.comparator.isSame(value, nValue)) {
3613
+ const keys = node.keys[i];
3614
+ const keyIndex = keys.indexOf(key);
3615
+ if (keyIndex !== -1) {
3616
+ keys.splice(keyIndex, 1);
3617
+ if (keys.length === 0) {
3618
+ node.keys.splice(i, 1);
3619
+ node.values.splice(i, 1);
3620
+ }
3621
+ await this._updateNode(node);
3622
+ await this._deleteEntry(node, key);
3623
+ found = true;
3624
+ break;
3625
+ }
3626
+ }
3627
+ }
3628
+ if (found) break;
3629
+ if (node.next) {
3630
+ node = await this.getNode(node.next);
3631
+ continue;
3632
+ }
3633
+ break;
3565
3634
  }
3566
- }
3567
- throw new Error("Invalid arguments");
3568
- }
3569
- _matchArgs(args, pattern) {
3570
- return args.every((arg, index) => {
3571
- const expectedType = pattern[index];
3572
- if (expectedType === void 0) return typeof arg === "undefined";
3573
- if (expectedType === Function) return typeof arg === "function";
3574
- if (expectedType === Number) return typeof arg === "number";
3575
- if (expectedType === Array) return Array.isArray(arg);
3576
- return false;
3577
3635
  });
3578
3636
  }
3579
- _createRandomId() {
3580
- const timestamp = Date.now().toString(36);
3581
- const random = Math.random().toString(36).substring(2);
3582
- return `${timestamp}${random}`;
3583
- }
3584
- _alloc(queue, workspaces, lockId) {
3585
- const unit = queue.get(lockId);
3586
- if (!unit) {
3587
- throw _Ryoiki2.ERR_NOT_EXISTS(lockId);
3637
+ async getHeadData() {
3638
+ const head = await this._readHead();
3639
+ if (head === null) {
3640
+ throw new Error("Head not found");
3588
3641
  }
3589
- workspaces.set(lockId, unit);
3590
- queue.delete(lockId);
3591
- unit.alloc();
3642
+ return head.data;
3592
3643
  }
3593
- _free(workspaces, lockId) {
3594
- const unit = workspaces.get(lockId);
3595
- if (!unit) {
3596
- throw _Ryoiki2.ERR_NOT_EXISTS(lockId);
3644
+ async setHeadData(data) {
3645
+ const head = await this._readHead();
3646
+ if (head === null) {
3647
+ throw new Error("Head not found");
3597
3648
  }
3598
- workspaces.delete(lockId);
3599
- unit.free();
3649
+ await this._writeHead({
3650
+ root: head.root,
3651
+ order: head.order,
3652
+ data
3653
+ });
3600
3654
  }
3601
- _lock(queue, range, timeout, task, condition) {
3602
- return new Promise((resolve, reject) => {
3603
- let timeoutId = null;
3604
- if (timeout >= 0) {
3605
- timeoutId = setTimeout(() => {
3606
- reject(_Ryoiki2.ERR_TIMEOUT(id, timeout));
3607
- }, timeout);
3655
+ async commit(label) {
3656
+ let result = await this.mvcc.commit(label);
3657
+ if (result.success) {
3658
+ const isRootTx = this.rootTx === this;
3659
+ if (!isRootTx) {
3660
+ result = await this.rootTx.commit(label);
3661
+ if (result.success) {
3662
+ this.rootTx.rootId = this.rootId;
3663
+ }
3608
3664
  }
3609
- const id = this._createRandomId();
3610
- const alloc = async () => {
3611
- if (timeoutId !== null) {
3612
- clearTimeout(timeoutId);
3665
+ if (result.success) {
3666
+ for (const r of result.created) {
3667
+ this.nodes.set(r.key, r.data);
3668
+ }
3669
+ for (const r of result.updated) {
3670
+ this.nodes.set(r.key, r.data);
3671
+ }
3672
+ for (const r of result.deleted) {
3673
+ this.nodes.delete(r.key);
3613
3674
  }
3614
- const [err, v] = await _Ryoiki2.CatchError(task(id));
3615
- if (err) reject(err);
3616
- else resolve(v);
3617
- };
3618
- const fetch = () => {
3619
- this.fetchUnitAndRun(this.readQueue, this.readings);
3620
- this.fetchUnitAndRun(this.writeQueue, this.writings);
3621
- };
3622
- queue.set(id, { id, range, condition, alloc, free: fetch });
3623
- fetch();
3624
- });
3625
- }
3626
- _checkWorking(range, workspaces) {
3627
- let isLocked = false;
3628
- for (const lock of workspaces.values()) {
3629
- if (_Ryoiki2.IsRangeOverlap(range, lock.range)) {
3630
- isLocked = true;
3631
- break;
3632
3675
  }
3633
3676
  }
3634
- return isLocked;
3677
+ return result;
3635
3678
  }
3636
- /**
3637
- * Checks if there is any active read lock within the specified range.
3638
- * @param range The range to check for active read locks.
3639
- * @returns `true` if there is an active read lock within the range, `false` otherwise.
3640
- */
3641
- isReading(range) {
3642
- return this._checkWorking(range, this.readings);
3679
+ rollback() {
3680
+ return this.mvcc.rollback();
3643
3681
  }
3644
- /**
3645
- * Checks if there is any active write lock within the specified range.
3646
- * @param range The range to check for active write locks.
3647
- * @returns `true` if there is an active write lock within the range, `false` otherwise.
3648
- */
3649
- isWriting(range) {
3650
- return this._checkWorking(range, this.writings);
3682
+ };
3683
+ var BPTreeMVCCStrategyAsync = class extends AsyncMVCCStrategy {
3684
+ constructor(strategy) {
3685
+ super();
3686
+ this.strategy = strategy;
3651
3687
  }
3652
- /**
3653
- * Checks if a read lock can be acquired within the specified range.
3654
- * @param range The range to check for read lock availability.
3655
- * @returns `true` if a read lock can be acquired, `false` otherwise.
3656
- */
3657
- canRead(range) {
3658
- const writing = this.isWriting(range);
3659
- return !writing;
3688
+ async read(key) {
3689
+ if (key === "__HEAD__") {
3690
+ return await this.strategy.readHead();
3691
+ }
3692
+ return await this.strategy.read(key);
3660
3693
  }
3661
- /**
3662
- * Checks if a write lock can be acquired within the specified range.
3663
- * @param range The range to check for write lock availability.
3664
- * @returns `true` if a write lock can be acquired, `false` otherwise.
3665
- */
3666
- canWrite(range) {
3667
- const reading = this.isReading(range);
3668
- const writing = this.isWriting(range);
3669
- return !reading && !writing;
3694
+ async write(key, value) {
3695
+ if (key === "__HEAD__") {
3696
+ await this.strategy.writeHead(value);
3697
+ } else {
3698
+ await this.strategy.write(key, value);
3699
+ }
3670
3700
  }
3671
- /**
3672
- * Internal implementation of the read lock. Handles both overloads.
3673
- * @template T - The return type of the task.
3674
- * @param arg0 - Either a range or a task callback.
3675
- * If a range is provided, the task is the second argument.
3676
- * @param arg1 - The task to execute, required if a range is provided.
3677
- * @param arg2 - The timeout for acquiring the lock.
3678
- * If the lock cannot be acquired within this period, an error will be thrown.
3679
- * If this value is not provided, no timeout will be set.
3680
- * @returns A promise resolving to the result of the task execution.
3681
- */
3682
- readLock(arg0, arg1, arg2) {
3683
- const [range, task, timeout] = this._handleOverload(
3684
- [arg0, arg1, arg2],
3685
- {
3686
- rangeTask: (range2, task2) => [range2, task2, -1],
3687
- rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
3688
- task: (task2) => [[-Infinity, Infinity], task2, -1],
3689
- taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
3690
- },
3691
- {
3692
- task: [Function],
3693
- taskTimeout: [Function, Number],
3694
- rangeTask: [Array, Function],
3695
- rangeTaskTimeout: [Array, Function, Number]
3696
- }
3697
- );
3698
- return this._lock(
3699
- this.readQueue,
3700
- range,
3701
- timeout,
3702
- task,
3703
- () => !this.rangeOverlapping(this.writings, range)
3704
- );
3701
+ async delete(key) {
3702
+ await this.strategy.delete(key);
3705
3703
  }
3706
- /**
3707
- * Internal implementation of the write lock. Handles both overloads.
3708
- * @template T - The return type of the task.
3709
- * @param arg0 - Either a range or a task callback.
3710
- * If a range is provided, the task is the second argument.
3711
- * @param arg1 - The task to execute, required if a range is provided.
3712
- * @param arg2 - The timeout for acquiring the lock.
3713
- * If the lock cannot be acquired within this period, an error will be thrown.
3714
- * If this value is not provided, no timeout will be set.
3715
- * @returns A promise resolving to the result of the task execution.
3716
- */
3717
- writeLock(arg0, arg1, arg2) {
3718
- const [range, task, timeout] = this._handleOverload(
3719
- [arg0, arg1, arg2],
3720
- {
3721
- rangeTask: (range2, task2) => [range2, task2, -1],
3722
- rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
3723
- task: (task2) => [[-Infinity, Infinity], task2, -1],
3724
- taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
3725
- },
3726
- {
3727
- task: [Function],
3728
- taskTimeout: [Function, Number],
3729
- rangeTask: [Array, Function],
3730
- rangeTaskTimeout: [Array, Function, Number]
3731
- }
3732
- );
3733
- return this._lock(
3734
- this.writeQueue,
3735
- range,
3736
- timeout,
3737
- task,
3738
- () => {
3739
- return !this.rangeOverlapping(this.writings, range) && !this.rangeOverlapping(this.readings, range);
3740
- }
3704
+ async exists(key) {
3705
+ if (key === "__HEAD__") {
3706
+ return await this.strategy.readHead() !== null;
3707
+ }
3708
+ try {
3709
+ const node = await this.strategy.read(key);
3710
+ return node !== null && node !== void 0;
3711
+ } catch {
3712
+ return false;
3713
+ }
3714
+ }
3715
+ };
3716
+ var BPTreeAsync = class extends BPTreeAsyncTransaction {
3717
+ constructor(strategy, comparator, option) {
3718
+ const mvccRoot = new AsyncMVCCTransaction(new BPTreeMVCCStrategyAsync(strategy));
3719
+ super(
3720
+ null,
3721
+ mvccRoot,
3722
+ mvccRoot,
3723
+ strategy,
3724
+ comparator,
3725
+ option
3741
3726
  );
3742
3727
  }
3743
3728
  /**
3744
- * Releases a read lock by its lock ID.
3745
- * @param lockId - The unique identifier for the lock to release.
3729
+ * Creates a new asynchronous transaction.
3730
+ * @returns A new BPTreeAsyncTransaction.
3746
3731
  */
3747
- readUnlock(lockId) {
3748
- this._free(this.readings, lockId);
3732
+ async createTransaction() {
3733
+ const nestedTx = this.mvcc.createNested();
3734
+ const tx = new BPTreeAsyncTransaction(
3735
+ this,
3736
+ this.mvcc,
3737
+ nestedTx,
3738
+ this.strategy,
3739
+ this.comparator,
3740
+ this.option
3741
+ );
3742
+ await tx._initInternal();
3743
+ return tx;
3749
3744
  }
3750
- /**
3751
- * Releases a write lock by its lock ID.
3752
- * @param lockId - The unique identifier for the lock to release.
3753
- */
3754
- writeUnlock(lockId) {
3755
- this._free(this.writings, lockId);
3745
+ async insert(key, value) {
3746
+ return this.writeLock(1, async () => {
3747
+ const tx = await this.createTransaction();
3748
+ await tx.insert(key, value);
3749
+ const result = await tx.commit();
3750
+ if (!result.success) {
3751
+ throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
3752
+ }
3753
+ });
3754
+ }
3755
+ async delete(key, value) {
3756
+ return this.writeLock(1, async () => {
3757
+ const tx = await this.createTransaction();
3758
+ await tx.delete(key, value);
3759
+ const result = await tx.commit();
3760
+ if (!result.success) {
3761
+ throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
3762
+ }
3763
+ });
3764
+ }
3765
+ };
3766
+ var SerializeStrategy = class {
3767
+ order;
3768
+ head;
3769
+ constructor(order) {
3770
+ this.order = order;
3771
+ this.head = {
3772
+ order,
3773
+ root: null,
3774
+ data: {}
3775
+ };
3776
+ }
3777
+ };
3778
+ var SerializeStrategySync = class extends SerializeStrategy {
3779
+ getHeadData(key, defaultValue) {
3780
+ if (!Object.hasOwn(this.head.data, key)) {
3781
+ this.setHeadData(key, defaultValue);
3782
+ }
3783
+ return this.head.data[key];
3784
+ }
3785
+ setHeadData(key, data) {
3786
+ this.head.data[key] = data;
3787
+ this.writeHead(this.head);
3788
+ }
3789
+ autoIncrement(key, defaultValue) {
3790
+ const current = this.getHeadData(key, defaultValue);
3791
+ const next = current + 1;
3792
+ this.setHeadData(key, next);
3793
+ return current;
3794
+ }
3795
+ };
3796
+ var InMemoryStoreStrategySync = class extends SerializeStrategySync {
3797
+ node;
3798
+ constructor(order) {
3799
+ super(order);
3800
+ this.node = {};
3801
+ }
3802
+ id(isLeaf) {
3803
+ return this.autoIncrement("index", 1).toString();
3804
+ }
3805
+ read(id) {
3806
+ if (!Object.hasOwn(this.node, id)) {
3807
+ throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
3808
+ }
3809
+ const node = this.node[id];
3810
+ return JSON.parse(JSON.stringify(node));
3811
+ }
3812
+ write(id, node) {
3813
+ this.node[id] = node;
3814
+ }
3815
+ delete(id) {
3816
+ delete this.node[id];
3817
+ }
3818
+ readHead() {
3819
+ if (this.head.root === null) {
3820
+ return null;
3821
+ }
3822
+ return this.head;
3823
+ }
3824
+ writeHead(head) {
3825
+ this.head = head;
3756
3826
  }
3757
3827
  };
3758
3828
  var SerializeStrategyAsync = class extends SerializeStrategy {
@@ -4543,6 +4613,7 @@ var MVCCTransaction2 = class {
4543
4613
  // delete 시 삭제 전 값 저장
4544
4614
  originallyExisted;
4545
4615
  // 트랜잭션 시작 시점에 디스크에 존재했던 키 (deleted 결과 필터링용)
4616
+ bufferHistory = /* @__PURE__ */ new Map();
4546
4617
  // Nested Transaction Properties
4547
4618
  parent;
4548
4619
  localVersion;
@@ -4597,26 +4668,45 @@ var MVCCTransaction2 = class {
4597
4668
  return false;
4598
4669
  }
4599
4670
  // --- Internal buffer manipulation helpers ---
4600
- _bufferCreate(key, value) {
4601
- this.localVersion++;
4671
+ _recordHistory(key) {
4672
+ const existsInWriteBuffer = this.writeBuffer.has(key);
4673
+ const existsInDeleteBuffer = this.deleteBuffer.has(key);
4674
+ const currentVer = this.keyVersions.get(key);
4675
+ if (currentVer !== void 0) {
4676
+ if (!this.bufferHistory.has(key)) this.bufferHistory.set(key, []);
4677
+ this.bufferHistory.get(key).push({
4678
+ value: existsInWriteBuffer ? this.writeBuffer.get(key) : this.deletedValues.get(key) ?? null,
4679
+ exists: existsInWriteBuffer || !existsInDeleteBuffer,
4680
+ version: currentVer
4681
+ });
4682
+ }
4683
+ }
4684
+ _bufferCreate(key, value, version) {
4685
+ if (version === void 0) this.localVersion++;
4686
+ const targetVersion = version ?? this.localVersion;
4687
+ this._recordHistory(key);
4602
4688
  this.writeBuffer.set(key, value);
4603
4689
  this.createdKeys.add(key);
4604
4690
  this.deleteBuffer.delete(key);
4605
4691
  this.originallyExisted.delete(key);
4606
- this.keyVersions.set(key, this.localVersion);
4692
+ this.keyVersions.set(key, targetVersion);
4607
4693
  }
4608
- _bufferWrite(key, value) {
4609
- this.localVersion++;
4694
+ _bufferWrite(key, value, version) {
4695
+ if (version === void 0) this.localVersion++;
4696
+ const targetVersion = version ?? this.localVersion;
4697
+ this._recordHistory(key);
4610
4698
  this.writeBuffer.set(key, value);
4611
4699
  this.deleteBuffer.delete(key);
4612
- this.keyVersions.set(key, this.localVersion);
4700
+ this.keyVersions.set(key, targetVersion);
4613
4701
  }
4614
- _bufferDelete(key) {
4615
- this.localVersion++;
4702
+ _bufferDelete(key, version) {
4703
+ if (version === void 0) this.localVersion++;
4704
+ const targetVersion = version ?? this.localVersion;
4705
+ this._recordHistory(key);
4616
4706
  this.deleteBuffer.add(key);
4617
4707
  this.writeBuffer.delete(key);
4618
4708
  this.createdKeys.delete(key);
4619
- this.keyVersions.set(key, this.localVersion);
4709
+ this.keyVersions.set(key, targetVersion);
4620
4710
  }
4621
4711
  /**
4622
4712
  * Returns the entries that will be created, updated, and deleted by this transaction.
@@ -4693,7 +4783,9 @@ var MVCCTransaction2 = class {
4693
4783
  break;
4694
4784
  }
4695
4785
  }
4696
- if (latestInSnapshotIdx > 0) {
4786
+ if (latestInSnapshotIdx === versions.length - 1) {
4787
+ this.versionIndex.delete(key);
4788
+ } else if (latestInSnapshotIdx > 0) {
4697
4789
  versions.splice(0, latestInSnapshotIdx);
4698
4790
  }
4699
4791
  }
@@ -4750,27 +4842,68 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4750
4842
  if (this.committed) throw new Error("Transaction already committed");
4751
4843
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
4752
4844
  if (this.deleteBuffer.has(key)) return null;
4753
- return this.root._diskRead(key, this.snapshotVersion);
4845
+ if (this.parent) {
4846
+ return this.parent._readSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
4847
+ }
4848
+ return this._diskRead(key, this.snapshotVersion);
4754
4849
  }
4755
4850
  exists(key) {
4756
4851
  if (this.committed) throw new Error("Transaction already committed");
4757
4852
  if (this.deleteBuffer.has(key)) return false;
4758
4853
  if (this.writeBuffer.has(key)) return true;
4759
- return this.root._diskExists(key, this.snapshotVersion);
4854
+ if (this.parent) {
4855
+ return this.parent._existsSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
4856
+ }
4857
+ return this._diskExists(key, this.snapshotVersion);
4858
+ }
4859
+ _existsSnapshot(key, snapshotVersion, snapshotLocalVersion) {
4860
+ if (this.writeBuffer.has(key)) {
4861
+ const keyModVersion = this.keyVersions.get(key);
4862
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
4863
+ return true;
4864
+ }
4865
+ }
4866
+ if (this.deleteBuffer.has(key)) {
4867
+ const keyModVersion = this.keyVersions.get(key);
4868
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
4869
+ return false;
4870
+ }
4871
+ }
4872
+ const history = this.bufferHistory.get(key);
4873
+ if (history && snapshotLocalVersion !== void 0) {
4874
+ for (let i = history.length - 1; i >= 0; i--) {
4875
+ if (history[i].version <= snapshotLocalVersion) {
4876
+ return history[i].exists;
4877
+ }
4878
+ }
4879
+ }
4880
+ if (this.parent) {
4881
+ return this.parent._existsSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
4882
+ } else {
4883
+ return this._diskExists(key, snapshotVersion);
4884
+ }
4760
4885
  }
4761
4886
  _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
4762
4887
  if (this.writeBuffer.has(key)) {
4763
4888
  const keyModVersion = this.keyVersions.get(key);
4764
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
4889
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
4765
4890
  return this.writeBuffer.get(key);
4766
4891
  }
4767
4892
  }
4768
4893
  if (this.deleteBuffer.has(key)) {
4769
4894
  const keyModVersion = this.keyVersions.get(key);
4770
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
4895
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
4771
4896
  return null;
4772
4897
  }
4773
4898
  }
4899
+ const history = this.bufferHistory.get(key);
4900
+ if (history && snapshotLocalVersion !== void 0) {
4901
+ for (let i = history.length - 1; i >= 0; i--) {
4902
+ if (history[i].version <= snapshotLocalVersion) {
4903
+ return history[i].exists ? history[i].value : null;
4904
+ }
4905
+ }
4906
+ }
4774
4907
  if (this.parent) {
4775
4908
  return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
4776
4909
  } else {
@@ -4780,54 +4913,22 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4780
4913
  commit(label) {
4781
4914
  const { created, updated, deleted } = this.getResultEntries();
4782
4915
  if (this.committed) {
4783
- return {
4784
- label,
4785
- success: false,
4786
- error: "Transaction already committed",
4787
- conflict: void 0,
4788
- created,
4789
- updated,
4790
- deleted
4791
- };
4916
+ return { label, success: false, error: "Transaction already committed", conflict: void 0, created, updated, deleted };
4792
4917
  }
4793
4918
  if (this.hasCommittedAncestor()) {
4794
- return {
4795
- label,
4796
- success: false,
4797
- error: "Ancestor transaction already committed",
4798
- conflict: void 0,
4799
- created,
4800
- updated,
4801
- deleted
4802
- };
4919
+ return { label, success: false, error: "Ancestor transaction already committed", conflict: void 0, created, updated, deleted };
4803
4920
  }
4804
4921
  if (this.parent) {
4805
4922
  const failure = this.parent._merge(this);
4806
4923
  if (failure) {
4807
- return {
4808
- label,
4809
- success: false,
4810
- error: failure.error,
4811
- conflict: failure.conflict,
4812
- created,
4813
- updated,
4814
- deleted
4815
- };
4924
+ return { label, success: false, error: failure.error, conflict: failure.conflict, created, updated, deleted };
4816
4925
  }
4817
4926
  this.committed = true;
4818
4927
  } else {
4819
4928
  if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
4820
4929
  const failure = this._merge(this);
4821
4930
  if (failure) {
4822
- return {
4823
- label,
4824
- success: false,
4825
- error: failure.error,
4826
- conflict: failure.conflict,
4827
- created: [],
4828
- updated: [],
4829
- deleted: []
4830
- };
4931
+ return { label, success: false, error: failure.error, conflict: failure.conflict, created: [], updated: [], deleted: [] };
4831
4932
  }
4832
4933
  this.writeBuffer.clear();
4833
4934
  this.deleteBuffer.clear();
@@ -4835,17 +4936,12 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4835
4936
  this.deletedValues.clear();
4836
4937
  this.originallyExisted.clear();
4837
4938
  this.keyVersions.clear();
4939
+ this.bufferHistory.clear();
4838
4940
  this.localVersion = 0;
4839
4941
  this.snapshotVersion = this.version;
4840
4942
  }
4841
4943
  }
4842
- return {
4843
- label,
4844
- success: true,
4845
- created,
4846
- updated,
4847
- deleted
4848
- };
4944
+ return { label, success: true, created, updated, deleted };
4849
4945
  }
4850
4946
  _merge(child) {
4851
4947
  if (this.parent) {
@@ -4854,11 +4950,7 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4854
4950
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
4855
4951
  return {
4856
4952
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
4857
- conflict: {
4858
- key,
4859
- parent: this.read(key),
4860
- child: child.read(key)
4861
- }
4953
+ conflict: { key, parent: this.read(key), child: child.read(key) }
4862
4954
  };
4863
4955
  }
4864
4956
  }
@@ -4867,40 +4959,26 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4867
4959
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
4868
4960
  return {
4869
4961
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
4870
- conflict: {
4871
- key,
4872
- parent: this.read(key),
4873
- child: child.read(key)
4874
- }
4962
+ conflict: { key, parent: this.read(key), child: child.read(key) }
4875
4963
  };
4876
4964
  }
4877
4965
  }
4878
- const newLocalVersion = this.localVersion + 1;
4879
- for (const key of child.writeBuffer.keys()) {
4880
- this.writeBuffer.set(key, child.writeBuffer.get(key));
4881
- this.deleteBuffer.delete(key);
4882
- this.keyVersions.set(key, newLocalVersion);
4883
- if (child.createdKeys.has(key)) {
4884
- this.createdKeys.add(key);
4885
- }
4966
+ const mergeVersion = ++this.localVersion;
4967
+ for (const [key, value] of child.writeBuffer) {
4968
+ const wasCreated = child.createdKeys.has(key);
4969
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
4970
+ else this._bufferWrite(key, value, mergeVersion);
4886
4971
  }
4887
4972
  for (const key of child.deleteBuffer) {
4888
- this.deleteBuffer.add(key);
4889
- this.writeBuffer.delete(key);
4890
- this.createdKeys.delete(key);
4891
- this.keyVersions.set(key, newLocalVersion);
4892
4973
  const deletedValue = child.deletedValues.get(key);
4893
- if (deletedValue !== void 0) {
4894
- this.deletedValues.set(key, deletedValue);
4895
- }
4896
- if (child.originallyExisted.has(key)) {
4974
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
4975
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
4897
4976
  this.originallyExisted.add(key);
4898
4977
  }
4978
+ this._bufferDelete(key, mergeVersion);
4899
4979
  }
4900
- this.localVersion = newLocalVersion;
4901
4980
  this.root.activeTransactions.delete(child);
4902
4981
  } else {
4903
- const newVersion = this.version + 1;
4904
4982
  if (child !== this) {
4905
4983
  const modifiedKeys = /* @__PURE__ */ new Set([...child.writeBuffer.keys(), ...child.deleteBuffer]);
4906
4984
  for (const key of modifiedKeys) {
@@ -4910,58 +4988,53 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4910
4988
  if (lastVer > child.snapshotVersion) {
4911
4989
  return {
4912
4990
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (v${lastVer})`,
4913
- conflict: {
4914
- key,
4915
- parent: this.read(key),
4916
- child: child.read(key)
4917
- }
4991
+ conflict: { key, parent: this.read(key), child: child.read(key) }
4918
4992
  };
4919
4993
  }
4920
4994
  }
4995
+ const lastModLocalVer = this.keyVersions.get(key);
4996
+ if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
4997
+ return {
4998
+ error: `Commit conflict: Key '${key}' was modified by a newer transaction in the same session (Local v${lastModLocalVer})`,
4999
+ conflict: { key, parent: this.read(key), child: child.read(key) }
5000
+ };
5001
+ }
4921
5002
  }
4922
- }
4923
- for (const [key, value] of child.writeBuffer) {
4924
- this.writeBuffer.set(key, value);
4925
- this.deleteBuffer.delete(key);
4926
- if (child.createdKeys.has(key)) {
4927
- this.createdKeys.add(key);
4928
- }
4929
- }
4930
- for (const key of child.deleteBuffer) {
4931
- this.deleteBuffer.add(key);
4932
- this.writeBuffer.delete(key);
4933
- this.createdKeys.delete(key);
4934
- const deletedValue = child.deletedValues.get(key);
4935
- if (deletedValue !== void 0) {
4936
- this.deletedValues.set(key, deletedValue);
5003
+ const mergeVersion = ++this.localVersion;
5004
+ for (const [key, value] of child.writeBuffer) {
5005
+ const wasCreated = child.createdKeys.has(key);
5006
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
5007
+ this.originallyExisted.add(key);
5008
+ }
5009
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
5010
+ else this._bufferWrite(key, value, mergeVersion);
4937
5011
  }
4938
- if (child.originallyExisted.has(key)) {
4939
- this.originallyExisted.add(key);
5012
+ for (const key of child.deleteBuffer) {
5013
+ const deletedValue = child.deletedValues.get(key);
5014
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
5015
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
5016
+ this.originallyExisted.add(key);
5017
+ }
5018
+ this._bufferDelete(key, mergeVersion);
4940
5019
  }
5020
+ this.root.activeTransactions.delete(child);
5021
+ } else {
5022
+ const newVersion = this.version + 1;
5023
+ for (const [key, value] of this.writeBuffer) this._diskWrite(key, value, newVersion);
5024
+ for (const key of this.deleteBuffer) this._diskDelete(key, newVersion);
5025
+ this.version = newVersion;
5026
+ this._cleanupDeletedCache();
4941
5027
  }
4942
- for (const [key, value] of child.writeBuffer) {
4943
- this._diskWrite(key, value, newVersion);
4944
- }
4945
- for (const key of child.deleteBuffer) {
4946
- this._diskDelete(key, newVersion);
4947
- }
4948
- this.version = newVersion;
4949
- this.root.activeTransactions.delete(child);
4950
- this._cleanupDeletedCache();
4951
5028
  }
4952
5029
  return null;
4953
5030
  }
4954
- // --- Internal IO Helpers (Root Only) ---
4955
5031
  _diskWrite(key, value, version) {
4956
5032
  const strategy = this.strategy;
4957
5033
  if (!strategy) throw new Error("Root Transaction missing strategy");
4958
5034
  if (strategy.exists(key)) {
4959
5035
  const currentVal = strategy.read(key);
4960
5036
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
4961
- this.deletedCache.get(key).push({
4962
- value: currentVal,
4963
- deletedAtVersion: version
4964
- });
5037
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
4965
5038
  }
4966
5039
  strategy.write(key, value);
4967
5040
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -4977,9 +5050,8 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4977
5050
  let targetVerObj = null;
4978
5051
  let nextVerObj = null;
4979
5052
  for (const v of versions) {
4980
- if (v.version <= snapshotVersion) {
4981
- targetVerObj = v;
4982
- } else {
5053
+ if (v.version <= snapshotVersion) targetVerObj = v;
5054
+ else {
4983
5055
  nextVerObj = v;
4984
5056
  break;
4985
5057
  }
@@ -4996,6 +5068,7 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
4996
5068
  }
4997
5069
  if (!targetVerObj.exists) return null;
4998
5070
  if (!nextVerObj) {
5071
+ if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
4999
5072
  return strategy.read(key);
5000
5073
  }
5001
5074
  const cached = this.deletedCache.get(key);
@@ -5013,14 +5086,24 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
5013
5086
  return strategy.exists(key);
5014
5087
  }
5015
5088
  let targetVerObj = null;
5089
+ let nextVerObj = null;
5016
5090
  for (const v of versions) {
5017
- if (v.version <= snapshotVersion) {
5018
- targetVerObj = v;
5019
- } else {
5091
+ if (v.version <= snapshotVersion) targetVerObj = v;
5092
+ else {
5093
+ nextVerObj = v;
5020
5094
  break;
5021
5095
  }
5022
5096
  }
5023
- if (!targetVerObj) return strategy.exists(key);
5097
+ if (!targetVerObj) {
5098
+ if (nextVerObj) {
5099
+ const cached = this.deletedCache.get(key);
5100
+ if (cached) {
5101
+ const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
5102
+ if (match) return true;
5103
+ }
5104
+ }
5105
+ return false;
5106
+ }
5024
5107
  return targetVerObj.exists;
5025
5108
  }
5026
5109
  _diskDelete(key, snapshotVersion) {
@@ -5029,12 +5112,9 @@ var SyncMVCCTransaction2 = class _SyncMVCCTransaction2 extends MVCCTransaction2
5029
5112
  if (strategy.exists(key)) {
5030
5113
  const currentVal = strategy.read(key);
5031
5114
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
5032
- this.deletedCache.get(key).push({
5033
- value: currentVal,
5034
- deletedAtVersion: snapshotVersion
5035
- });
5115
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
5116
+ strategy.delete(key);
5036
5117
  }
5037
- strategy.delete(key);
5038
5118
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
5039
5119
  this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });
5040
5120
  }
@@ -5355,84 +5435,93 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5355
5435
  if (this.committed) throw new Error("Transaction already committed");
5356
5436
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
5357
5437
  if (this.deleteBuffer.has(key)) return null;
5358
- return this.root._diskRead(key, this.snapshotVersion);
5438
+ if (this.parent) {
5439
+ return this.parent._readSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
5440
+ }
5441
+ return await this._diskRead(key, this.snapshotVersion);
5359
5442
  }
5360
5443
  async exists(key) {
5361
5444
  if (this.committed) throw new Error("Transaction already committed");
5362
5445
  if (this.deleteBuffer.has(key)) return false;
5363
5446
  if (this.writeBuffer.has(key)) return true;
5364
- return this.root._diskExists(key, this.snapshotVersion);
5447
+ if (this.parent) {
5448
+ return this.parent._existsSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
5449
+ }
5450
+ return await this._diskExists(key, this.snapshotVersion);
5451
+ }
5452
+ async _existsSnapshot(key, snapshotVersion, snapshotLocalVersion) {
5453
+ if (this.writeBuffer.has(key)) {
5454
+ const keyModVersion = this.keyVersions.get(key);
5455
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
5456
+ return true;
5457
+ }
5458
+ }
5459
+ if (this.deleteBuffer.has(key)) {
5460
+ const keyModVersion = this.keyVersions.get(key);
5461
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
5462
+ return false;
5463
+ }
5464
+ }
5465
+ const history = this.bufferHistory.get(key);
5466
+ if (history && snapshotLocalVersion !== void 0) {
5467
+ for (let i = history.length - 1; i >= 0; i--) {
5468
+ if (history[i].version <= snapshotLocalVersion) {
5469
+ return history[i].exists;
5470
+ }
5471
+ }
5472
+ }
5473
+ if (this.parent) {
5474
+ return this.parent._existsSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
5475
+ } else {
5476
+ return await this._diskExists(key, snapshotVersion);
5477
+ }
5365
5478
  }
5366
5479
  async _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
5367
5480
  if (this.writeBuffer.has(key)) {
5368
5481
  const keyModVersion = this.keyVersions.get(key);
5369
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
5482
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
5370
5483
  return this.writeBuffer.get(key);
5371
5484
  }
5372
5485
  }
5373
5486
  if (this.deleteBuffer.has(key)) {
5374
5487
  const keyModVersion = this.keyVersions.get(key);
5375
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
5488
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
5376
5489
  return null;
5377
5490
  }
5378
5491
  }
5492
+ const history = this.bufferHistory.get(key);
5493
+ if (history && snapshotLocalVersion !== void 0) {
5494
+ for (let i = history.length - 1; i >= 0; i--) {
5495
+ if (history[i].version <= snapshotLocalVersion) {
5496
+ return history[i].exists ? history[i].value : null;
5497
+ }
5498
+ }
5499
+ }
5379
5500
  if (this.parent) {
5380
5501
  return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
5381
5502
  } else {
5382
- return this._diskRead(key, snapshotVersion);
5503
+ return await this._diskRead(key, snapshotVersion);
5383
5504
  }
5384
5505
  }
5385
5506
  async commit(label) {
5386
5507
  const { created, updated, deleted } = this.getResultEntries();
5387
5508
  if (this.committed) {
5388
- return {
5389
- label,
5390
- success: false,
5391
- error: "Transaction already committed",
5392
- conflict: void 0,
5393
- created,
5394
- updated,
5395
- deleted
5396
- };
5509
+ return { label, success: false, error: "Transaction already committed", conflict: void 0, created, updated, deleted };
5397
5510
  }
5398
5511
  if (this.hasCommittedAncestor()) {
5399
- return {
5400
- label,
5401
- success: false,
5402
- error: "Ancestor transaction already committed",
5403
- conflict: void 0,
5404
- created,
5405
- updated,
5406
- deleted
5407
- };
5512
+ return { label, success: false, error: "Ancestor transaction already committed", conflict: void 0, created, updated, deleted };
5408
5513
  }
5409
5514
  if (this.parent) {
5410
5515
  const failure = await this.parent._merge(this);
5411
5516
  if (failure) {
5412
- return {
5413
- label,
5414
- success: false,
5415
- error: failure.error,
5416
- conflict: failure.conflict,
5417
- created,
5418
- updated,
5419
- deleted
5420
- };
5517
+ return { label, success: false, error: failure.error, conflict: failure.conflict, created, updated, deleted };
5421
5518
  }
5422
5519
  this.committed = true;
5423
5520
  } else {
5424
5521
  if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
5425
5522
  const failure = await this._merge(this);
5426
5523
  if (failure) {
5427
- return {
5428
- label,
5429
- success: false,
5430
- error: failure.error,
5431
- conflict: failure.conflict,
5432
- created: [],
5433
- updated: [],
5434
- deleted: []
5435
- };
5524
+ return { label, success: false, error: failure.error, conflict: failure.conflict, created: [], updated: [], deleted: [] };
5436
5525
  }
5437
5526
  this.writeBuffer.clear();
5438
5527
  this.deleteBuffer.clear();
@@ -5440,17 +5529,12 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5440
5529
  this.deletedValues.clear();
5441
5530
  this.originallyExisted.clear();
5442
5531
  this.keyVersions.clear();
5532
+ this.bufferHistory.clear();
5443
5533
  this.localVersion = 0;
5444
5534
  this.snapshotVersion = this.version;
5445
5535
  }
5446
5536
  }
5447
- return {
5448
- label,
5449
- success: true,
5450
- created,
5451
- updated,
5452
- deleted
5453
- };
5537
+ return { label, success: true, created, updated, deleted };
5454
5538
  }
5455
5539
  async _merge(child) {
5456
5540
  return this.writeLock(async () => {
@@ -5460,11 +5544,7 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5460
5544
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
5461
5545
  return {
5462
5546
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
5463
- conflict: {
5464
- key,
5465
- parent: await this.read(key),
5466
- child: await child.read(key)
5467
- }
5547
+ conflict: { key, parent: await this.read(key), child: await child.read(key) }
5468
5548
  };
5469
5549
  }
5470
5550
  }
@@ -5473,41 +5553,27 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5473
5553
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
5474
5554
  return {
5475
5555
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
5476
- conflict: {
5477
- key,
5478
- parent: await this.read(key),
5479
- child: await child.read(key)
5480
- }
5556
+ conflict: { key, parent: await this.read(key), child: await child.read(key) }
5481
5557
  };
5482
5558
  }
5483
5559
  }
5484
- const newLocalVersion = this.localVersion + 1;
5485
- for (const key of child.writeBuffer.keys()) {
5486
- this.writeBuffer.set(key, child.writeBuffer.get(key));
5487
- this.deleteBuffer.delete(key);
5488
- this.keyVersions.set(key, newLocalVersion);
5489
- if (child.createdKeys.has(key)) {
5490
- this.createdKeys.add(key);
5491
- }
5560
+ const mergeVersion = ++this.localVersion;
5561
+ for (const [key, value] of child.writeBuffer) {
5562
+ const wasCreated = child.createdKeys.has(key);
5563
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
5564
+ else this._bufferWrite(key, value, mergeVersion);
5492
5565
  }
5493
5566
  for (const key of child.deleteBuffer) {
5494
- this.deleteBuffer.add(key);
5495
- this.writeBuffer.delete(key);
5496
- this.createdKeys.delete(key);
5497
- this.keyVersions.set(key, newLocalVersion);
5498
5567
  const deletedValue = child.deletedValues.get(key);
5499
- if (deletedValue !== void 0) {
5500
- this.deletedValues.set(key, deletedValue);
5501
- }
5502
- if (child.originallyExisted.has(key)) {
5568
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
5569
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
5503
5570
  this.originallyExisted.add(key);
5504
5571
  }
5572
+ this._bufferDelete(key, mergeVersion);
5505
5573
  }
5506
- this.localVersion = newLocalVersion;
5507
5574
  this.root.activeTransactions.delete(child);
5508
5575
  return null;
5509
5576
  } else {
5510
- const newVersion = this.version + 1;
5511
5577
  if (child !== this) {
5512
5578
  const modifiedKeys = /* @__PURE__ */ new Set([...child.writeBuffer.keys(), ...child.deleteBuffer]);
5513
5579
  for (const key of modifiedKeys) {
@@ -5517,59 +5583,54 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5517
5583
  if (lastVer > child.snapshotVersion) {
5518
5584
  return {
5519
5585
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (v${lastVer})`,
5520
- conflict: {
5521
- key,
5522
- parent: await this.read(key),
5523
- child: await child.read(key)
5524
- }
5586
+ conflict: { key, parent: await this.read(key), child: await child.read(key) }
5525
5587
  };
5526
5588
  }
5527
5589
  }
5590
+ const lastModLocalVer = this.keyVersions.get(key);
5591
+ if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
5592
+ return {
5593
+ error: `Commit conflict: Key '${key}' was modified by a newer transaction in the same session (Local v${lastModLocalVer})`,
5594
+ conflict: { key, parent: await this.read(key), child: await child.read(key) }
5595
+ };
5596
+ }
5528
5597
  }
5529
- }
5530
- for (const [key, value] of child.writeBuffer) {
5531
- this.writeBuffer.set(key, value);
5532
- this.deleteBuffer.delete(key);
5533
- if (child.createdKeys.has(key)) {
5534
- this.createdKeys.add(key);
5535
- }
5536
- }
5537
- for (const key of child.deleteBuffer) {
5538
- this.deleteBuffer.add(key);
5539
- this.writeBuffer.delete(key);
5540
- this.createdKeys.delete(key);
5541
- const deletedValue = child.deletedValues.get(key);
5542
- if (deletedValue !== void 0) {
5543
- this.deletedValues.set(key, deletedValue);
5598
+ const mergeVersion = ++this.localVersion;
5599
+ for (const [key, value] of child.writeBuffer) {
5600
+ const wasCreated = child.createdKeys.has(key);
5601
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
5602
+ this.originallyExisted.add(key);
5603
+ }
5604
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
5605
+ else this._bufferWrite(key, value, mergeVersion);
5544
5606
  }
5545
- if (child.originallyExisted.has(key)) {
5546
- this.originallyExisted.add(key);
5607
+ for (const key of child.deleteBuffer) {
5608
+ const deletedValue = child.deletedValues.get(key);
5609
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
5610
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
5611
+ this.originallyExisted.add(key);
5612
+ }
5613
+ this._bufferDelete(key, mergeVersion);
5547
5614
  }
5615
+ this.root.activeTransactions.delete(child);
5616
+ } else {
5617
+ const newVersion = this.version + 1;
5618
+ for (const [key, value] of this.writeBuffer) await this._diskWrite(key, value, newVersion);
5619
+ for (const key of this.deleteBuffer) await this._diskDelete(key, newVersion);
5620
+ this.version = newVersion;
5621
+ this._cleanupDeletedCache();
5548
5622
  }
5549
- for (const [key, value] of child.writeBuffer) {
5550
- await this._diskWrite(key, value, newVersion);
5551
- }
5552
- for (const key of child.deleteBuffer) {
5553
- await this._diskDelete(key, newVersion);
5554
- }
5555
- this.version = newVersion;
5556
- this.root.activeTransactions.delete(child);
5557
- this._cleanupDeletedCache();
5558
5623
  return null;
5559
5624
  }
5560
5625
  });
5561
5626
  }
5562
- // --- Internal IO Helpers (Root Only) ---
5563
5627
  async _diskWrite(key, value, version) {
5564
5628
  const strategy = this.strategy;
5565
5629
  if (!strategy) throw new Error("Root Transaction missing strategy");
5566
5630
  if (await strategy.exists(key)) {
5567
5631
  const currentVal = await strategy.read(key);
5568
5632
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
5569
- this.deletedCache.get(key).push({
5570
- value: currentVal,
5571
- deletedAtVersion: version
5572
- });
5633
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
5573
5634
  }
5574
5635
  await strategy.write(key, value);
5575
5636
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -5580,14 +5641,13 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5580
5641
  if (!strategy) throw new Error("Root Transaction missing strategy");
5581
5642
  const versions = this.versionIndex.get(key);
5582
5643
  if (!versions) {
5583
- return await strategy.exists(key) ? strategy.read(key) : null;
5644
+ return await strategy.exists(key) ? await strategy.read(key) : null;
5584
5645
  }
5585
5646
  let targetVerObj = null;
5586
5647
  let nextVerObj = null;
5587
5648
  for (const v of versions) {
5588
- if (v.version <= snapshotVersion) {
5589
- targetVerObj = v;
5590
- } else {
5649
+ if (v.version <= snapshotVersion) targetVerObj = v;
5650
+ else {
5591
5651
  nextVerObj = v;
5592
5652
  break;
5593
5653
  }
@@ -5604,6 +5664,7 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5604
5664
  }
5605
5665
  if (!targetVerObj.exists) return null;
5606
5666
  if (!nextVerObj) {
5667
+ if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
5607
5668
  return strategy.read(key);
5608
5669
  }
5609
5670
  const cached = this.deletedCache.get(key);
@@ -5618,17 +5679,27 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5618
5679
  if (!strategy) throw new Error("Root Transaction missing strategy");
5619
5680
  const versions = this.versionIndex.get(key);
5620
5681
  if (!versions) {
5621
- return strategy.exists(key);
5682
+ return await strategy.exists(key);
5622
5683
  }
5623
5684
  let targetVerObj = null;
5685
+ let nextVerObj = null;
5624
5686
  for (const v of versions) {
5625
- if (v.version <= snapshotVersion) {
5626
- targetVerObj = v;
5627
- } else {
5687
+ if (v.version <= snapshotVersion) targetVerObj = v;
5688
+ else {
5689
+ nextVerObj = v;
5628
5690
  break;
5629
5691
  }
5630
5692
  }
5631
- if (!targetVerObj) return strategy.exists(key);
5693
+ if (!targetVerObj) {
5694
+ if (nextVerObj) {
5695
+ const cached = this.deletedCache.get(key);
5696
+ if (cached) {
5697
+ const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
5698
+ if (match) return true;
5699
+ }
5700
+ }
5701
+ return false;
5702
+ }
5632
5703
  return targetVerObj.exists;
5633
5704
  }
5634
5705
  async _diskDelete(key, snapshotVersion) {
@@ -5637,12 +5708,9 @@ var AsyncMVCCTransaction2 = class _AsyncMVCCTransaction2 extends MVCCTransaction
5637
5708
  if (await strategy.exists(key)) {
5638
5709
  const currentVal = await strategy.read(key);
5639
5710
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
5640
- this.deletedCache.get(key).push({
5641
- value: currentVal,
5642
- deletedAtVersion: snapshotVersion
5643
- });
5711
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
5712
+ await strategy.delete(key);
5644
5713
  }
5645
- await strategy.delete(key);
5646
5714
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
5647
5715
  this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });
5648
5716
  }
@@ -8343,7 +8411,6 @@ var RowTableEngine = class {
8343
8411
  if (!btx) return;
8344
8412
  const result = await btx.commit();
8345
8413
  if (result.success) {
8346
- await this.bptree.init();
8347
8414
  for (const entry of result.deleted) {
8348
8415
  await this.strategy.delete(entry.key);
8349
8416
  }