serializable-bptree 8.1.6 → 8.1.7

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.
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  This is a B+tree that's totally okay with duplicate values. If you need to keep track of the B+ tree's state, don't just leave it in memory - make sure you write it down.
8
8
 
9
9
  ```typescript
10
- import { readFileSync, writeFileSync, unlinkSync, existsSync } from 'fs'
10
+ import { readFileSync, writeFileSync, unlinkSync, existsSync } from 'node:fs'
11
11
  import {
12
12
  BPTreeSync,
13
13
  SerializeStrategySync,
@@ -91,6 +91,8 @@ Additionally, this library supports asynchronous operations and rule-based query
91
91
 
92
92
  ```bash
93
93
  npm i serializable-bptree
94
+ # or
95
+ npx jsr add @izure/serializable-bptree
94
96
  ```
95
97
 
96
98
  ```typescript
@@ -343,6 +343,30 @@ var MVCCTransaction = class {
343
343
  deleted
344
344
  };
345
345
  }
346
+ /**
347
+ * Checks for conflicts among multiple transactions.
348
+ * A conflict occurs if two or more transactions modify (write or delete) the same key.
349
+ * @param transactions Array of transactions to check.
350
+ * @returns An array of keys that are in conflict.
351
+ */
352
+ static CheckConflicts(transactions) {
353
+ const modifiedKeys = /* @__PURE__ */ new Map();
354
+ const conflicts = /* @__PURE__ */ new Set();
355
+ for (const tx of transactions) {
356
+ const txModified = /* @__PURE__ */ new Set([
357
+ ...tx.writeBuffer.keys(),
358
+ ...tx.deleteBuffer
359
+ ]);
360
+ for (const key of txModified) {
361
+ const count = modifiedKeys.get(key) ?? 0;
362
+ if (count > 0) {
363
+ conflicts.add(key);
364
+ }
365
+ modifiedKeys.set(key, count + 1);
366
+ }
367
+ }
368
+ return Array.from(conflicts);
369
+ }
346
370
  /**
347
371
  * Cleans up both deletedCache and versionIndex based on minActiveVersion.
348
372
  * Root transactions call this after commit to reclaim memory.
@@ -1632,6 +1656,15 @@ var BPTreeTransaction = class _BPTreeTransaction {
1632
1656
  }
1633
1657
  return best;
1634
1658
  }
1659
+ /**
1660
+ * Checks for conflicts between multiple transactions.
1661
+ *
1662
+ * @param transactions Array of BPTreeTransaction instances to check
1663
+ * @returns An array of keys that are in conflict. Empty array if no conflicts.
1664
+ */
1665
+ static CheckConflicts(transactions) {
1666
+ return MVCCTransaction.CheckConflicts(transactions.map((tx) => tx.mvcc));
1667
+ }
1635
1668
  /**
1636
1669
  * Returns the ID of the root node.
1637
1670
  * @returns The root node ID.
@@ -2084,11 +2117,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2084
2117
  const { root, order } = head;
2085
2118
  this.strategy.head = head;
2086
2119
  this.order = order;
2087
- this._writeHead({
2088
- root,
2089
- order: this.order,
2090
- data: this.strategy.head.data
2091
- });
2120
+ this.rootId = root;
2092
2121
  }
2093
2122
  if (this.order < 3) {
2094
2123
  throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
@@ -2414,6 +2443,12 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2414
2443
  return node;
2415
2444
  }
2416
2445
  delete(key, value) {
2446
+ if (value === void 0) {
2447
+ value = this.get(key);
2448
+ }
2449
+ if (value === void 0) {
2450
+ return;
2451
+ }
2417
2452
  let node = this.insertableNodeByPrimary(value);
2418
2453
  let found = false;
2419
2454
  while (true) {
@@ -2865,14 +2900,6 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
2865
2900
  next,
2866
2901
  prev
2867
2902
  };
2868
- const head = await this._readHead();
2869
- if (head) {
2870
- await this._writeHead({
2871
- root: head.root,
2872
- order: head.order,
2873
- data: this.strategy.head.data
2874
- });
2875
- }
2876
2903
  await this.mvcc.create(id, node);
2877
2904
  return node;
2878
2905
  }
@@ -3165,11 +3192,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3165
3192
  const { root, order } = head;
3166
3193
  this.strategy.head = head;
3167
3194
  this.order = order;
3168
- await this._writeHead({
3169
- root,
3170
- order: this.order,
3171
- data: this.strategy.head.data
3172
- });
3195
+ this.rootId = root;
3173
3196
  }
3174
3197
  if (this.order < 3) {
3175
3198
  throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
@@ -3498,6 +3521,12 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3498
3521
  }
3499
3522
  async delete(key, value) {
3500
3523
  return this.writeLock(0, async () => {
3524
+ if (value === void 0) {
3525
+ value = await this.get(key);
3526
+ }
3527
+ if (value === void 0) {
3528
+ return;
3529
+ }
3501
3530
  let node = await this.insertableNodeByPrimary(value);
3502
3531
  let found = false;
3503
3532
  while (true) {
@@ -307,6 +307,30 @@ var MVCCTransaction = class {
307
307
  deleted
308
308
  };
309
309
  }
310
+ /**
311
+ * Checks for conflicts among multiple transactions.
312
+ * A conflict occurs if two or more transactions modify (write or delete) the same key.
313
+ * @param transactions Array of transactions to check.
314
+ * @returns An array of keys that are in conflict.
315
+ */
316
+ static CheckConflicts(transactions) {
317
+ const modifiedKeys = /* @__PURE__ */ new Map();
318
+ const conflicts = /* @__PURE__ */ new Set();
319
+ for (const tx of transactions) {
320
+ const txModified = /* @__PURE__ */ new Set([
321
+ ...tx.writeBuffer.keys(),
322
+ ...tx.deleteBuffer
323
+ ]);
324
+ for (const key of txModified) {
325
+ const count = modifiedKeys.get(key) ?? 0;
326
+ if (count > 0) {
327
+ conflicts.add(key);
328
+ }
329
+ modifiedKeys.set(key, count + 1);
330
+ }
331
+ }
332
+ return Array.from(conflicts);
333
+ }
310
334
  /**
311
335
  * Cleans up both deletedCache and versionIndex based on minActiveVersion.
312
336
  * Root transactions call this after commit to reclaim memory.
@@ -1596,6 +1620,15 @@ var BPTreeTransaction = class _BPTreeTransaction {
1596
1620
  }
1597
1621
  return best;
1598
1622
  }
1623
+ /**
1624
+ * Checks for conflicts between multiple transactions.
1625
+ *
1626
+ * @param transactions Array of BPTreeTransaction instances to check
1627
+ * @returns An array of keys that are in conflict. Empty array if no conflicts.
1628
+ */
1629
+ static CheckConflicts(transactions) {
1630
+ return MVCCTransaction.CheckConflicts(transactions.map((tx) => tx.mvcc));
1631
+ }
1599
1632
  /**
1600
1633
  * Returns the ID of the root node.
1601
1634
  * @returns The root node ID.
@@ -2048,11 +2081,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2048
2081
  const { root, order } = head;
2049
2082
  this.strategy.head = head;
2050
2083
  this.order = order;
2051
- this._writeHead({
2052
- root,
2053
- order: this.order,
2054
- data: this.strategy.head.data
2055
- });
2084
+ this.rootId = root;
2056
2085
  }
2057
2086
  if (this.order < 3) {
2058
2087
  throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
@@ -2378,6 +2407,12 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2378
2407
  return node;
2379
2408
  }
2380
2409
  delete(key, value) {
2410
+ if (value === void 0) {
2411
+ value = this.get(key);
2412
+ }
2413
+ if (value === void 0) {
2414
+ return;
2415
+ }
2381
2416
  let node = this.insertableNodeByPrimary(value);
2382
2417
  let found = false;
2383
2418
  while (true) {
@@ -2829,14 +2864,6 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
2829
2864
  next,
2830
2865
  prev
2831
2866
  };
2832
- const head = await this._readHead();
2833
- if (head) {
2834
- await this._writeHead({
2835
- root: head.root,
2836
- order: head.order,
2837
- data: this.strategy.head.data
2838
- });
2839
- }
2840
2867
  await this.mvcc.create(id, node);
2841
2868
  return node;
2842
2869
  }
@@ -3129,11 +3156,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3129
3156
  const { root, order } = head;
3130
3157
  this.strategy.head = head;
3131
3158
  this.order = order;
3132
- await this._writeHead({
3133
- root,
3134
- order: this.order,
3135
- data: this.strategy.head.data
3136
- });
3159
+ this.rootId = root;
3137
3160
  }
3138
3161
  if (this.order < 3) {
3139
3162
  throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
@@ -3462,6 +3485,12 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3462
3485
  }
3463
3486
  async delete(key, value) {
3464
3487
  return this.writeLock(0, async () => {
3488
+ if (value === void 0) {
3489
+ value = await this.get(key);
3490
+ }
3491
+ if (value === void 0) {
3492
+ return;
3493
+ }
3465
3494
  let node = await this.insertableNodeByPrimary(value);
3466
3495
  let found = false;
3467
3496
  while (true) {
@@ -10,5 +10,5 @@ export declare class BPTreeAsync<K, V> extends BPTreeAsyncTransaction<K, V> {
10
10
  */
