mvcc-api 1.2.2 → 1.2.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.
@@ -84,6 +84,19 @@ var MVCCTransaction = class {
84
84
  isRoot() {
85
85
  return !this.parent;
86
86
  }
87
+ /**
88
+ * Checks if any ancestor transaction has already been committed.
89
+ * A nested transaction cannot commit if its parent or any higher ancestor is committed.
90
+ * @returns True if at least one ancestor is committed, false otherwise.
91
+ */
92
+ hasCommittedAncestor() {
93
+ let current = this.parent;
94
+ while (current) {
95
+ if (current.committed) return true;
96
+ current = current.parent;
97
+ }
98
+ return false;
99
+ }
87
100
  // --- Internal buffer manipulation helpers ---
88
101
  _bufferCreate(key, value) {
89
102
  this.localVersion++;
@@ -106,12 +119,7 @@ var MVCCTransaction = class {
106
119
  this.createdKeys.delete(key);
107
120
  this.keyVersions.set(key, this.localVersion);
108
121
  }
109
- /**
110
- * Rolls back the transaction.
111
- * Clears all buffers and marks the transaction as finished.
112
- * @returns The result object with success, created, updated, and deleted keys.
113
- */
114
- rollback() {
122
+ _getResultEntries() {
115
123
  const created = [];
116
124
  const updated = [];
117
125
  for (const [key, data] of this.writeBuffer.entries()) {
@@ -129,6 +137,15 @@ var MVCCTransaction = class {
129
137
  deleted.push({ key, data });
130
138
  }
131
139
  }
140
+ return { created, updated, deleted };
141
+ }
142
+ /**
143
+ * Rolls back the transaction.
144
+ * Clears all buffers and marks the transaction as finished.
145
+ * @returns The result object with success, created, updated, and deleted keys.
146
+ */
147
+ rollback() {
148
+ const { created, updated, deleted } = this._getResultEntries();
132
149
  this.writeBuffer.clear();
133
150
  this.deleteBuffer.clear();
134
151
  this.createdKeys.clear();
@@ -223,30 +240,17 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
223
240
  }
224
241
  }
225
242
  commit() {
243
+ const { created, updated, deleted } = this._getResultEntries();
226
244
  if (this.committed) {
227
- return { success: false, error: "Transaction already committed", created: [], updated: [], deleted: [] };
228
- }
229
- const created = [];
230
- const updated = [];
231
- for (const [key, data] of this.writeBuffer.entries()) {
232
- if (this.createdKeys.has(key)) {
233
- created.push({ key, data });
234
- } else {
235
- updated.push({ key, data });
236
- }
245
+ return { success: false, error: "Transaction already committed", created, updated, deleted };
237
246
  }
238
- const deleted = [];
239
- for (const key of this.deleteBuffer) {
240
- if (!this.originallyExisted.has(key)) continue;
241
- const data = this.deletedValues.get(key);
242
- if (data !== void 0) {
243
- deleted.push({ key, data });
244
- }
247
+ if (this.hasCommittedAncestor()) {
248
+ return { success: false, error: "Ancestor transaction already committed", created, updated, deleted };
245
249
  }
246
250
  if (this.parent) {
247
251
  const error = this.parent._merge(this);
248
252
  if (error) {
249
- return { success: false, error, created: [], updated: [], deleted: [] };
253
+ return { success: false, error, created, updated, deleted };
250
254
  }
251
255
  this.committed = true;
252
256
  } else {
@@ -776,30 +780,17 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
776
780
  }
777
781
  async commit() {
778
782
  return this.writeLock(async () => {
783
+ const { created, updated, deleted } = this._getResultEntries();
779
784
  if (this.committed) {
780
- return { success: false, error: "Transaction already committed", created: [], updated: [], deleted: [] };
781
- }
782
- const created = [];
783
- const updated = [];
784
- for (const [key, data] of this.writeBuffer.entries()) {
785
- if (this.createdKeys.has(key)) {
786
- created.push({ key, data });
787
- } else {
788
- updated.push({ key, data });
789
- }
785
+ return { success: false, error: "Transaction already committed", created, updated, deleted };
790
786
  }
791
- const deleted = [];
792
- for (const key of this.deleteBuffer) {
793
- if (!this.originallyExisted.has(key)) continue;
794
- const data = this.deletedValues.get(key);
795
- if (data !== void 0) {
796
- deleted.push({ key, data });
797
- }
787
+ if (this.hasCommittedAncestor()) {
788
+ return { success: false, error: "Ancestor transaction already committed", created, updated, deleted };
798
789
  }
799
790
  if (this.parent) {
800
791
  const error = await this.parent._merge(this);
801
792
  if (error) {
802
- return { success: false, error, created: [], updated: [], deleted: [] };
793
+ return { success: false, error, created, updated, deleted };
803
794
  }
804
795
  this.committed = true;
805
796
  } else {
@@ -55,6 +55,19 @@ var MVCCTransaction = class {
55
55
  isRoot() {
56
56
  return !this.parent;
57
57
  }
58
+ /**
59
+ * Checks if any ancestor transaction has already been committed.
60
+ * A nested transaction cannot commit if its parent or any higher ancestor is committed.
61
+ * @returns True if at least one ancestor is committed, false otherwise.
62
+ */
63
+ hasCommittedAncestor() {
64
+ let current = this.parent;
65
+ while (current) {
66
+ if (current.committed) return true;
67
+ current = current.parent;
68
+ }
69
+ return false;
70
+ }
58
71
  // --- Internal buffer manipulation helpers ---
59
72
  _bufferCreate(key, value) {
60
73
  this.localVersion++;
@@ -77,12 +90,7 @@ var MVCCTransaction = class {
77
90
  this.createdKeys.delete(key);
78
91
  this.keyVersions.set(key, this.localVersion);
79
92
  }
80
- /**
81
- * Rolls back the transaction.
82
- * Clears all buffers and marks the transaction as finished.
83
- * @returns The result object with success, created, updated, and deleted keys.
84
- */
85
- rollback() {
93
+ _getResultEntries() {
86
94
  const created = [];
87
95
  const updated = [];
88
96
  for (const [key, data] of this.writeBuffer.entries()) {
@@ -100,6 +108,15 @@ var MVCCTransaction = class {
100
108
  deleted.push({ key, data });
101
109
  }
102
110
  }
111
+ return { created, updated, deleted };
112
+ }
113
+ /**
114
+ * Rolls back the transaction.
115
+ * Clears all buffers and marks the transaction as finished.
116
+ * @returns The result object with success, created, updated, and deleted keys.
117
+ */
118
+ rollback() {
119
+ const { created, updated, deleted } = this._getResultEntries();
103
120
  this.writeBuffer.clear();
104
121
  this.deleteBuffer.clear();
105
122
  this.createdKeys.clear();
@@ -194,30 +211,17 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
194
211
  }
195
212
  }
196
213
  commit() {
214
+ const { created, updated, deleted } = this._getResultEntries();
197
215
  if (this.committed) {
198
- return { success: false, error: "Transaction already committed", created: [], updated: [], deleted: [] };
199
- }
200
- const created = [];
201
- const updated = [];
202
- for (const [key, data] of this.writeBuffer.entries()) {
203
- if (this.createdKeys.has(key)) {
204
- created.push({ key, data });
205
- } else {
206
- updated.push({ key, data });
207
- }
216
+ return { success: false, error: "Transaction already committed", created, updated, deleted };
208
217
  }
209
- const deleted = [];
210
- for (const key of this.deleteBuffer) {
211
- if (!this.originallyExisted.has(key)) continue;
212
- const data = this.deletedValues.get(key);
213
- if (data !== void 0) {
214
- deleted.push({ key, data });
215
- }
218
+ if (this.hasCommittedAncestor()) {
219
+ return { success: false, error: "Ancestor transaction already committed", created, updated, deleted };
216
220
  }
217
221
  if (this.parent) {
218
222
  const error = this.parent._merge(this);
219
223
  if (error) {
220
- return { success: false, error, created: [], updated: [], deleted: [] };
224
+ return { success: false, error, created, updated, deleted };
221
225
  }
222
226
  this.committed = true;
223
227
  } else {
@@ -747,30 +751,17 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
747
751
  }
748
752
  async commit() {
749
753
  return this.writeLock(async () => {
754
+ const { created, updated, deleted } = this._getResultEntries();
750
755
  if (this.committed) {
751
- return { success: false, error: "Transaction already committed", created: [], updated: [], deleted: [] };
752
- }
753
- const created = [];
754
- const updated = [];
755
- for (const [key, data] of this.writeBuffer.entries()) {
756
- if (this.createdKeys.has(key)) {
757
- created.push({ key, data });
758
- } else {
759
- updated.push({ key, data });
760
- }
756
+ return { success: false, error: "Transaction already committed", created, updated, deleted };
761
757
  }
762
- const deleted = [];
763
- for (const key of this.deleteBuffer) {
764
- if (!this.originallyExisted.has(key)) continue;
765
- const data = this.deletedValues.get(key);
766
- if (data !== void 0) {
767
- deleted.push({ key, data });
768
- }
758
+ if (this.hasCommittedAncestor()) {
759
+ return { success: false, error: "Ancestor transaction already committed", created, updated, deleted };
769
760
  }
770
761
  if (this.parent) {
771
762
  const error = await this.parent._merge(this);
772
763
  if (error) {
773
- return { success: false, error, created: [], updated: [], deleted: [] };
764
+ return { success: false, error, created, updated, deleted };
774
765
  }
775
766
  this.committed = true;
776
767
  } else {
@@ -1,4 +1,4 @@
1
- import type { Deferred, TransactionResult } from '../../types';
1
+ import type { Deferred, TransactionResult, TransactionEntry } from '../../types';
2
2
  import type { MVCCStrategy } from './Strategy';
3
3
  /**
4
4
  * MVCC Transaction abstract class.
@@ -34,6 +34,12 @@ export declare abstract class MVCCTransaction<S extends MVCCStrategy<K, T>, K, T
34
34
  protected activeTransactions: Set<MVCCTransaction<S, K, T>>;
35
35
  constructor(strategy?: S, parent?: MVCCTransaction<S, K, T>, snapshotVersion?: number);
36
36
  isRoot(): boolean;
37
+ /**
38
+ * Checks if any ancestor transaction has already been committed.
39
+ * A nested transaction cannot commit if its parent or any higher ancestor is committed.
40
+ * @returns True if at least one ancestor is committed, false otherwise.
41
+ */
42
+ hasCommittedAncestor(): boolean;
37
43
  /**
38
44
  * Schedules a creation (insert) of a key-value pair.
39
45
  * Throws if the key already exists.
@@ -60,6 +66,11 @@ export declare abstract class MVCCTransaction<S extends MVCCStrategy<K, T>, K, T
60
66
  protected _bufferCreate(key: K, value: T): void;
61
67
  protected _bufferWrite(key: K, value: T): void;
62
68
  protected _bufferDelete(key: K): void;
69
+ protected _getResultEntries(): {
70
+ created: TransactionEntry<K, T>[];
71
+ updated: TransactionEntry<K, T>[];
72
+ deleted: TransactionEntry<K, T>[];
73
+ };
63
74
  /**
64
75
  * Rolls back the transaction.
65
76
  * Clears all buffers and marks the transaction as finished.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mvcc-api",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "Multiversion Concurrency Control (MVCC) API for TypeScript",
5
5
  "license": "MIT",
6
6
  "author": "izure <admin@izure.org>",