serializable-bptree 8.1.2 → 8.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -105,6 +105,7 @@ var MVCCTransaction = class {
105
105
  // delete 시 삭제 전 값 저장
106
106
  originallyExisted;
107
107
  // 트랜잭션 시작 시점에 디스크에 존재했던 키 (deleted 결과 필터링용)
108
+ bufferHistory = /* @__PURE__ */ new Map();
108
109
  // Nested Transaction Properties
109
110
  parent;
110
111
  localVersion;
@@ -159,26 +160,45 @@ var MVCCTransaction = class {
159
160
  return false;
160
161
  }
161
162
  // --- Internal buffer manipulation helpers ---
162
- _bufferCreate(key, value) {
163
- this.localVersion++;
163
+ _recordHistory(key) {
164
+ const existsInWriteBuffer = this.writeBuffer.has(key);
165
+ const existsInDeleteBuffer = this.deleteBuffer.has(key);
166
+ const currentVer = this.keyVersions.get(key);
167
+ if (currentVer !== void 0) {
168
+ if (!this.bufferHistory.has(key)) this.bufferHistory.set(key, []);
169
+ this.bufferHistory.get(key).push({
170
+ value: existsInWriteBuffer ? this.writeBuffer.get(key) : this.deletedValues.get(key) ?? null,
171
+ exists: existsInWriteBuffer || !existsInDeleteBuffer,
172
+ version: currentVer
173
+ });
174
+ }
175
+ }
176
+ _bufferCreate(key, value, version) {
177
+ if (version === void 0) this.localVersion++;
178
+ const targetVersion = version ?? this.localVersion;
179
+ this._recordHistory(key);
164
180
  this.writeBuffer.set(key, value);
165
181
  this.createdKeys.add(key);
166
182
  this.deleteBuffer.delete(key);
167
183
  this.originallyExisted.delete(key);
168
- this.keyVersions.set(key, this.localVersion);
184
+ this.keyVersions.set(key, targetVersion);
169
185
  }
170
- _bufferWrite(key, value) {
171
- this.localVersion++;
186
+ _bufferWrite(key, value, version) {
187
+ if (version === void 0) this.localVersion++;
188
+ const targetVersion = version ?? this.localVersion;
189
+ this._recordHistory(key);
172
190
  this.writeBuffer.set(key, value);
173
191
  this.deleteBuffer.delete(key);
174
- this.keyVersions.set(key, this.localVersion);
192
+ this.keyVersions.set(key, targetVersion);
175
193
  }
176
- _bufferDelete(key) {
177
- this.localVersion++;
194
+ _bufferDelete(key, version) {
195
+ if (version === void 0) this.localVersion++;
196
+ const targetVersion = version ?? this.localVersion;
197
+ this._recordHistory(key);
178
198
  this.deleteBuffer.add(key);
179
199
  this.writeBuffer.delete(key);
180
200
  this.createdKeys.delete(key);
181
- this.keyVersions.set(key, this.localVersion);
201
+ this.keyVersions.set(key, targetVersion);
182
202
  }
183
203
  /**
184
204
  * Returns the entries that will be created, updated, and deleted by this transaction.
@@ -255,7 +275,9 @@ var MVCCTransaction = class {
255
275
  break;
256
276
  }
257
277
  }
258
- if (latestInSnapshotIdx > 0) {
278
+ if (latestInSnapshotIdx === versions.length - 1) {
279
+ this.versionIndex.delete(key);
280
+ } else if (latestInSnapshotIdx > 0) {
259
281
  versions.splice(0, latestInSnapshotIdx);
260
282
  }
261
283
  }
@@ -312,27 +334,68 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
312
334
  if (this.committed) throw new Error("Transaction already committed");
313
335
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
314
336
  if (this.deleteBuffer.has(key)) return null;
315
- return this.root._diskRead(key, this.snapshotVersion);
337
+ if (this.parent) {
338
+ return this.parent._readSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
339
+ }
340
+ return this._diskRead(key, this.snapshotVersion);
316
341
  }
317
342
  exists(key) {
318
343
  if (this.committed) throw new Error("Transaction already committed");
319
344
  if (this.deleteBuffer.has(key)) return false;
320
345
  if (this.writeBuffer.has(key)) return true;
321
- return this.root._diskExists(key, this.snapshotVersion);
346
+ if (this.parent) {
347
+ return this.parent._existsSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
348
+ }
349
+ return this._diskExists(key, this.snapshotVersion);
350
+ }
351
+ _existsSnapshot(key, snapshotVersion, snapshotLocalVersion) {
352
+ if (this.writeBuffer.has(key)) {
353
+ const keyModVersion = this.keyVersions.get(key);
354
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
355
+ return true;
356
+ }
357
+ }
358
+ if (this.deleteBuffer.has(key)) {
359
+ const keyModVersion = this.keyVersions.get(key);
360
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
361
+ return false;
362
+ }
363
+ }
364
+ const history = this.bufferHistory.get(key);
365
+ if (history && snapshotLocalVersion !== void 0) {
366
+ for (let i = history.length - 1; i >= 0; i--) {
367
+ if (history[i].version <= snapshotLocalVersion) {
368
+ return history[i].exists;
369
+ }
370
+ }
371
+ }
372
+ if (this.parent) {
373
+ return this.parent._existsSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
374
+ } else {
375
+ return this._diskExists(key, snapshotVersion);
376
+ }
322
377
  }
323
378
  _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
324
379
  if (this.writeBuffer.has(key)) {
325
380
  const keyModVersion = this.keyVersions.get(key);
326
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
381
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
327
382
  return this.writeBuffer.get(key);
328
383
  }
329
384
  }
330
385
  if (this.deleteBuffer.has(key)) {
331
386
  const keyModVersion = this.keyVersions.get(key);
332
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
387
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
333
388
  return null;
334
389
  }
335
390
  }
391
+ const history = this.bufferHistory.get(key);
392
+ if (history && snapshotLocalVersion !== void 0) {
393
+ for (let i = history.length - 1; i >= 0; i--) {
394
+ if (history[i].version <= snapshotLocalVersion) {
395
+ return history[i].exists ? history[i].value : null;
396
+ }
397
+ }
398
+ }
336
399
  if (this.parent) {
337
400
  return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
338
401
  } else {
@@ -342,54 +405,22 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
342
405
  commit(label) {
343
406
  const { created, updated, deleted } = this.getResultEntries();
344
407
  if (this.committed) {
345
- return {
346
- label,
347
- success: false,
348
- error: "Transaction already committed",
349
- conflict: void 0,
350
- created,
351
- updated,
352
- deleted
353
- };
408
+ return { label, success: false, error: "Transaction already committed", conflict: void 0, created, updated, deleted };
354
409
  }
355
410
  if (this.hasCommittedAncestor()) {
356
- return {
357
- label,
358
- success: false,
359
- error: "Ancestor transaction already committed",
360
- conflict: void 0,
361
- created,
362
- updated,
363
- deleted
364
- };
411
+ return { label, success: false, error: "Ancestor transaction already committed", conflict: void 0, created, updated, deleted };
365
412
  }
366
413
  if (this.parent) {
367
414
  const failure = this.parent._merge(this);
368
415
  if (failure) {
369
- return {
370
- label,
371
- success: false,
372
- error: failure.error,
373
- conflict: failure.conflict,
374
- created,
375
- updated,
376
- deleted
377
- };
416
+ return { label, success: false, error: failure.error, conflict: failure.conflict, created, updated, deleted };
378
417
  }
379
418
  this.committed = true;
380
419
  } else {
381
420
  if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
382
421
  const failure = this._merge(this);
383
422
  if (failure) {
384
- return {
385
- label,
386
- success: false,
387
- error: failure.error,
388
- conflict: failure.conflict,
389
- created: [],
390
- updated: [],
391
- deleted: []
392
- };
423
+ return { label, success: false, error: failure.error, conflict: failure.conflict, created: [], updated: [], deleted: [] };
393
424
  }
394
425
  this.writeBuffer.clear();
395
426
  this.deleteBuffer.clear();
@@ -397,17 +428,12 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
397
428
  this.deletedValues.clear();
398
429
  this.originallyExisted.clear();
399
430
  this.keyVersions.clear();
431
+ this.bufferHistory.clear();
400
432
  this.localVersion = 0;
401
433
  this.snapshotVersion = this.version;
402
434
  }
403
435
  }
404
- return {
405
- label,
406
- success: true,
407
- created,
408
- updated,
409
- deleted
410
- };
436
+ return { label, success: true, created, updated, deleted };
411
437
  }
412
438
  _merge(child) {
413
439
  if (this.parent) {
@@ -416,11 +442,7 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
416
442
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
417
443
  return {
418
444
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
419
- conflict: {
420
- key,
421
- parent: this.read(key),
422
- child: child.read(key)
423
- }
445
+ conflict: { key, parent: this.read(key), child: child.read(key) }
424
446
  };
425
447
  }
426
448
  }
@@ -429,40 +451,26 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
429
451
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
430
452
  return {
431
453
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
432
- conflict: {
433
- key,
434
- parent: this.read(key),
435
- child: child.read(key)
436
- }
454
+ conflict: { key, parent: this.read(key), child: child.read(key) }
437
455
  };
438
456
  }
439
457
  }
440
- const newLocalVersion = this.localVersion + 1;
441
- for (const key of child.writeBuffer.keys()) {
442
- this.writeBuffer.set(key, child.writeBuffer.get(key));
443
- this.deleteBuffer.delete(key);
444
- this.keyVersions.set(key, newLocalVersion);
445
- if (child.createdKeys.has(key)) {
446
- this.createdKeys.add(key);
447
- }
458
+ const mergeVersion = ++this.localVersion;
459
+ for (const [key, value] of child.writeBuffer) {
460
+ const wasCreated = child.createdKeys.has(key);
461
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
462
+ else this._bufferWrite(key, value, mergeVersion);
448
463
  }
449
464
  for (const key of child.deleteBuffer) {
450
- this.deleteBuffer.add(key);
451
- this.writeBuffer.delete(key);
452
- this.createdKeys.delete(key);
453
- this.keyVersions.set(key, newLocalVersion);
454
465
  const deletedValue = child.deletedValues.get(key);
455
- if (deletedValue !== void 0) {
456
- this.deletedValues.set(key, deletedValue);
457
- }
458
- if (child.originallyExisted.has(key)) {
466
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
467
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
459
468
  this.originallyExisted.add(key);
460
469
  }
470
+ this._bufferDelete(key, mergeVersion);
461
471
  }
462
- this.localVersion = newLocalVersion;
463
472
  this.root.activeTransactions.delete(child);
464
473
  } else {
465
- const newVersion = this.version + 1;
466
474
  if (child !== this) {
467
475
  const modifiedKeys = /* @__PURE__ */ new Set([...child.writeBuffer.keys(), ...child.deleteBuffer]);
468
476
  for (const key of modifiedKeys) {
@@ -472,58 +480,53 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
472
480
  if (lastVer > child.snapshotVersion) {
473
481
  return {
474
482
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (v${lastVer})`,
475
- conflict: {
476
- key,
477
- parent: this.read(key),
478
- child: child.read(key)
479
- }
483
+ conflict: { key, parent: this.read(key), child: child.read(key) }
480
484
  };
481
485
  }
482
486
  }
487
+ const lastModLocalVer = this.keyVersions.get(key);
488
+ if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
489
+ return {
490
+ error: `Commit conflict: Key '${key}' was modified by a newer transaction in the same session (Local v${lastModLocalVer})`,
491
+ conflict: { key, parent: this.read(key), child: child.read(key) }
492
+ };
493
+ }
483
494
  }
484
- }
485
- for (const [key, value] of child.writeBuffer) {
486
- this.writeBuffer.set(key, value);
487
- this.deleteBuffer.delete(key);
488
- if (child.createdKeys.has(key)) {
489
- this.createdKeys.add(key);
490
- }
491
- }
492
- for (const key of child.deleteBuffer) {
493
- this.deleteBuffer.add(key);
494
- this.writeBuffer.delete(key);
495
- this.createdKeys.delete(key);
496
- const deletedValue = child.deletedValues.get(key);
497
- if (deletedValue !== void 0) {
498
- this.deletedValues.set(key, deletedValue);
495
+ const mergeVersion = ++this.localVersion;
496
+ for (const [key, value] of child.writeBuffer) {
497
+ const wasCreated = child.createdKeys.has(key);
498
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
499
+ this.originallyExisted.add(key);
500
+ }
501
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
502
+ else this._bufferWrite(key, value, mergeVersion);
499
503
  }
500
- if (child.originallyExisted.has(key)) {
501
- this.originallyExisted.add(key);
504
+ for (const key of child.deleteBuffer) {
505
+ const deletedValue = child.deletedValues.get(key);
506
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
507
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
508
+ this.originallyExisted.add(key);
509
+ }
510
+ this._bufferDelete(key, mergeVersion);
502
511
  }
512
+ this.root.activeTransactions.delete(child);
513
+ } else {
514
+ const newVersion = this.version + 1;
515
+ for (const [key, value] of this.writeBuffer) this._diskWrite(key, value, newVersion);
516
+ for (const key of this.deleteBuffer) this._diskDelete(key, newVersion);
517
+ this.version = newVersion;
518
+ this._cleanupDeletedCache();
503
519
  }
504
- for (const [key, value] of child.writeBuffer) {
505
- this._diskWrite(key, value, newVersion);
506
- }
507
- for (const key of child.deleteBuffer) {
508
- this._diskDelete(key, newVersion);
509
- }
510
- this.version = newVersion;
511
- this.root.activeTransactions.delete(child);
512
- this._cleanupDeletedCache();
513
520
  }
514
521
  return null;
515
522
  }
516
- // --- Internal IO Helpers (Root Only) ---
517
523
  _diskWrite(key, value, version) {
518
524
  const strategy = this.strategy;
519
525
  if (!strategy) throw new Error("Root Transaction missing strategy");
520
526
  if (strategy.exists(key)) {
521
527
  const currentVal = strategy.read(key);
522
528
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
523
- this.deletedCache.get(key).push({
524
- value: currentVal,
525
- deletedAtVersion: version
526
- });
529
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
527
530
  }
528
531
  strategy.write(key, value);
529
532
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -539,9 +542,8 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
539
542
  let targetVerObj = null;
540
543
  let nextVerObj = null;
541
544
  for (const v of versions) {
542
- if (v.version <= snapshotVersion) {
543
- targetVerObj = v;
544
- } else {
545
+ if (v.version <= snapshotVersion) targetVerObj = v;
546
+ else {
545
547
  nextVerObj = v;
546
548
  break;
547
549
  }
@@ -558,6 +560,7 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
558
560
  }
559
561
  if (!targetVerObj.exists) return null;
560
562
  if (!nextVerObj) {
563
+ if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
561
564
  return strategy.read(key);
562
565
  }
563
566
  const cached = this.deletedCache.get(key);
@@ -575,14 +578,24 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
575
578
  return strategy.exists(key);
576
579
  }
577
580
  let targetVerObj = null;
581
+ let nextVerObj = null;
578
582
  for (const v of versions) {
579
- if (v.version <= snapshotVersion) {
580
- targetVerObj = v;
581
- } else {
583
+ if (v.version <= snapshotVersion) targetVerObj = v;
584
+ else {
585
+ nextVerObj = v;
582
586
  break;
583
587
  }
584
588
  }
585
- if (!targetVerObj) return strategy.exists(key);
589
+ if (!targetVerObj) {
590
+ if (nextVerObj) {
591
+ const cached = this.deletedCache.get(key);
592
+ if (cached) {
593
+ const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
594
+ if (match) return true;
595
+ }
596
+ }
597
+ return false;
598
+ }
586
599
  return targetVerObj.exists;
587
600
  }
588
601
  _diskDelete(key, snapshotVersion) {
@@ -591,12 +604,9 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
591
604
  if (strategy.exists(key)) {
592
605
  const currentVal = strategy.read(key);
593
606
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
594
- this.deletedCache.get(key).push({
595
- value: currentVal,
596
- deletedAtVersion: snapshotVersion
597
- });
607
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
608
+ strategy.delete(key);
598
609
  }
599
- strategy.delete(key);
600
610
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
601
611
  this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });
602
612
  }
@@ -917,84 +927,93 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
917
927
  if (this.committed) throw new Error("Transaction already committed");
918
928
  if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
919
929
  if (this.deleteBuffer.has(key)) return null;
920
- return this.root._diskRead(key, this.snapshotVersion);
930
+ if (this.parent) {
931
+ return this.parent._readSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
932
+ }
933
+ return await this._diskRead(key, this.snapshotVersion);
921
934
  }
922
935
  async exists(key) {
923
936
  if (this.committed) throw new Error("Transaction already committed");
924
937
  if (this.deleteBuffer.has(key)) return false;
925
938
  if (this.writeBuffer.has(key)) return true;
926
- return this.root._diskExists(key, this.snapshotVersion);
939
+ if (this.parent) {
940
+ return this.parent._existsSnapshot(key, this.snapshotVersion, this.snapshotLocalVersion);
941
+ }
942
+ return await this._diskExists(key, this.snapshotVersion);
943
+ }
944
+ async _existsSnapshot(key, snapshotVersion, snapshotLocalVersion) {
945
+ if (this.writeBuffer.has(key)) {
946
+ const keyModVersion = this.keyVersions.get(key);
947
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
948
+ return true;
949
+ }
950
+ }
951
+ if (this.deleteBuffer.has(key)) {
952
+ const keyModVersion = this.keyVersions.get(key);
953
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
954
+ return false;
955
+ }
956
+ }
957
+ const history = this.bufferHistory.get(key);
958
+ if (history && snapshotLocalVersion !== void 0) {
959
+ for (let i = history.length - 1; i >= 0; i--) {
960
+ if (history[i].version <= snapshotLocalVersion) {
961
+ return history[i].exists;
962
+ }
963
+ }
964
+ }
965
+ if (this.parent) {
966
+ return this.parent._existsSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
967
+ } else {
968
+ return await this._diskExists(key, snapshotVersion);
969
+ }
927
970
  }
928
971
  async _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
929
972
  if (this.writeBuffer.has(key)) {
930
973
  const keyModVersion = this.keyVersions.get(key);
931
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
974
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
932
975
  return this.writeBuffer.get(key);
933
976
  }
934
977
  }
935
978
  if (this.deleteBuffer.has(key)) {
936
979
  const keyModVersion = this.keyVersions.get(key);
937
- if (snapshotLocalVersion === void 0 || keyModVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
980
+ if (snapshotLocalVersion === void 0 || keyModVersion <= snapshotLocalVersion) {
938
981
  return null;
939
982
  }
940
983
  }
984
+ const history = this.bufferHistory.get(key);
985
+ if (history && snapshotLocalVersion !== void 0) {
986
+ for (let i = history.length - 1; i >= 0; i--) {
987
+ if (history[i].version <= snapshotLocalVersion) {
988
+ return history[i].exists ? history[i].value : null;
989
+ }
990
+ }
991
+ }
941
992
  if (this.parent) {
942
993
  return this.parent._readSnapshot(key, snapshotVersion, this.snapshotLocalVersion);
943
994
  } else {
944
- return this._diskRead(key, snapshotVersion);
995
+ return await this._diskRead(key, snapshotVersion);
945
996
  }
946
997
  }
947
998
  async commit(label) {
948
999
  const { created, updated, deleted } = this.getResultEntries();
949
1000
  if (this.committed) {
950
- return {
951
- label,
952
- success: false,
953
- error: "Transaction already committed",
954
- conflict: void 0,
955
- created,
956
- updated,
957
- deleted
958
- };
1001
+ return { label, success: false, error: "Transaction already committed", conflict: void 0, created, updated, deleted };
959
1002
  }
960
1003
  if (this.hasCommittedAncestor()) {
961
- return {
962
- label,
963
- success: false,
964
- error: "Ancestor transaction already committed",
965
- conflict: void 0,
966
- created,
967
- updated,
968
- deleted
969
- };
1004
+ return { label, success: false, error: "Ancestor transaction already committed", conflict: void 0, created, updated, deleted };
970
1005
  }
971
1006
  if (this.parent) {
972
1007
  const failure = await this.parent._merge(this);
973
1008
  if (failure) {
974
- return {
975
- label,
976
- success: false,
977
- error: failure.error,
978
- conflict: failure.conflict,
979
- created,
980
- updated,
981
- deleted
982
- };
1009
+ return { label, success: false, error: failure.error, conflict: failure.conflict, created, updated, deleted };
983
1010
  }
984
1011
  this.committed = true;
985
1012
  } else {
986
1013
  if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
987
1014
  const failure = await this._merge(this);
988
1015
  if (failure) {
989
- return {
990
- label,
991
- success: false,
992
- error: failure.error,
993
- conflict: failure.conflict,
994
- created: [],
995
- updated: [],
996
- deleted: []
997
- };
1016
+ return { label, success: false, error: failure.error, conflict: failure.conflict, created: [], updated: [], deleted: [] };
998
1017
  }
999
1018
  this.writeBuffer.clear();
1000
1019
  this.deleteBuffer.clear();
@@ -1002,17 +1021,12 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1002
1021
  this.deletedValues.clear();
1003
1022
  this.originallyExisted.clear();
1004
1023
  this.keyVersions.clear();
1024
+ this.bufferHistory.clear();
1005
1025
  this.localVersion = 0;
1006
1026
  this.snapshotVersion = this.version;
1007
1027
  }
1008
1028
  }
1009
- return {
1010
- label,
1011
- success: true,
1012
- created,
1013
- updated,
1014
- deleted
1015
- };
1029
+ return { label, success: true, created, updated, deleted };
1016
1030
  }
1017
1031
  async _merge(child) {
1018
1032
  return this.writeLock(async () => {
@@ -1022,11 +1036,7 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1022
1036
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
1023
1037
  return {
1024
1038
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
1025
- conflict: {
1026
- key,
1027
- parent: await this.read(key),
1028
- child: await child.read(key)
1029
- }
1039
+ conflict: { key, parent: await this.read(key), child: await child.read(key) }
1030
1040
  };
1031
1041
  }
1032
1042
  }
@@ -1035,41 +1045,27 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1035
1045
  if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
1036
1046
  return {
1037
1047
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`,
1038
- conflict: {
1039
- key,
1040
- parent: await this.read(key),
1041
- child: await child.read(key)
1042
- }
1048
+ conflict: { key, parent: await this.read(key), child: await child.read(key) }
1043
1049
  };
1044
1050
  }
1045
1051
  }
1046
- const newLocalVersion = this.localVersion + 1;
1047
- for (const key of child.writeBuffer.keys()) {
1048
- this.writeBuffer.set(key, child.writeBuffer.get(key));
1049
- this.deleteBuffer.delete(key);
1050
- this.keyVersions.set(key, newLocalVersion);
1051
- if (child.createdKeys.has(key)) {
1052
- this.createdKeys.add(key);
1053
- }
1052
+ const mergeVersion = ++this.localVersion;
1053
+ for (const [key, value] of child.writeBuffer) {
1054
+ const wasCreated = child.createdKeys.has(key);
1055
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
1056
+ else this._bufferWrite(key, value, mergeVersion);
1054
1057
  }
1055
1058
  for (const key of child.deleteBuffer) {
1056
- this.deleteBuffer.add(key);
1057
- this.writeBuffer.delete(key);
1058
- this.createdKeys.delete(key);
1059
- this.keyVersions.set(key, newLocalVersion);
1060
1059
  const deletedValue = child.deletedValues.get(key);
1061
- if (deletedValue !== void 0) {
1062
- this.deletedValues.set(key, deletedValue);
1063
- }
1064
- if (child.originallyExisted.has(key)) {
1060
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
1061
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
1065
1062
  this.originallyExisted.add(key);
1066
1063
  }
1064
+ this._bufferDelete(key, mergeVersion);
1067
1065
  }
1068
- this.localVersion = newLocalVersion;
1069
1066
  this.root.activeTransactions.delete(child);
1070
1067
  return null;
1071
1068
  } else {
1072
- const newVersion = this.version + 1;
1073
1069
  if (child !== this) {
1074
1070
  const modifiedKeys = /* @__PURE__ */ new Set([...child.writeBuffer.keys(), ...child.deleteBuffer]);
1075
1071
  for (const key of modifiedKeys) {
@@ -1079,59 +1075,54 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1079
1075
  if (lastVer > child.snapshotVersion) {
1080
1076
  return {
1081
1077
  error: `Commit conflict: Key '${key}' was modified by a newer transaction (v${lastVer})`,
1082
- conflict: {
1083
- key,
1084
- parent: await this.read(key),
1085
- child: await child.read(key)
1086
- }
1078
+ conflict: { key, parent: await this.read(key), child: await child.read(key) }
1087
1079
  };
1088
1080
  }
1089
1081
  }
1082
+ const lastModLocalVer = this.keyVersions.get(key);
1083
+ if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
1084
+ return {
1085
+ error: `Commit conflict: Key '${key}' was modified by a newer transaction in the same session (Local v${lastModLocalVer})`,
1086
+ conflict: { key, parent: await this.read(key), child: await child.read(key) }
1087
+ };
1088
+ }
1090
1089
  }
1091
- }
1092
- for (const [key, value] of child.writeBuffer) {
1093
- this.writeBuffer.set(key, value);
1094
- this.deleteBuffer.delete(key);
1095
- if (child.createdKeys.has(key)) {
1096
- this.createdKeys.add(key);
1097
- }
1098
- }
1099
- for (const key of child.deleteBuffer) {
1100
- this.deleteBuffer.add(key);
1101
- this.writeBuffer.delete(key);
1102
- this.createdKeys.delete(key);
1103
- const deletedValue = child.deletedValues.get(key);
1104
- if (deletedValue !== void 0) {
1105
- this.deletedValues.set(key, deletedValue);
1090
+ const mergeVersion = ++this.localVersion;
1091
+ for (const [key, value] of child.writeBuffer) {
1092
+ const wasCreated = child.createdKeys.has(key);
1093
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
1094
+ this.originallyExisted.add(key);
1095
+ }
1096
+ if (wasCreated) this._bufferCreate(key, value, mergeVersion);
1097
+ else this._bufferWrite(key, value, mergeVersion);
1106
1098
  }
1107
- if (child.originallyExisted.has(key)) {
1108
- this.originallyExisted.add(key);
1099
+ for (const key of child.deleteBuffer) {
1100
+ const deletedValue = child.deletedValues.get(key);
1101
+ if (deletedValue !== void 0) this.deletedValues.set(key, deletedValue);
1102
+ if (child.originallyExisted.has(key) && !this.createdKeys.has(key)) {
1103
+ this.originallyExisted.add(key);
1104
+ }
1105
+ this._bufferDelete(key, mergeVersion);
1109
1106
  }
1107
+ this.root.activeTransactions.delete(child);
1108
+ } else {
1109
+ const newVersion = this.version + 1;
1110
+ for (const [key, value] of this.writeBuffer) await this._diskWrite(key, value, newVersion);
1111
+ for (const key of this.deleteBuffer) await this._diskDelete(key, newVersion);
1112
+ this.version = newVersion;
1113
+ this._cleanupDeletedCache();
1110
1114
  }
1111
- for (const [key, value] of child.writeBuffer) {
1112
- await this._diskWrite(key, value, newVersion);
1113
- }
1114
- for (const key of child.deleteBuffer) {
1115
- await this._diskDelete(key, newVersion);
1116
- }
1117
- this.version = newVersion;
1118
- this.root.activeTransactions.delete(child);
1119
- this._cleanupDeletedCache();
1120
1115
  return null;
1121
1116
  }
1122
1117
  });
1123
1118
  }