11
11
  createTransaction(): Promise<BPTreeAsyncTransaction<K, V>>;
12
12
  insert(key: K, value: V): Promise<void>;
13
- delete(key: K, value: V): Promise<void>;
13
+ delete(key: K, value?: V): Promise<void>;
14
14
  }
@@ -10,5 +10,5 @@ export declare class BPTreeSync<K, V> extends BPTreeSyncTransaction<K, V> {
10
10
  */
11
11
  createTransaction(): BPTreeSyncTransaction<K, V>;
12
12
  insert(key: K, value: V): void;
13
- delete(key: K, value: V): void;
13
+ delete(key: K, value?: V): void;
14
14
  }
@@ -55,6 +55,13 @@ export declare abstract class BPTreeTransaction<K, V> {
55
55
  tree: T;
56
56
  condition: BPTreeCondition<unknown>;
57
57
  } | null;
58
+ /**
59
+ * Checks for conflicts between multiple transactions.
60
+ *
61
+ * @param transactions Array of BPTreeTransaction instances to check
62
+ * @returns An array of keys that are in conflict. Empty array if no conflicts.
63
+ */
64
+ static CheckConflicts<K, V>(transactions: BPTreeTransaction<K, V>[]): string[];
58
65
  /**
59
66
  * Returns the ID of the root node.
60
67
  * @returns The root node ID.
@@ -131,10 +138,13 @@ export declare abstract class BPTreeTransaction<K, V> {
131
138
  abstract insert(key: K, value: V): Deferred<void>;
132
139
  /**
133
140
  * Deletes the pair that matches the key and value.
141
+ *
134
142
  * @param key The key of the pair. This key must be unique.
135
143
  * @param value The value of the pair.
144
+ *
145
+ * @warning If the 'value' is not specified, a full scan will be performed to find the value associated with the key, which may lead to performance degradation.
136
146
  */
137
- abstract delete(key: K, value: V): Deferred<void>;
147
+ abstract delete(key: K, value?: V): Deferred<void>;
138
148
  /**
139
149
  * It returns whether there is a value in the tree.
140
150
  * @param key The key value to search for. This key must be unique.
@@ -43,7 +43,7 @@ export declare class BPTreeAsyncTransaction<K, V> extends BPTreeTransaction<K, V
43
43
  where(condition: BPTreeCondition<V>, order?: BPTreeOrder): Promise<BPTreePair<K, V>>;
44
44
  insert(key: K, value: V): Promise<void>;
45
45
  protected _deleteEntry(node: BPTreeUnknownNode<K, V>, key: BPTreeNodeKey<K>): Promise<BPTreeUnknownNode<K, V>>;
46
- delete(key: K, value: V): Promise<void>;
46
+ delete(key: K, value?: V): Promise<void>;
47
47
  getHeadData(): Promise<SerializableData>;
48
48
  setHeadData(data: SerializableData): Promise<void>;
49
49
  commit(label?: string): Promise<TransactionResult<string, BPTreeNode<K, V>>>;
@@ -40,7 +40,7 @@ export declare class BPTreeSyncTransaction<K, V> extends BPTreeTransaction<K, V>
40
40
  where(condition: BPTreeCondition<V>, order?: BPTreeOrder): BPTreePair<K, V>;
41
41
  insert(key: K, value: V): void;
42
42
  protected _deleteEntry(node: BPTreeUnknownNode<K, V>, key: BPTreeNodeKey<K>): BPTreeUnknownNode<K, V>;
43
- delete(key: K, value: V): void;
43
+ delete(key: K, value?: V): void;
44
44
  getHeadData(): SerializableData;
45
45
  setHeadData(data: SerializableData): void;
46
46
  commit(label?: string): TransactionResult<string, BPTreeNode<K, V>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "serializable-bptree",
3
- "version": "8.1.6",
3
+ "version": "8.1.7",
4
4
  "description": "Store the B+tree flexibly, not only in-memory.",
5
5
  "types": "./dist/types/index.d.ts",
6
6
  "main": "./dist/cjs/index.cjs",
@@ -38,13 +38,13 @@
38
38
  "license": "MIT",
39
39
  "devDependencies": {
40
40
  "@types/jest": "^30.0.0",
41
- "esbuild": "^0.27.2",
41
+ "esbuild": "^0.27.3",
42
42
  "jest": "^30.2.0",
43
43
  "ts-jest": "^29.4.6",
44
44
  "typescript": "^5.9.3"
45
45
  },
46
46
  "dependencies": {
47
- "mvcc-api": "^1.3.3",
47
+ "mvcc-api": "^1.3.4",
48
48
  "ryoiki": "^1.2.0"
49
49
  }
50
50
  }