1124
- // --- Internal IO Helpers (Root Only) ---
1125
1119
  async _diskWrite(key, value, version) {
1126
1120
  const strategy = this.strategy;
1127
1121
  if (!strategy) throw new Error("Root Transaction missing strategy");
1128
1122
  if (await strategy.exists(key)) {
1129
1123
  const currentVal = await strategy.read(key);
1130
1124
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
1131
- this.deletedCache.get(key).push({
1132
- value: currentVal,
1133
- deletedAtVersion: version
1134
- });
1125
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: version });
1135
1126
  }
1136
1127
  await strategy.write(key, value);
1137
1128
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
@@ -1142,14 +1133,13 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1142
1133
  if (!strategy) throw new Error("Root Transaction missing strategy");
1143
1134
  const versions = this.versionIndex.get(key);
1144
1135
  if (!versions) {
1145
- return await strategy.exists(key) ? strategy.read(key) : null;
1136
+ return await strategy.exists(key) ? await strategy.read(key) : null;
1146
1137
  }
1147
1138
  let targetVerObj = null;
1148
1139
  let nextVerObj = null;
1149
1140
  for (const v of versions) {
1150
- if (v.version <= snapshotVersion) {
1151
- targetVerObj = v;
1152
- } else {
1141
+ if (v.version <= snapshotVersion) targetVerObj = v;
1142
+ else {
1153
1143
  nextVerObj = v;
1154
1144
  break;
1155
1145
  }
@@ -1166,6 +1156,7 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1166
1156
  }
1167
1157
  if (!targetVerObj.exists) return null;
1168
1158
  if (!nextVerObj) {
1159
+ if (this.writeBuffer.has(key)) return this.writeBuffer.get(key);
1169
1160
  return strategy.read(key);
1170
1161
  }
1171
1162
  const cached = this.deletedCache.get(key);
@@ -1180,17 +1171,27 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1180
1171
  if (!strategy) throw new Error("Root Transaction missing strategy");
1181
1172
  const versions = this.versionIndex.get(key);
1182
1173
  if (!versions) {
1183
- return strategy.exists(key);
1174
+ return await strategy.exists(key);
1184
1175
  }
1185
1176
  let targetVerObj = null;
1177
+ let nextVerObj = null;
1186
1178
  for (const v of versions) {
1187
- if (v.version <= snapshotVersion) {
1188
- targetVerObj = v;
1189
- } else {
1179
+ if (v.version <= snapshotVersion) targetVerObj = v;
1180
+ else {
1181
+ nextVerObj = v;
1190
1182
  break;
1191
1183
  }
1192
1184
  }
1193
- if (!targetVerObj) return strategy.exists(key);
1185
+ if (!targetVerObj) {
1186
+ if (nextVerObj) {
1187
+ const cached = this.deletedCache.get(key);
1188
+ if (cached) {
1189
+ const match = cached.find((c) => c.deletedAtVersion === nextVerObj.version);
1190
+ if (match) return true;
1191
+ }
1192
+ }
1193
+ return false;
1194
+ }
1194
1195
  return targetVerObj.exists;
1195
1196
  }
1196
1197
  async _diskDelete(key, snapshotVersion) {
@@ -1199,12 +1200,9 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
1199
1200
  if (await strategy.exists(key)) {
1200
1201
  const currentVal = await strategy.read(key);
1201
1202
  if (!this.deletedCache.has(key)) this.deletedCache.set(key, []);
1202
- this.deletedCache.get(key).push({
1203
- value: currentVal,
1204
- deletedAtVersion: snapshotVersion
1205
- });
1203
+ this.deletedCache.get(key).push({ value: currentVal, deletedAtVersion: snapshotVersion });
1204
+ await strategy.delete(key);
1206
1205
  }
1207
- await strategy.delete(key);
1208
1206
  if (!this.versionIndex.has(key)) this.versionIndex.set(key, []);
1209
1207
  this.versionIndex.get(key).push({ version: snapshotVersion, exists: false });
1210
1208
  }
@@ -1546,6 +1544,8 @@ var BPTreeTransaction = class _BPTreeTransaction {
1546
1544
  option;
1547
1545
  order;
1548
1546
  rootId;
1547
+ isInitialized = false;
1548
+ isDestroyed = false;
1549
1549
  verifierMap = {
1550
1550
  gt: (nv, v) => this.comparator.isHigher(nv, v),
1551
1551
  gte: (nv, v) => this.comparator.isHigher(nv, v) || this.comparator.isSame(nv, v),
@@ -1810,13 +1810,26 @@ var BPTreeTransaction = class _BPTreeTransaction {
1810
1810
  getResultEntries() {
1811
1811
  return this.mvcc.getResultEntries();
1812
1812
  }
1813
+ _clearCache() {
1814
+ this._cachedRegexp.clear();
1815
+ this.nodes.clear();
1816
+ }
1813
1817
  /**
1814
1818
  * Clears all cached nodes.
1815
1819
  * This method is useful for freeing up memory when the tree is no longer needed.
1816
1820
  */
1817
1821
  clear() {
1818
- this._cachedRegexp.clear();
1819
- this.nodes.clear();
1822
+ if (this.rootTx !== this) {
1823
+ throw new Error("Cannot call clear on a nested transaction");
1824
+ }
1825
+ this._clearInternal();
1826
+ }
1827
+ _clearInternal() {
1828
+ if (this.isDestroyed) {
1829
+ throw new Error("Transaction already destroyed");
1830
+ }
1831
+ this._clearCache();
1832
+ this.isDestroyed = true;
1820
1833
  }
1821
1834
  _binarySearchValues(values, target, usePrimary = false, upperBound = false) {
1822
1835
  let low = 0;
@@ -2122,28 +2135,46 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2122
2135
  }
2123
2136
  }
2124
2137
  init() {
2125
- this.clear();
2126
- const head = this._readHead();
2127
- if (head === null) {
2128
- this.order = this.strategy.order;
2129
- const root = this._createNode(true, [], []);
2130
- this._writeHead({
2131
- root: root.id,
2132
- order: this.order,
2133
- data: this.strategy.head.data
2134
- });
2135
- } else {
2136
- const { root, order } = head;
2137
- this.strategy.head = head;
2138
- this.order = order;
2139
- this._writeHead({
2140
- root,
2141
- order: this.order,
2142
- data: this.strategy.head.data
2143
- });
2138
+ if (this.rootTx !== this) {
2139
+ throw new Error("Cannot call init on a nested transaction");
2140
+ }
2141
+ this._initInternal();
2142
+ }
2143
+ _initInternal() {
2144
+ if (this.isInitialized) {
2145
+ throw new Error("Transaction already initialized");
2146
+ }
2147
+ if (this.isDestroyed) {
2148
+ throw new Error("Transaction already destroyed");
2144
2149
  }
2145
- if (this.order < 3) {
2146
- throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
2150
+ this.isInitialized = true;
2151
+ try {
2152
+ this._clearCache();
2153
+ const head = this._readHead();
2154
+ if (head === null) {
2155
+ this.order = this.strategy.order;
2156
+ const root = this._createNode(true, [], []);
2157
+ this._writeHead({
2158
+ root: root.id,
2159
+ order: this.order,
2160
+ data: this.strategy.head.data
2161
+ });
2162
+ } else {
2163
+ const { root, order } = head;
2164
+ this.strategy.head = head;
2165
+ this.order = order;
2166
+ this._writeHead({
2167
+ root,
2168
+ order: this.order,
2169
+ data: this.strategy.head.data
2170
+ });
2171
+ }
2172
+ if (this.order < 3) {
2173
+ throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
2174
+ }
2175
+ } catch (e) {
2176
+ this.isInitialized = false;
2177
+ throw e;
2147
2178
  }
2148
2179
  }
2149
2180
  exists(key, value) {
@@ -2521,9 +2552,12 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2521
2552
  commit(label) {
2522
2553
  let result = this.mvcc.commit(label);
2523
2554
  if (result.success) {
2524
- result = this.mvccRoot.commit(label);
2525
- if (result.success && this.rootTx !== this) {
2526
- this.rootTx.rootId = this.rootId;
2555
+ const isRootTx = this.rootTx !== this;
2556
+ if (isRootTx) {
2557
+ result = this.rootTx.commit(label);
2558
+ if (result.success) {
2559
+ this.rootTx.rootId = this.rootId;
2560
+ }
2527
2561
  }
2528
2562
  if (result.success) {
2529
2563
  for (const r of result.created) {
@@ -2606,7 +2640,7 @@ var BPTreeSync = class extends BPTreeSyncTransaction {
2606
2640
  this.comparator,
2607
2641
  this.option
2608
2642
  );
2609
- tx.init();
2643
+ tx._initInternal();
2610
2644
  return tx;
2611
2645
  }
2612
2646
  insert(key, value) {
@@ -2616,7 +2650,6 @@ var BPTreeSync = class extends BPTreeSyncTransaction {
2616
2650
  if (!result.success) {
2617
2651
  throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
2618
2652
  }
2619
- this.rootId = tx.getRootId();
2620
2653
  }
2621
2654
  delete(key, value) {
2622
2655
  const tx = this.createTransaction();
@@ -2625,244 +2658,512 @@ var BPTreeSync = class extends BPTreeSyncTransaction {
2625
2658
  if (!result.success) {
2626
2659
  throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
2627
2660
  }
2628
- this.rootId = tx.getRootId();
2629
2661
  }
2630
2662
  };
2631
2663
 
2632
- // src/transaction/BPTreeAsyncTransaction.ts
2633
- var BPTreeAsyncTransaction = class extends BPTreeTransaction {
2634
- constructor(rootTx, mvccRoot, mvcc, strategy, comparator, option) {
2635
- super(
2636
- rootTx,
2637
- mvccRoot,
2638
- mvcc,
2639
- strategy,
2640
- comparator,
2641
- option
2642
- );
2664
+ // node_modules/ryoiki/dist/esm/index.mjs
2665
+ var Ryoiki2 = class _Ryoiki2 {
2666
+ readings;
2667
+ writings;
2668
+ readQueue;
2669
+ writeQueue;
2670
+ static async CatchError(promise) {
2671
+ return await promise.then((v) => [void 0, v]).catch((err) => [err]);
2643
2672
  }
2644
- async getNode(id) {
2645
- if (this.nodes.has(id)) {
2646
- return this.nodes.get(id);
2673
+ static IsRangeOverlap(a, b) {
2674
+ const [start1, end1] = a;
2675
+ const [start2, end2] = b;
2676
+ if (end1 <= start2 || end2 <= start1) {
2677
+ return false;
2647
2678
  }
2648
- return await this.mvcc.read(id);
2679
+ return true;
2680
+ }
2681
+ static ERR_ALREADY_EXISTS(lockId) {
2682
+ return new Error(`The '${lockId}' task already existing in queue or running.`);
2683
+ }
2684
+ static ERR_NOT_EXISTS(lockId) {
2685
+ return new Error(`The '${lockId}' task not existing in task queue.`);
2686
+ }
2687
+ static ERR_TIMEOUT(lockId, timeout) {
2688
+ return new Error(`The task with ID '${lockId}' failed to acquire the lock within the timeout(${timeout}ms).`);
2649
2689
  }
2650
2690
  /**
2651
- * Create a new node with a unique ID.
2691
+ * Constructs a new instance of the Ryoiki class.
2652
2692
  */
2653
- async _createNode(leaf, keys, values, parent = null, next = null, prev = null) {
2654
- const id = await this.strategy.id(leaf);
2655
- const node = {
2656
- id,
2657
- keys,
2658
- values,
2659
- leaf,
2660
- parent,
2661
- next,
2662
- prev
2663
- };
2664
- await this.mvcc.create(id, node);
2665
- this.nodes.set(id, node);
2666
- return node;
2693
+ constructor() {
2694
+ this.readings = /* @__PURE__ */ new Map();
2695
+ this.writings = /* @__PURE__ */ new Map();
2696
+ this.readQueue = /* @__PURE__ */ new Map();
2697
+ this.writeQueue = /* @__PURE__ */ new Map();
2667
2698
  }
2668
- async _updateNode(node) {
2669
- await this.mvcc.write(node.id, node);
2670
- this.nodes.set(node.id, node);
2699
+ /**
2700
+ * Creates a range based on a start value and length.
2701
+ * @param start - The starting value of the range.
2702
+ * @param length - The length of the range.
2703
+ * @returns A range tuple [start, start + length].
2704
+ */
2705
+ range(start, length) {
2706
+ return [start, start + length];
2671
2707
  }
2672
- async _deleteNode(node) {
2673
- await this.mvcc.delete(node.id);
2674
- this.nodes.delete(node.id);
2708
+ rangeOverlapping(tasks, range) {
2709
+ return Array.from(tasks.values()).some((t) => _Ryoiki2.IsRangeOverlap(t.range, range));
2675
2710
  }
2676
- async _readHead() {
2677
- if (this.nodes.has("__HEAD__")) {
2678
- return this.nodes.get("__HEAD__") ?? null;
2679
- }
2680
- const head = await this.mvcc.read("__HEAD__");
2681
- return head ?? null;
2682
- }
2683
- async _writeHead(head) {
2684
- if (!await this.mvcc.exists("__HEAD__")) {
2685
- await this.mvcc.create("__HEAD__", head);
2686
- } else {
2687
- await this.mvcc.write("__HEAD__", head);
2688
- }
2689
- this.nodes.set("__HEAD__", head);
2690
- this.rootId = head.root;
2711
+ isSameRange(a, b) {
2712
+ const [a1, a2] = a;
2713
+ const [b1, b2] = b;
2714
+ return a1 === b1 && a2 === b2;
2691
2715
  }
2692
- async _insertAtLeaf(node, key, value) {
2693
- if (node.values.length) {
2694
- for (let i = 0, len = node.values.length; i < len; i++) {
2695
- const nValue = node.values[i];
2696
- if (this.comparator.isSame(value, nValue)) {
2697
- const keys = node.keys[i];
2698
- if (keys.includes(key)) {
2699
- break;
2700
- }
2701
- keys.push(key);
2702
- await this._updateNode(node);
2703
- return;
2704
- } else if (this.comparator.isLower(value, nValue)) {
2705
- node.values.splice(i, 0, value);
2706
- node.keys.splice(i, 0, [key]);
2707
- await this._updateNode(node);
2708
- return;
2709
- } else if (i + 1 === node.values.length) {
2710
- node.values.push(value);
2711
- node.keys.push([key]);
2712
- await this._updateNode(node);
2713
- return;
2714
- }
2716
+ fetchUnitAndRun(queue, workspaces) {
2717
+ for (const [id, unit] of queue) {
2718
+ if (!unit.condition()) {
2719
+ continue;
2715
2720
  }
2716
- } else {
2717
- node.values = [value];
2718
- node.keys = [[key]];
2719
- await this._updateNode(node);
2720
- return;
2721
+ this._alloc(queue, workspaces, id);
2721
2722
  }
2722
2723
  }
2723
- async _insertInParent(node, value, pointer) {
2724
- if (this.rootId === node.id) {
2725
- const root = await this._createNode(false, [node.id, pointer.id], [value]);
2726
- this.rootId = root.id;
2727
- node.parent = root.id;
2728
- pointer.parent = root.id;
2729
- if (pointer.leaf) {
2730
- node.next = pointer.id;
2731
- pointer.prev = node.id;
2732
- }
2733
- await this._writeHead({
2734
- root: root.id,
2735
- order: this.order,
2736
- data: this.strategy.head.data
2737
- });
2738
- await this._updateNode(node);
2739
- await this._updateNode(pointer);
2740
- return;
2741
- }
2742
- const parentNode = await this.getNode(node.parent);
2743
- const nodeIndex = parentNode.keys.indexOf(node.id);
2744
- if (nodeIndex === -1) {
2745
- throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
2746
- }
2747
- parentNode.values.splice(nodeIndex, 0, value);
2748
- parentNode.keys.splice(nodeIndex + 1, 0, pointer.id);
2749
- pointer.parent = parentNode.id;
2750
- if (pointer.leaf) {
2751
- const leftSibling = node;
2752
- const oldNextId = leftSibling.next;
2753
- pointer.prev = leftSibling.id;
2754
- pointer.next = oldNextId;
2755
- leftSibling.next = pointer.id;
2756
- await this._updateNode(leftSibling);
2757
- if (oldNextId) {
2758
- const oldNext = await this.getNode(oldNextId);
2759
- oldNext.prev = pointer.id;
2760
- await this._updateNode(oldNext);
2761
- }
2762
- }
2763
- await this._updateNode(parentNode);
2764
- await this._updateNode(pointer);
2765
- if (parentNode.keys.length > this.order) {
2766
- const parentPointer = await this._createNode(false, [], []);
2767
- parentPointer.parent = parentNode.parent;
2768
- const mid = Math.ceil(this.order / 2) - 1;
2769
- parentPointer.values = parentNode.values.slice(mid + 1);
2770
- parentPointer.keys = parentNode.keys.slice(mid + 1);
2771
- const midValue = parentNode.values[mid];
2772
- parentNode.values = parentNode.values.slice(0, mid);
2773
- parentNode.keys = parentNode.keys.slice(0, mid + 1);
2774
- for (const k of parentNode.keys) {
2775
- const n = await this.getNode(k);
2776
- n.parent = parentNode.id;
2777
- await this._updateNode(n);
2778
- }
2779
- for (const k of parentPointer.keys) {
2780
- const n = await this.getNode(k);
2781
- n.parent = parentPointer.id;
2782
- await this._updateNode(n);
2724
+ _handleOverload(args, handlers, argPatterns) {
2725
+ for (const [key, pattern] of Object.entries(argPatterns)) {
2726
+ if (this._matchArgs(args, pattern)) {
2727
+ return handlers[key](...args);
2783
2728
  }
2784
- await this._updateNode(parentNode);
2785
- await this._insertInParent(parentNode, midValue, parentPointer);
2786
2729
  }
2730
+ throw new Error("Invalid arguments");
2787
2731
  }
2788
- async insertableNode(value) {
2789
- let node = await this.getNode(this.rootId);
2790
- while (!node.leaf) {
2791
- const { index } = this._binarySearchValues(node.values, value, false, true);
2792
- node = await this.getNode(node.keys[index]);
2793
- }
2794
- return node;
2732
+ _matchArgs(args, pattern) {
2733
+ return args.every((arg, index) => {
2734
+ const expectedType = pattern[index];
2735
+ if (expectedType === void 0) return typeof arg === "undefined";
2736
+ if (expectedType === Function) return typeof arg === "function";
2737
+ if (expectedType === Number) return typeof arg === "number";
2738
+ if (expectedType === Array) return Array.isArray(arg);
2739
+ return false;
2740
+ });
2795
2741
  }
2796
- async insertableNodeByPrimary(value) {
2797
- let node = await this.getNode(this.rootId);
2798
- while (!node.leaf) {
2799
- const { index } = this._binarySearchValues(node.values, value, true, false);
2800
- node = await this.getNode(node.keys[index]);
2801
- }
2802
- return node;
2742
+ _createRandomId() {
2743
+ const timestamp = Date.now().toString(36);
2744
+ const random = Math.random().toString(36).substring(2);
2745
+ return `${timestamp}${random}`;
2803
2746
  }
2804
- async insertableRightestNodeByPrimary(value) {
2805
- let node = await this.getNode(this.rootId);
2806
- while (!node.leaf) {
2807
- const { index } = this._binarySearchValues(node.values, value, true, true);
2808
- node = await this.getNode(node.keys[index]);
2747
+ _alloc(queue, workspaces, lockId) {
2748
+ const unit = queue.get(lockId);
2749
+ if (!unit) {
2750
+ throw _Ryoiki2.ERR_NOT_EXISTS(lockId);
2809
2751
  }
2810
- return node;
2752
+ workspaces.set(lockId, unit);
2753
+ queue.delete(lockId);
2754
+ unit.alloc();
2811
2755
  }
2812
- async insertableRightestEndNodeByPrimary(value) {
2813
- const node = await this.insertableRightestNodeByPrimary(value);
2814
- if (!node.next) {
2815
- return null;
2756
+ _free(workspaces, lockId) {
2757
+ const unit = workspaces.get(lockId);
2758
+ if (!unit) {
2759
+ throw _Ryoiki2.ERR_NOT_EXISTS(lockId);
2816
2760
  }
2817
- return await this.getNode(node.next);
2761
+ workspaces.delete(lockId);
2762
+ unit.free();
2818
2763
  }
2819
- async insertableEndNode(value, direction) {
2820
- const insertableNode = await this.insertableNode(value);
2821
- let key;
2822
- switch (direction) {
2823
- case -1:
2824
- key = "prev";
2825
- break;
2826
- case 1:
2827
- key = "next";
2764
+ _lock(queue, range, timeout, task, condition) {
2765
+ return new Promise((resolve, reject) => {
2766
+ let timeoutId = null;
2767
+ if (timeout >= 0) {
2768
+ timeoutId = setTimeout(() => {
2769
+ reject(_Ryoiki2.ERR_TIMEOUT(id, timeout));
2770
+ }, timeout);
2771
+ }
2772
+ const id = this._createRandomId();
2773
+ const alloc = async () => {
2774
+ if (timeoutId !== null) {
2775
+ clearTimeout(timeoutId);
2776
+ }
2777
+ const [err, v] = await _Ryoiki2.CatchError(task(id));
2778
+ if (err) reject(err);
2779
+ else resolve(v);
2780
+ };
2781
+ const fetch = () => {
2782
+ this.fetchUnitAndRun(this.readQueue, this.readings);
2783
+ this.fetchUnitAndRun(this.writeQueue, this.writings);
2784
+ };
2785
+ queue.set(id, { id, range, condition, alloc, free: fetch });
2786
+ fetch();
2787
+ });
2788
+ }
2789
+ _checkWorking(range, workspaces) {
2790
+ let isLocked = false;
2791
+ for (const lock of workspaces.values()) {
2792
+ if (_Ryoiki2.IsRangeOverlap(range, lock.range)) {
2793
+ isLocked = true;
2828
2794
  break;
2829
- default:
2830
- throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
2831
- }
2832
- const guessNode = insertableNode[key];
2833
- if (!guessNode) {
2834
- return null;
2795
+ }
2835
2796
  }
2836
- return await this.getNode(guessNode);
2797
+ return isLocked;
2837
2798
  }
2838
- async leftestNode() {
2839
- let node = await this.getNode(this.rootId);
2840
- if (node === null) {
2841
- debugger;
2842
- }
2843
- while (!node.leaf) {
2844
- const keys = node.keys;
2845
- node = await this.getNode(keys[0]);
2846
- }
2847
- return node;
2799
+ /**
2800
+ * Checks if there is any active read lock within the specified range.
2801
+ * @param range The range to check for active read locks.
2802
+ * @returns `true` if there is an active read lock within the range, `false` otherwise.
2803
+ */
2804
+ isReading(range) {
2805
+ return this._checkWorking(range, this.readings);
2848
2806
  }
2849
- async rightestNode() {
2850
- let node = await this.getNode(this.rootId);
2851
- while (!node.leaf) {
2852
- const keys = node.keys;
2853
- node = await this.getNode(keys[keys.length - 1]);
2854
- }
2855
- return node;
2807
+ /**
2808
+ * Checks if there is any active write lock within the specified range.
2809
+ * @param range The range to check for active write locks.
2810
+ * @returns `true` if there is an active write lock within the range, `false` otherwise.
2811
+ */
2812
+ isWriting(range) {
2813
+ return this._checkWorking(range, this.writings);
2856
2814
  }
2857
- async *getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
2858
- let node = startNode;
2859
- let done = false;
2860
- let hasMatched = false;
2861
- let nextNodePromise = null;
2862
- while (!done) {
2863
- if (endNode && node.id === endNode.id) {
2864
- done = true;
2865
- break;
2815
+ /**
2816
+ * Checks if a read lock can be acquired within the specified range.
2817
+ * @param range The range to check for read lock availability.
2818
+ * @returns `true` if a read lock can be acquired, `false` otherwise.
2819
+ */
2820
+ canRead(range) {
2821
+ const writing = this.isWriting(range);
2822
+ return !writing;
2823
+ }
2824
+ /**
2825
+ * Checks if a write lock can be acquired within the specified range.
2826
+ * @param range The range to check for write lock availability.
2827
+ * @returns `true` if a write lock can be acquired, `false` otherwise.
2828
+ */
2829
+ canWrite(range) {
2830
+ const reading = this.isReading(range);
2831
+ const writing = this.isWriting(range);
2832
+ return !reading && !writing;
2833
+ }
2834
+ /**
2835
+ * Internal implementation of the read lock. Handles both overloads.
2836
+ * @template T - The return type of the task.
2837
+ * @param arg0 - Either a range or a task callback.
2838
+ * If a range is provided, the task is the second argument.
2839
+ * @param arg1 - The task to execute, required if a range is provided.
2840
+ * @param arg2 - The timeout for acquiring the lock.
2841
+ * If the lock cannot be acquired within this period, an error will be thrown.
2842
+ * If this value is not provided, no timeout will be set.
2843
+ * @returns A promise resolving to the result of the task execution.
2844
+ */
2845
+ readLock(arg0, arg1, arg2) {
2846
+ const [range, task, timeout] = this._handleOverload(
2847
+ [arg0, arg1, arg2],
2848
+ {
2849
+ rangeTask: (range2, task2) => [range2, task2, -1],
2850
+ rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
2851
+ task: (task2) => [[-Infinity, Infinity], task2, -1],
2852
+ taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
2853
+ },
2854
+ {
2855
+ task: [Function],
2856
+ taskTimeout: [Function, Number],
2857
+ rangeTask: [Array, Function],
2858
+ rangeTaskTimeout: [Array, Function, Number]
2859
+ }
2860
+ );
2861
+ return this._lock(
2862
+ this.readQueue,
2863
+ range,
2864
+ timeout,
2865
+ task,
2866
+ () => !this.rangeOverlapping(this.writings, range)
2867
+ );
2868
+ }
2869
+ /**
2870
+ * Internal implementation of the write lock. Handles both overloads.
2871
+ * @template T - The return type of the task.
2872
+ * @param arg0 - Either a range or a task callback.
2873
+ * If a range is provided, the task is the second argument.
2874
+ * @param arg1 - The task to execute, required if a range is provided.
2875
+ * @param arg2 - The timeout for acquiring the lock.
2876
+ * If the lock cannot be acquired within this period, an error will be thrown.
2877
+ * If this value is not provided, no timeout will be set.
2878
+ * @returns A promise resolving to the result of the task execution.
2879
+ */
2880
+ writeLock(arg0, arg1, arg2) {
2881
+ const [range, task, timeout] = this._handleOverload(
2882
+ [arg0, arg1, arg2],
2883
+ {
2884
+ rangeTask: (range2, task2) => [range2, task2, -1],
2885
+ rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
2886
+ task: (task2) => [[-Infinity, Infinity], task2, -1],
2887
+ taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
2888
+ },
2889
+ {
2890
+ task: [Function],
2891
+ taskTimeout: [Function, Number],
2892
+ rangeTask: [Array, Function],
2893
+ rangeTaskTimeout: [Array, Function, Number]
2894
+ }
2895
+ );
2896
+ return this._lock(
2897
+ this.writeQueue,
2898
+ range,
2899
+ timeout,
2900
+ task,
2901
+ () => {
2902
+ return !this.rangeOverlapping(this.writings, range) && !this.rangeOverlapping(this.readings, range);
2903
+ }
2904
+ );
2905
+ }
2906
+ /**
2907
+ * Releases a read lock by its lock ID.
2908
+ * @param lockId - The unique identifier for the lock to release.
2909
+ */
2910
+ readUnlock(lockId) {
2911
+ this._free(this.readings, lockId);
2912
+ }
2913
+ /**
2914
+ * Releases a write lock by its lock ID.
2915
+ * @param lockId - The unique identifier for the lock to release.
2916
+ */
2917
+ writeUnlock(lockId) {
2918
+ this._free(this.writings, lockId);
2919
+ }
2920
+ };
2921
+
2922
+ // src/transaction/BPTreeAsyncTransaction.ts
2923
+ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
2924
+ lock;
2925
+ constructor(rootTx, mvccRoot, mvcc, strategy, comparator, option) {
2926
+ super(
2927
+ rootTx,
2928
+ mvccRoot,
2929
+ mvcc,
2930
+ strategy,
2931
+ comparator,
2932
+ option
2933
+ );
2934
+ this.lock = new Ryoiki2();
2935
+ }
2936
+ async writeLock(id, fn) {
2937
+ let lockId;
2938
+ return this.lock.writeLock([id, id + 0.1], async (_lockId) => {
2939
+ lockId = _lockId;
2940
+ return fn();
2941
+ }).finally(() => {
2942
+ this.lock.writeUnlock(lockId);
2943
+ });
2944
+ }
2945
+ async getNode(id) {
2946
+ if (this.nodes.has(id)) {
2947
+ return this.nodes.get(id);
2948
+ }
2949
+ return await this.mvcc.read(id);
2950
+ }
2951
+ /**
2952
+ * Create a new node with a unique ID.
2953
+ */
2954
+ async _createNode(leaf, keys, values, parent = null, next = null, prev = null) {
2955
+ const id = await this.strategy.id(leaf);
2956
+ const node = {
2957
+ id,
2958
+ keys,
2959
+ values,
2960
+ leaf,
2961
+ parent,
2962
+ next,
2963
+ prev
2964
+ };
2965
+ await this.mvcc.create(id, node);
2966
+ this.nodes.set(id, node);
2967
+ return node;
2968
+ }
2969
+ async _updateNode(node) {
2970
+ await this.mvcc.write(node.id, node);
2971
+ this.nodes.set(node.id, node);
2972
+ }
2973
+ async _deleteNode(node) {
2974
+ await this.mvcc.delete(node.id);
2975
+ this.nodes.delete(node.id);
2976
+ }
2977
+ async _readHead() {
2978
+ if (this.nodes.has("__HEAD__")) {
2979
+ return this.nodes.get("__HEAD__") ?? null;
2980
+ }
2981
+ const head = await this.mvcc.read("__HEAD__");
2982
+ return head ?? null;
2983
+ }
2984
+ async _writeHead(head) {
2985
+ if (!await this.mvcc.exists("__HEAD__")) {
2986
+ await this.mvcc.create("__HEAD__", head);
2987
+ } else {
2988
+ await this.mvcc.write("__HEAD__", head);
2989
+ }
2990
+ this.nodes.set("__HEAD__", head);
2991
+ this.rootId = head.root;
2992
+ }
2993
+ async _insertAtLeaf(node, key, value) {
2994
+ if (node.values.length) {
2995
+ for (let i = 0, len = node.values.length; i < len; i++) {
2996
+ const nValue = node.values[i];
2997
+ if (this.comparator.isSame(value, nValue)) {
2998
+ const keys = node.keys[i];
2999
+ if (keys.includes(key)) {
3000
+ break;
3001
+ }
3002
+ keys.push(key);
3003
+ await this._updateNode(node);
3004
+ return;
3005
+ } else if (this.comparator.isLower(value, nValue)) {
3006
+ node.values.splice(i, 0, value);
3007
+ node.keys.splice(i, 0, [key]);
3008
+ await this._updateNode(node);
3009
+ return;
3010
+ } else if (i + 1 === node.values.length) {
3011
+ node.values.push(value);
3012
+ node.keys.push([key]);
3013
+ await this._updateNode(node);
3014
+ return;
3015
+ }
3016
+ }
3017
+ } else {
3018
+ node.values = [value];
3019
+ node.keys = [[key]];
3020
+ await this._updateNode(node);
3021
+ return;
3022
+ }
3023
+ }
3024
+ async _insertInParent(node, value, pointer) {
3025
+ if (this.rootId === node.id) {
3026
+ const root = await this._createNode(false, [node.id, pointer.id], [value]);
3027
+ this.rootId = root.id;
3028
+ node.parent = root.id;
3029
+ pointer.parent = root.id;
3030
+ if (pointer.leaf) {
3031
+ node.next = pointer.id;
3032
+ pointer.prev = node.id;
3033
+ }
3034
+ await this._writeHead({
3035
+ root: root.id,
3036
+ order: this.order,
3037
+ data: this.strategy.head.data
3038
+ });
3039
+ await this._updateNode(node);
3040
+ await this._updateNode(pointer);
3041
+ return;
3042
+ }
3043
+ const parentNode = await this.getNode(node.parent);
3044
+ const nodeIndex = parentNode.keys.indexOf(node.id);
3045
+ if (nodeIndex === -1) {
3046
+ throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
3047
+ }
3048
+ parentNode.values.splice(nodeIndex, 0, value);
3049
+ parentNode.keys.splice(nodeIndex + 1, 0, pointer.id);
3050
+ pointer.parent = parentNode.id;
3051
+ if (pointer.leaf) {
3052
+ const leftSibling = node;
3053
+ const oldNextId = leftSibling.next;
3054
+ pointer.prev = leftSibling.id;
3055
+ pointer.next = oldNextId;
3056
+ leftSibling.next = pointer.id;
3057
+ await this._updateNode(leftSibling);
3058
+ if (oldNextId) {
3059
+ const oldNext = await this.getNode(oldNextId);
3060
+ oldNext.prev = pointer.id;
3061
+ await this._updateNode(oldNext);
3062
+ }
3063
+ }
3064
+ await this._updateNode(parentNode);
3065
+ await this._updateNode(pointer);
3066
+ if (parentNode.keys.length > this.order) {
3067
+ const parentPointer = await this._createNode(false, [], []);
3068
+ parentPointer.parent = parentNode.parent;
3069
+ const mid = Math.ceil(this.order / 2) - 1;
3070
+ parentPointer.values = parentNode.values.slice(mid + 1);
3071
+ parentPointer.keys = parentNode.keys.slice(mid + 1);
3072
+ const midValue = parentNode.values[mid];
3073
+ parentNode.values = parentNode.values.slice(0, mid);
3074
+ parentNode.keys = parentNode.keys.slice(0, mid + 1);
3075
+ for (const k of parentNode.keys) {
3076
+ const n = await this.getNode(k);
3077
+ n.parent = parentNode.id;
3078
+ await this._updateNode(n);
3079
+ }
3080
+ for (const k of parentPointer.keys) {
3081
+ const n = await this.getNode(k);
3082
+ n.parent = parentPointer.id;
3083
+ await this._updateNode(n);
3084
+ }
3085
+ await this._updateNode(parentNode);
3086
+ await this._insertInParent(parentNode, midValue, parentPointer);
3087
+ }
3088
+ }
3089
+ async insertableNode(value) {
3090
+ let node = await this.getNode(this.rootId);
3091
+ while (!node.leaf) {
3092
+ const { index } = this._binarySearchValues(node.values, value, false, true);
3093
+ node = await this.getNode(node.keys[index]);
3094
+ }
3095
+ return node;
3096
+ }
3097
+ async insertableNodeByPrimary(value) {
3098
+ let node = await this.getNode(this.rootId);
3099
+ while (!node.leaf) {
3100
+ const { index } = this._binarySearchValues(node.values, value, true, false);
3101
+ node = await this.getNode(node.keys[index]);
3102
+ }
3103
+ return node;
3104
+ }
3105
+ async insertableRightestNodeByPrimary(value) {
3106
+ let node = await this.getNode(this.rootId);
3107
+ while (!node.leaf) {
3108
+ const { index } = this._binarySearchValues(node.values, value, true, true);
3109
+ node = await this.getNode(node.keys[index]);
3110
+ }
3111
+ return node;
3112
+ }
3113
+ async insertableRightestEndNodeByPrimary(value) {
3114
+ const node = await this.insertableRightestNodeByPrimary(value);
3115
+ if (!node.next) {
3116
+ return null;
3117
+ }
3118
+ return await this.getNode(node.next);
3119
+ }
3120
+ async insertableEndNode(value, direction) {
3121
+ const insertableNode = await this.insertableNode(value);
3122
+ let key;
3123
+ switch (direction) {
3124
+ case -1:
3125
+ key = "prev";
3126
+ break;
3127
+ case 1:
3128
+ key = "next";
3129
+ break;
3130
+ default:
3131
+ throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
3132
+ }
3133
+ const guessNode = insertableNode[key];
3134
+ if (!guessNode) {
3135
+ return null;
3136
+ }
3137
+ return await this.getNode(guessNode);
3138
+ }
3139
+ async leftestNode() {
3140
+ let node = await this.getNode(this.rootId);
3141
+ if (node === null) {
3142
+ debugger;
3143
+ }
3144
+ while (!node.leaf) {
3145
+ const keys = node.keys;
3146
+ node = await this.getNode(keys[0]);
3147
+ }
3148
+ return node;
3149
+ }
3150
+ async rightestNode() {
3151
+ let node = await this.getNode(this.rootId);
3152
+ while (!node.leaf) {
3153
+ const keys = node.keys;
3154
+ node = await this.getNode(keys[keys.length - 1]);
3155
+ }
3156
+ return node;
3157
+ }
3158
+ async *getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
3159
+ let node = startNode;
3160
+ let done = false;
3161
+ let hasMatched = false;
3162
+ let nextNodePromise = null;
3163
+ while (!done) {
3164
+ if (endNode && node.id === endNode.id) {
3165
+ done = true;
3166
+ break;
2866
3167
  }
2867
3168
  if (direction === 1) {
2868
3169
  if (node.next && !done) {
@@ -2918,28 +3219,46 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
2918
3219
  }
2919
3220
  }
2920
3221
  async init() {
2921
- this.clear();
2922
- const head = await this._readHead();
2923
- if (head === null) {
2924
- this.order = this.strategy.order;
2925
- const root = await this._createNode(true, [], []);
2926
- await this._writeHead({
2927
- root: root.id,
2928
- order: this.order,
2929
- data: this.strategy.head.data
2930
- });
2931
- } else {
2932
- const { root, order } = head;
2933
- this.strategy.head = head;
2934
- this.order = order;
2935
- await this._writeHead({
2936
- root,
2937
- order: this.order,
2938
- data: this.strategy.head.data
2939
- });
3222
+ if (this.rootTx !== this) {
3223
+ throw new Error("Cannot call init on a nested transaction");
2940
3224
  }
2941
- if (this.order < 3) {
2942
- throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
3225
+ return await this._initInternal();
3226
+ }
3227
+ async _initInternal() {
3228
+ if (this.isInitialized) {
3229
+ throw new Error("Transaction already initialized");
3230
+ }
3231
+ if (this.isDestroyed) {
3232
+ throw new Error("Transaction already destroyed");
3233
+ }
3234
+ this.isInitialized = true;
3235
+ try {
3236
+ this._clearCache();
3237
+ const head = await this._readHead();
3238
+ if (head === null) {
3239
+ this.order = this.strategy.order;
3240
+ const root = await this._createNode(true, [], []);
3241
+ await this._writeHead({
3242
+ root: root.id,
3243
+ order: this.order,
3244
+ data: this.strategy.head.data
3245
+ });
3246
+ } else {
3247
+ const { root, order } = head;
3248
+ this.strategy.head = head;
3249
+ this.order = order;
3250
+ await this._writeHead({
3251
+ root,
3252
+ order: this.order,
3253
+ data: this.strategy.head.data
3254
+ });
3255
+ }
3256
+ if (this.order < 3) {
3257
+ throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
3258
+ }
3259
+ } catch (e) {
3260
+ this.isInitialized = false;
3261
+ throw e;
2943
3262
  }
2944
3263
  }
2945
3264
  async exists(key, value) {
@@ -3039,38 +3358,40 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3039
3358
  }
3040
3359
  }
3041
3360
  async keys(condition, filterValues, order = "asc") {
3042
- const set = /* @__PURE__ */ new Set();
3043
- for await (const key of this.keysStream(condition, filterValues, void 0, order)) {
3044
- set.add(key);
3045
- }
3046
- return set;
3047
- }
3048
- async where(condition, order = "asc") {
3049
- const map = /* @__PURE__ */ new Map();
3050
- for await (const [key, value] of this.whereStream(condition, void 0, order)) {
3051
- map.set(key, value);
3052
- }
3053
- return map;
3054
- }
3055
- async insert(key, value) {
3056
- const before = await this.insertableNode(value);
3057
- await this._insertAtLeaf(before, key, value);
3058
- if (before.values.length === this.order) {
3059
- const after = await this._createNode(
3060
- true,
3061
- [],
3062
- [],
3063
- before.parent,
3064
- null,
3065
- null
3066
- );
3067
- const mid = Math.ceil(this.order / 2) - 1;
3068
- after.values = before.values.slice(mid + 1);
3069
- after.keys = before.keys.slice(mid + 1);
3070
- before.values = before.values.slice(0, mid + 1);
3071
- before.keys = before.keys.slice(0, mid + 1);
3072
- await this._insertInParent(before, after.values[0], after);
3361
+ const set = /* @__PURE__ */ new Set();
3362
+ for await (const key of this.keysStream(condition, filterValues, void 0, order)) {
3363
+ set.add(key);
3364
+ }
3365
+ return set;
3366
+ }
3367
+ async where(condition, order = "asc") {
3368
+ const map = /* @__PURE__ */ new Map();
3369
+ for await (const [key, value] of this.whereStream(condition, void 0, order)) {
3370
+ map.set(key, value);
3073
3371
  }
3372
+ return map;
3373
+ }
3374
+ async insert(key, value) {
3375
+ return this.writeLock(0, async () => {
3376
+ const before = await this.insertableNode(value);
3377
+ await this._insertAtLeaf(before, key, value);
3378
+ if (before.values.length === this.order) {
3379
+ const after = await this._createNode(
3380
+ true,
3381
+ [],
3382
+ [],
3383
+ before.parent,
3384
+ null,
3385
+ null
3386
+ );
3387
+ const mid = Math.ceil(this.order / 2) - 1;
3388
+ after.values = before.values.slice(mid + 1);
3389
+ after.keys = before.keys.slice(mid + 1);
3390
+ before.values = before.values.slice(0, mid + 1);
3391
+ before.keys = before.keys.slice(0, mid + 1);
3392
+ await this._insertInParent(before, after.values[0], after);
3393
+ }
3394
+ });
3074
3395
  }
3075
3396
  async _deleteEntry(node, key) {
3076
3397
  if (!node.leaf) {
@@ -3263,35 +3584,37 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3263
3584
  }
3264
3585
  }
3265
3586
  async delete(key, value) {
3266
- let node = await this.insertableNodeByPrimary(value);
3267
- let found = false;
3268
- while (true) {
3269
- let i = node.values.length;
3270
- while (i--) {
3271
- const nValue = node.values[i];
3272
- if (this.comparator.isSame(value, nValue)) {
3273
- const keys = node.keys[i];
3274
- const keyIndex = keys.indexOf(key);
3275
- if (keyIndex !== -1) {
3276
- keys.splice(keyIndex, 1);
3277
- if (keys.length === 0) {
3278
- node.keys.splice(i, 1);
3279
- node.values.splice(i, 1);
3587
+ return this.writeLock(0, async () => {
3588
+ let node = await this.insertableNodeByPrimary(value);
3589
+ let found = false;
3590
+ while (true) {
3591
+ let i = node.values.length;
3592
+ while (i--) {
3593
+ const nValue = node.values[i];
3594
+ if (this.comparator.isSame(value, nValue)) {
3595
+ const keys = node.keys[i];
3596
+ const keyIndex = keys.indexOf(key);
3597
+ if (keyIndex !== -1) {
3598
+ keys.splice(keyIndex, 1);
3599
+ if (keys.length === 0) {
3600
+ node.keys.splice(i, 1);
3601
+ node.values.splice(i, 1);
3602
+ }
3603
+ await this._updateNode(node);
3604
+ await this._deleteEntry(node, key);
3605
+ found = true;
3606
+ break;
3280
3607
  }
3281
- await this._updateNode(node);
3282
- await this._deleteEntry(node, key);
3283
- found = true;
3284
- break;
3285
3608
  }
3286
3609
  }
3610
+ if (found) break;
3611
+ if (node.next) {
3612
+ node = await this.getNode(node.next);
3613
+ continue;
3614
+ }
3615
+ break;
3287
3616
  }
3288
- if (found) break;
3289
- if (node.next) {
3290
- node = await this.getNode(node.next);
3291
- continue;
3292
- }
3293
- break;
3294
- }
3617
+ });
3295
3618
  }
3296
3619
  async getHeadData() {
3297
3620
  const head = await this._readHead();
@@ -3314,9 +3637,12 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3314
3637
  async commit(label) {
3315
3638
  let result = await this.mvcc.commit(label);
3316
3639
  if (result.success) {
3317
- result = await this.mvccRoot.commit(label);
3318
- if (result.success && this.rootTx !== this) {
3319
- this.rootTx.rootId = this.rootId;
3640
+ const isRootTx = this.rootTx === this;
3641
+ if (!isRootTx) {
3642
+ result = await this.rootTx.commit(label);
3643
+ if (result.success) {
3644
+ this.rootTx.rootId = this.rootId;
3645
+ }
3320
3646
  }
3321
3647
  if (result.success) {
3322
3648
  for (const r of result.created) {
@@ -3352,397 +3678,141 @@ var BPTreeMVCCStrategyAsync = class extends AsyncMVCCStrategy {
3352
3678
  async write(key, value) {
3353
3679
  if (key === "__HEAD__") {
3354
3680
  await this.strategy.writeHead(value);
3355
- } else {
3356
- await this.strategy.write(key, value);
3357
- }
3358
- }
3359
- async delete(key) {
3360
- await this.strategy.delete(key);
3361
- }
3362
- async exists(key) {
3363
- if (key === "__HEAD__") {
3364
- return await this.strategy.readHead() !== null;
3365
- }
3366
- try {
3367
- const node = await this.strategy.read(key);
3368
- return node !== null && node !== void 0;
3369
- } catch {
3370
- return false;
3371
- }
3372
- }
3373
- };
3374
-
3375
- // src/BPTreeAsync.ts
3376
- var BPTreeAsync = class extends BPTreeAsyncTransaction {
3377
- constructor(strategy, comparator, option) {
3378
- const mvccRoot = new AsyncMVCCTransaction(new BPTreeMVCCStrategyAsync(strategy));
3379
- super(
3380
- null,
3381
- mvccRoot,
3382
- mvccRoot,
3383
- strategy,
3384
- comparator,
3385
- option
3386
- );
3387
- }
3388
- /**
3389
- * Creates a new asynchronous transaction.
3390
- * @returns A new BPTreeAsyncTransaction.
3391
- */
3392
- async createTransaction() {
3393
- const nestedTx = await this.mvcc.createNested();
3394
- const tx = new BPTreeAsyncTransaction(
3395
- this,
3396
- this.mvcc,
3397
- nestedTx,
3398
- this.strategy,
3399
- this.comparator,
3400
- this.option
3401
- );
3402
- await tx.init();
3403
- return tx;
3404
- }
3405
- async insert(key, value) {
3406
- const tx = await this.createTransaction();
3407
- await tx.insert(key, value);
3408
- const result = await tx.commit();
3409
- if (!result.success) {
3410
- throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
3411
- }
3412
- this.rootId = tx.getRootId();
3413
- }
3414
- async delete(key, value) {
3415
- const tx = await this.createTransaction();
3416
- await tx.delete(key, value);
3417
- const result = await tx.commit();
3418
- if (!result.success) {
3419
- throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
3420
- }
3421
- this.rootId = tx.getRootId();
3422
- }
3423
- };
3424
-
3425
- // src/base/SerializeStrategy.ts
3426
- var SerializeStrategy = class {
3427
- order;
3428
- head;
3429
- constructor(order) {
3430
- this.order = order;
3431
- this.head = {
3432
- order,
3433
- root: null,
3434
- data: {}
3435
- };
3436
- }
3437
- };
3438
-
3439
- // src/SerializeStrategySync.ts
3440
- var SerializeStrategySync = class extends SerializeStrategy {
3441
- getHeadData(key, defaultValue) {
3442
- if (!Object.hasOwn(this.head.data, key)) {
3443
- this.setHeadData(key, defaultValue);
3444
- }
3445
- return this.head.data[key];
3446
- }
3447
- setHeadData(key, data) {
3448
- this.head.data[key] = data;
3449
- this.writeHead(this.head);
3450
- }
3451
- autoIncrement(key, defaultValue) {
3452
- const current = this.getHeadData(key, defaultValue);
3453
- const next = current + 1;
3454
- this.setHeadData(key, next);
3455
- return current;
3456
- }
3457
- };
3458
- var InMemoryStoreStrategySync = class extends SerializeStrategySync {
3459
- node;
3460
- constructor(order) {
3461
- super(order);
3462
- this.node = {};
3463
- }
3464
- id(isLeaf) {
3465
- return this.autoIncrement("index", 1).toString();
3466
- }
3467
- read(id) {
3468
- if (!Object.hasOwn(this.node, id)) {
3469
- throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
3470
- }
3471
- const node = this.node[id];
3472
- return JSON.parse(JSON.stringify(node));
3473
- }
3474
- write(id, node) {
3475
- this.node[id] = node;
3476
- }
3477
- delete(id) {
3478
- delete this.node[id];
3479
- }
3480
- readHead() {
3481
- if (this.head.root === null) {
3482
- return null;
3483
- }
3484
- return this.head;
3485
- }
3486
- writeHead(head) {
3487
- this.head = head;
3488
- }
3489
- };
3490
-
3491
- // node_modules/ryoiki/dist/esm/index.mjs
3492
- var Ryoiki2 = class _Ryoiki2 {
3493
- readings;
3494
- writings;
3495
- readQueue;
3496
- writeQueue;
3497
- static async CatchError(promise) {
3498
- return await promise.then((v) => [void 0, v]).catch((err) => [err]);
3499
- }
3500
- static IsRangeOverlap(a, b) {
3501
- const [start1, end1] = a;
3502
- const [start2, end2] = b;
3503
- if (end1 <= start2 || end2 <= start1) {
3504
- return false;
3505
- }
3506
- return true;
3507
- }
3508
- static ERR_ALREADY_EXISTS(lockId) {
3509
- return new Error(`The '${lockId}' task already existing in queue or running.`);
3510
- }
3511
- static ERR_NOT_EXISTS(lockId) {
3512
- return new Error(`The '${lockId}' task not existing in task queue.`);
3513
- }
3514
- static ERR_TIMEOUT(lockId, timeout) {
3515
- return new Error(`The task with ID '${lockId}' failed to acquire the lock within the timeout(${timeout}ms).`);
3516
- }
3517
- /**
3518
- * Constructs a new instance of the Ryoiki class.
3519
- */
3520
- constructor() {
3521
- this.readings = /* @__PURE__ */ new Map();
3522
- this.writings = /* @__PURE__ */ new Map();
3523
- this.readQueue = /* @__PURE__ */ new Map();
3524
- this.writeQueue = /* @__PURE__ */ new Map();
3525
- }
3526
- /**
3527
- * Creates a range based on a start value and length.
3528
- * @param start - The starting value of the range.
3529
- * @param length - The length of the range.
3530
- * @returns A range tuple [start, start + length].
3531
- */
3532
- range(start, length) {
3533
- return [start, start + length];
3534
- }
3535
- rangeOverlapping(tasks, range) {
3536
- return Array.from(tasks.values()).some((t) => _Ryoiki2.IsRangeOverlap(t.range, range));
3537
- }
3538
- isSameRange(a, b) {
3539
- const [a1, a2] = a;
3540
- const [b1, b2] = b;
3541
- return a1 === b1 && a2 === b2;
3542
- }
3543
- fetchUnitAndRun(queue, workspaces) {
3544
- for (const [id, unit] of queue) {
3545
- if (!unit.condition()) {
3546
- continue;
3547
- }
3548
- this._alloc(queue, workspaces, id);
3549
- }
3550
- }
3551
- _handleOverload(args, handlers, argPatterns) {
3552
- for (const [key, pattern] of Object.entries(argPatterns)) {
3553
- if (this._matchArgs(args, pattern)) {
3554
- return handlers[key](...args);
3555
- }
3556
- }
3557
- throw new Error("Invalid arguments");
3558
- }
3559
- _matchArgs(args, pattern) {
3560
- return args.every((arg, index) => {
3561
- const expectedType = pattern[index];
3562
- if (expectedType === void 0) return typeof arg === "undefined";
3563
- if (expectedType === Function) return typeof arg === "function";
3564
- if (expectedType === Number) return typeof arg === "number";
3565
- if (expectedType === Array) return Array.isArray(arg);
3566
- return false;
3567
- });
3568
- }
3569
- _createRandomId() {
3570
- const timestamp = Date.now().toString(36);
3571
- const random = Math.random().toString(36).substring(2);
3572
- return `${timestamp}${random}`;
3573
- }
3574
- _alloc(queue, workspaces, lockId) {
3575
- const unit = queue.get(lockId);
3576
- if (!unit) {
3577
- throw _Ryoiki2.ERR_NOT_EXISTS(lockId);
3681
+ } else {
3682
+ await this.strategy.write(key, value);
3578
3683
  }
3579
- workspaces.set(lockId, unit);
3580
- queue.delete(lockId);
3581
- unit.alloc();
3582
3684
  }
3583
- _free(workspaces, lockId) {
3584
- const unit = workspaces.get(lockId);
3585
- if (!unit) {
3586
- throw _Ryoiki2.ERR_NOT_EXISTS(lockId);
3685
+ async delete(key) {
3686
+ await this.strategy.delete(key);
3687
+ }
3688
+ async exists(key) {
3689
+ if (key === "__HEAD__") {
3690
+ return await this.strategy.readHead() !== null;
3691
+ }
3692
+ try {
3693
+ const node = await this.strategy.read(key);
3694
+ return node !== null && node !== void 0;
3695
+ } catch {
3696
+ return false;
3587
3697
  }
3588
- workspaces.delete(lockId);
3589
- unit.free();
3590
3698
  }
3591
- _lock(queue, range, timeout, task, condition) {
3592
- return new Promise((resolve, reject) => {
3593
- let timeoutId = null;
3594
- if (timeout >= 0) {
3595
- timeoutId = setTimeout(() => {
3596
- reject(_Ryoiki2.ERR_TIMEOUT(id, timeout));
3597
- }, timeout);
3699
+ };
3700
+
3701
+ // src/BPTreeAsync.ts
3702
+ var BPTreeAsync = class extends BPTreeAsyncTransaction {
3703
+ constructor(strategy, comparator, option) {
3704
+ const mvccRoot = new AsyncMVCCTransaction(new BPTreeMVCCStrategyAsync(strategy));
3705
+ super(
3706
+ null,
3707
+ mvccRoot,
3708
+ mvccRoot,
3709
+ strategy,
3710
+ comparator,
3711
+ option
3712
+ );
3713
+ }
3714
+ /**
3715
+ * Creates a new asynchronous transaction.
3716
+ * @returns A new BPTreeAsyncTransaction.
3717
+ */
3718
+ async createTransaction() {
3719
+ const nestedTx = this.mvcc.createNested();
3720
+ const tx = new BPTreeAsyncTransaction(
3721
+ this,
3722
+ this.mvcc,
3723
+ nestedTx,
3724
+ this.strategy,
3725
+ this.comparator,
3726
+ this.option
3727
+ );
3728
+ await tx._initInternal();
3729
+ return tx;
3730
+ }
3731
+ async insert(key, value) {
3732
+ return this.writeLock(1, async () => {
3733
+ const tx = await this.createTransaction();
3734
+ await tx.insert(key, value);
3735
+ const result = await tx.commit();
3736
+ if (!result.success) {
3737
+ throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
3598
3738
  }
3599
- const id = this._createRandomId();
3600
- const alloc = async () => {
3601
- if (timeoutId !== null) {
3602
- clearTimeout(timeoutId);
3603
- }
3604
- const [err, v] = await _Ryoiki2.CatchError(task(id));
3605
- if (err) reject(err);
3606
- else resolve(v);
3607
- };
3608
- const fetch = () => {
3609
- this.fetchUnitAndRun(this.readQueue, this.readings);
3610
- this.fetchUnitAndRun(this.writeQueue, this.writings);
3611
- };
3612
- queue.set(id, { id, range, condition, alloc, free: fetch });
3613
- fetch();
3614
3739
  });
3615
3740
  }
3616
- _checkWorking(range, workspaces) {
3617
- let isLocked = false;
3618
- for (const lock of workspaces.values()) {
3619
- if (_Ryoiki2.IsRangeOverlap(range, lock.range)) {
3620
- isLocked = true;
3621
- break;
3741
+ async delete(key, value) {
3742
+ return this.writeLock(1, async () => {
3743
+ const tx = await this.createTransaction();
3744
+ await tx.delete(key, value);
3745
+ const result = await tx.commit();
3746
+ if (!result.success) {
3747
+ throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
3622
3748
  }
3749
+ });
3750
+ }
3751
+ };
3752
+
3753
+ // src/base/SerializeStrategy.ts
3754
+ var SerializeStrategy = class {
3755
+ order;
3756
+ head;
3757
+ constructor(order) {
3758
+ this.order = order;
3759
+ this.head = {
3760
+ order,
3761
+ root: null,
3762
+ data: {}
3763
+ };
3764
+ }
3765
+ };
3766
+
3767
+ // src/SerializeStrategySync.ts
3768
+ var SerializeStrategySync = class extends SerializeStrategy {
3769
+ getHeadData(key, defaultValue) {
3770
+ if (!Object.hasOwn(this.head.data, key)) {
3771
+ this.setHeadData(key, defaultValue);
3623
3772
  }
3624
- return isLocked;
3773
+ return this.head.data[key];
3625
3774
  }
3626
- /**
3627
- * Checks if there is any active read lock within the specified range.
3628
- * @param range The range to check for active read locks.
3629
- * @returns `true` if there is an active read lock within the range, `false` otherwise.
3630
- */
3631
- isReading(range) {
3632
- return this._checkWorking(range, this.readings);
3775
+ setHeadData(key, data) {
3776
+ this.head.data[key] = data;
3777
+ this.writeHead(this.head);
3633
3778
  }
3634
- /**
3635
- * Checks if there is any active write lock within the specified range.
3636
- * @param range The range to check for active write locks.
3637
- * @returns `true` if there is an active write lock within the range, `false` otherwise.
3638
- */
3639
- isWriting(range) {
3640
- return this._checkWorking(range, this.writings);
3779
+ autoIncrement(key, defaultValue) {
3780
+ const current = this.getHeadData(key, defaultValue);
3781
+ const next = current + 1;
3782
+ this.setHeadData(key, next);
3783
+ return current;
3641
3784
  }
3642
- /**
3643
- * Checks if a read lock can be acquired within the specified range.
3644
- * @param range The range to check for read lock availability.
3645
- * @returns `true` if a read lock can be acquired, `false` otherwise.
3646
- */
3647
- canRead(range) {
3648
- const writing = this.isWriting(range);
3649
- return !writing;
3785
+ };
3786
+ var InMemoryStoreStrategySync = class extends SerializeStrategySync {
3787
+ node;
3788
+ constructor(order) {
3789
+ super(order);
3790
+ this.node = {};
3650
3791
  }
3651
- /**
3652
- * Checks if a write lock can be acquired within the specified range.
3653
- * @param range The range to check for write lock availability.
3654
- * @returns `true` if a write lock can be acquired, `false` otherwise.
3655
- */
3656
- canWrite(range) {
3657
- const reading = this.isReading(range);
3658
- const writing = this.isWriting(range);
3659
- return !reading && !writing;
3792
+ id(isLeaf) {
3793
+ return this.autoIncrement("index", 1).toString();
3660
3794
  }
3661
- /**
3662
- * Internal implementation of the read lock. Handles both overloads.
3663
- * @template T - The return type of the task.
3664
- * @param arg0 - Either a range or a task callback.
3665
- * If a range is provided, the task is the second argument.
3666
- * @param arg1 - The task to execute, required if a range is provided.
3667
- * @param arg2 - The timeout for acquiring the lock.
3668
- * If the lock cannot be acquired within this period, an error will be thrown.
3669
- * If this value is not provided, no timeout will be set.
3670
- * @returns A promise resolving to the result of the task execution.
3671
- */
3672
- readLock(arg0, arg1, arg2) {
3673
- const [range, task, timeout] = this._handleOverload(
3674
- [arg0, arg1, arg2],
3675
- {
3676
- rangeTask: (range2, task2) => [range2, task2, -1],
3677
- rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
3678
- task: (task2) => [[-Infinity, Infinity], task2, -1],
3679
- taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
3680
- },
3681
- {
3682
- task: [Function],
3683
- taskTimeout: [Function, Number],
3684
- rangeTask: [Array, Function],
3685
- rangeTaskTimeout: [Array, Function, Number]
3686
- }
3687
- );
3688
- return this._lock(
3689
- this.readQueue,
3690
- range,
3691
- timeout,
3692
- task,
3693
- () => !this.rangeOverlapping(this.writings, range)
3694
- );
3795
+ read(id) {
3796
+ if (!Object.hasOwn(this.node, id)) {
3797
+ throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
3798
+ }
3799
+ const node = this.node[id];
3800
+ return JSON.parse(JSON.stringify(node));
3695
3801
  }
3696
- /**
3697
- * Internal implementation of the write lock. Handles both overloads.
3698
- * @template T - The return type of the task.
3699
- * @param arg0 - Either a range or a task callback.
3700
- * If a range is provided, the task is the second argument.
3701
- * @param arg1 - The task to execute, required if a range is provided.
3702
- * @param arg2 - The timeout for acquiring the lock.
3703
- * If the lock cannot be acquired within this period, an error will be thrown.
3704
- * If this value is not provided, no timeout will be set.
3705
- * @returns A promise resolving to the result of the task execution.
3706
- */
3707
- writeLock(arg0, arg1, arg2) {
3708
- const [range, task, timeout] = this._handleOverload(
3709
- [arg0, arg1, arg2],
3710
- {
3711
- rangeTask: (range2, task2) => [range2, task2, -1],
3712
- rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
3713
- task: (task2) => [[-Infinity, Infinity], task2, -1],
3714
- taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
3715
- },
3716
- {
3717
- task: [Function],
3718
- taskTimeout: [Function, Number],
3719
- rangeTask: [Array, Function],
3720
- rangeTaskTimeout: [Array, Function, Number]
3721
- }
3722
- );
3723
- return this._lock(
3724
- this.writeQueue,
3725
- range,
3726
- timeout,
3727
- task,
3728
- () => {
3729
- return !this.rangeOverlapping(this.writings, range) && !this.rangeOverlapping(this.readings, range);
3730
- }
3731
- );
3802
+ write(id, node) {
3803
+ this.node[id] = node;
3732
3804
  }
3733
- /**
3734
- * Releases a read lock by its lock ID.
3735
- * @param lockId - The unique identifier for the lock to release.
3736
- */
3737
- readUnlock(lockId) {
3738
- this._free(this.readings, lockId);
3805
+ delete(id) {
3806
+ delete this.node[id];
3739
3807
  }
3740
- /**
3741
- * Releases a write lock by its lock ID.
3742
- * @param lockId - The unique identifier for the lock to release.
3743
- */
3744
- writeUnlock(lockId) {
3745
- this._free(this.writings, lockId);
3808
+ readHead() {
3809
+ if (this.head.root === null) {
3810
+ return null;
3811
+ }
3812
+ return this.head;
3813
+ }
3814
+ writeHead(head) {
3815
+ this.head = head;
3746
3816
  }
3747
3817
  };
3748
3818