mvcc-api 1.1.0 → 1.2.1
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 +150 -96
- package/dist/cjs/index.cjs +239 -48
- package/dist/esm/index.mjs +239 -48
- package/dist/types/core/async/Transaction.d.ts +8 -2
- package/dist/types/core/base/Transaction.d.ts +24 -11
- package/dist/types/core/sync/Transaction.d.ts +8 -2
- package/dist/types/types/index.d.ts +11 -0
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -38,6 +38,10 @@ var MVCCTransaction = class {
|
|
|
38
38
|
snapshotLocalVersion;
|
|
39
39
|
writeBuffer;
|
|
40
40
|
deleteBuffer;
|
|
41
|
+
createdKeys;
|
|
42
|
+
// create()로 생성된 키 추적
|
|
43
|
+
deletedValues;
|
|
44
|
+
// delete 시 삭제 전 값 저장
|
|
41
45
|
// Nested Transaction Properties
|
|
42
46
|
parent;
|
|
43
47
|
localVersion;
|
|
@@ -55,6 +59,8 @@ var MVCCTransaction = class {
|
|
|
55
59
|
this.snapshotVersion = snapshotVersion ?? 0;
|
|
56
60
|
this.writeBuffer = /* @__PURE__ */ new Map();
|
|
57
61
|
this.deleteBuffer = /* @__PURE__ */ new Set();
|
|
62
|
+
this.createdKeys = /* @__PURE__ */ new Set();
|
|
63
|
+
this.deletedValues = /* @__PURE__ */ new Map();
|
|
58
64
|
this.committed = false;
|
|
59
65
|
this.parent = parent;
|
|
60
66
|
this.keyVersions = /* @__PURE__ */ new Map();
|
|
@@ -75,59 +81,58 @@ var MVCCTransaction = class {
|
|
|
75
81
|
isRoot() {
|
|
76
82
|
return !this.parent;
|
|
77
83
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
* @param key The key to create.
|
|
82
|
-
* @param value The value to store.
|
|
83
|
-
* @returns The transaction instance for chaining.
|
|
84
|
-
*/
|
|
85
|
-
create(key, value) {
|
|
86
|
-
if (this.committed) throw new Error("Transaction already committed");
|
|
84
|
+
// --- Internal buffer manipulation helpers ---
|
|
85
|
+
_bufferCreate(key, value) {
|
|
86
|
+
this.localVersion++;
|
|
87
87
|
this.writeBuffer.set(key, value);
|
|
88
|
-
|
|
88
|
+
this.createdKeys.add(key);
|
|
89
|
+
this.deleteBuffer.delete(key);
|
|
90
|
+
this.keyVersions.set(key, this.localVersion);
|
|
89
91
|
}
|
|
90
|
-
|
|
91
|
-
* Schedules a write (update) of a key-value pair.
|
|
92
|
-
* Overwrites any existing value in the buffer.
|
|
93
|
-
* @param key The key to write.
|
|
94
|
-
* @param value The value to store.
|
|
95
|
-
* @returns The transaction instance for chaining.
|
|
96
|
-
*/
|
|
97
|
-
write(key, value) {
|
|
98
|
-
if (this.committed) throw new Error("Transaction already committed");
|
|
92
|
+
_bufferWrite(key, value) {
|
|
99
93
|
this.localVersion++;
|
|
100
94
|
this.writeBuffer.set(key, value);
|
|
101
95
|
this.deleteBuffer.delete(key);
|
|
102
96
|
this.keyVersions.set(key, this.localVersion);
|
|
103
|
-
return this;
|
|
104
97
|
}
|
|
105
|
-
|
|
106
|
-
* Schedules a deletion of a key.
|
|
107
|
-
* @param key The key to delete.
|
|
108
|
-
* @returns The transaction instance for chaining.
|
|
109
|
-
*/
|
|
110
|
-
delete(key) {
|
|
111
|
-
if (this.committed) throw new Error("Transaction already committed");
|
|
98
|
+
_bufferDelete(key) {
|
|
112
99
|
this.localVersion++;
|
|
113
100
|
this.deleteBuffer.add(key);
|
|
114
101
|
this.writeBuffer.delete(key);
|
|
102
|
+
this.createdKeys.delete(key);
|
|
115
103
|
this.keyVersions.set(key, this.localVersion);
|
|
116
|
-
return this;
|
|
117
104
|
}
|
|
118
105
|
/**
|
|
119
106
|
* Rolls back the transaction.
|
|
120
107
|
* Clears all buffers and marks the transaction as finished.
|
|
121
|
-
* @returns The
|
|
108
|
+
* @returns The result object with success, created, updated, and deleted keys.
|
|
122
109
|
*/
|
|
123
110
|
rollback() {
|
|
111
|
+
const created = [];
|
|
112
|
+
const updated = [];
|
|
113
|
+
for (const [key, data] of this.writeBuffer.entries()) {
|
|
114
|
+
if (this.createdKeys.has(key)) {
|
|
115
|
+
created.push({ key, data });
|
|
116
|
+
} else {
|
|
117
|
+
updated.push({ key, data });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const deleted = [];
|
|
121
|
+
for (const key of this.deleteBuffer) {
|
|
122
|
+
const data = this.deletedValues.get(key);
|
|
123
|
+
if (data !== void 0) {
|
|
124
|
+
deleted.push({ key, data });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
124
127
|
this.writeBuffer.clear();
|
|
125
128
|
this.deleteBuffer.clear();
|
|
129
|
+
this.createdKeys.clear();
|
|
130
|
+
this.deletedValues.clear();
|
|
126
131
|
this.committed = true;
|
|
127
132
|
if (this.root !== this) {
|
|
128
133
|
this.root.activeTransactions.delete(this);
|
|
129
134
|
}
|
|
130
|
-
return
|
|
135
|
+
return { success: true, created, updated, deleted };
|
|
131
136
|
}
|
|
132
137
|
};
|
|
133
138
|
|
|
@@ -137,7 +142,39 @@ var SyncMVCCStrategy = class extends MVCCStrategy {
|
|
|
137
142
|
|
|
138
143
|
// src/core/sync/Transaction.ts
|
|
139
144
|
var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
|
|
145
|
+
create(key, value) {
|
|
146
|
+
if (this.committed) throw new Error("Transaction already committed");
|
|
147
|
+
if (this.writeBuffer.has(key) || !this.deleteBuffer.has(key) && this.read(key) !== null) {
|
|
148
|
+
throw new Error(`Key already exists: ${key}`);
|
|
149
|
+
}
|
|
150
|
+
this._bufferCreate(key, value);
|
|
151
|
+
return this;
|
|
152
|
+
}
|
|
153
|
+
write(key, value) {
|
|
154
|
+
if (this.committed) throw new Error("Transaction already committed");
|
|
155
|
+
if (!this.writeBuffer.has(key) && (this.deleteBuffer.has(key) || this.read(key) === null)) {
|
|
156
|
+
throw new Error(`Key not found: ${key}`);
|
|
157
|
+
}
|
|
158
|
+
this._bufferWrite(key, value);
|
|
159
|
+
return this;
|
|
160
|
+
}
|
|
161
|
+
delete(key) {
|
|
162
|
+
if (this.committed) throw new Error("Transaction already committed");
|
|
163
|
+
let valueToDelete = null;
|
|
164
|
+
if (this.writeBuffer.has(key)) {
|
|
165
|
+
valueToDelete = this.writeBuffer.get(key);
|
|
166
|
+
} else if (!this.deleteBuffer.has(key)) {
|
|
167
|
+
valueToDelete = this.read(key);
|
|
168
|
+
}
|
|
169
|
+
if (valueToDelete === null) {
|
|
170
|
+
throw new Error(`Key not found: ${key}`);
|
|
171
|
+
}
|
|
172
|
+
this.deletedValues.set(key, valueToDelete);
|
|
173
|
+
this._bufferDelete(key);
|
|
174
|
+
return this;
|
|
175
|
+
}
|
|
140
176
|
createNested() {
|
|
177
|
+
if (this.committed) throw new Error("Transaction already committed");
|
|
141
178
|
const childVersion = this.isRoot() ? this.version : this.snapshotVersion;
|
|
142
179
|
const child = new _SyncMVCCTransaction(void 0, this, childVersion);
|
|
143
180
|
this.root.activeTransactions.add(child);
|
|
@@ -149,6 +186,12 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
|
|
|
149
186
|
if (this.deleteBuffer.has(key)) return null;
|
|
150
187
|
return this.root._diskRead(key, this.snapshotVersion);
|
|
151
188
|
}
|
|
189
|
+
exists(key) {
|
|
190
|
+
if (this.committed) throw new Error("Transaction already committed");
|
|
191
|
+
if (this.deleteBuffer.has(key)) return false;
|
|
192
|
+
if (this.writeBuffer.has(key)) return true;
|
|
193
|
+
return this.root._diskExists(key, this.snapshotVersion);
|
|
194
|
+
}
|
|
152
195
|
_readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
|
|
153
196
|
if (this.writeBuffer.has(key)) {
|
|
154
197
|
const keyModVersion = this.keyVersions.get(key);
|
|
@@ -169,43 +212,79 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
|
|
|
169
212
|
}
|
|
170
213
|
}
|
|
171
214
|
commit() {
|
|
172
|
-
if (this.committed)
|
|
215
|
+
if (this.committed) {
|
|
216
|
+
return { success: false, error: "Transaction already committed", created: [], updated: [], deleted: [] };
|
|
217
|
+
}
|
|
218
|
+
const created = [];
|
|
219
|
+
const updated = [];
|
|
220
|
+
for (const [key, data] of this.writeBuffer.entries()) {
|
|
221
|
+
if (this.createdKeys.has(key)) {
|
|
222
|
+
created.push({ key, data });
|
|
223
|
+
} else {
|
|
224
|
+
updated.push({ key, data });
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const deleted = [];
|
|
228
|
+
for (const key of this.deleteBuffer) {
|
|
229
|
+
const data = this.deletedValues.get(key);
|
|
230
|
+
if (data !== void 0) {
|
|
231
|
+
deleted.push({ key, data });
|
|
232
|
+
}
|
|
233
|
+
}
|
|
173
234
|
if (this.parent) {
|
|
174
|
-
this.parent._merge(this);
|
|
235
|
+
const error = this.parent._merge(this);
|
|
236
|
+
if (error) {
|
|
237
|
+
return { success: false, error, created: [], updated: [], deleted: [] };
|
|
238
|
+
}
|
|
175
239
|
this.committed = true;
|
|
176
240
|
} else {
|
|
177
241
|
if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
|
|
178
|
-
this._merge(this);
|
|
242
|
+
const error = this._merge(this);
|
|
243
|
+
if (error) {
|
|
244
|
+
return { success: false, error, created: [], updated: [], deleted: [] };
|
|
245
|
+
}
|
|
179
246
|
this.writeBuffer.clear();
|
|
180
247
|
this.deleteBuffer.clear();
|
|
248
|
+
this.createdKeys.clear();
|
|
249
|
+
this.deletedValues.clear();
|
|
181
250
|
this.keyVersions.clear();
|
|
182
251
|
this.localVersion = 0;
|
|
183
252
|
}
|
|
184
253
|
}
|
|
185
|
-
return
|
|
254
|
+
return { success: true, created, updated, deleted };
|
|
186
255
|
}
|
|
187
256
|
_merge(child) {
|
|
188
257
|
if (this.parent) {
|
|
189
258
|
for (const key of child.writeBuffer.keys()) {
|
|
190
259
|
const lastModLocalVer = this.keyVersions.get(key);
|
|
191
260
|
if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
|
|
192
|
-
|
|
261
|
+
return `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`;
|
|
193
262
|
}
|
|
194
263
|
}
|
|
195
264
|
for (const key of child.deleteBuffer) {
|
|
196
265
|
const lastModLocalVer = this.keyVersions.get(key);
|
|
197
266
|
if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
|
|
198
|
-
|
|
267
|
+
return `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`;
|
|
199
268
|
}
|
|
200
269
|
}
|
|
201
270
|
const newLocalVersion = this.localVersion + 1;
|
|
202
271
|
for (const key of child.writeBuffer.keys()) {
|
|
203
|
-
this.
|
|
272
|
+
this.writeBuffer.set(key, child.writeBuffer.get(key));
|
|
273
|
+
this.deleteBuffer.delete(key);
|
|
204
274
|
this.keyVersions.set(key, newLocalVersion);
|
|
275
|
+
if (child.createdKeys.has(key)) {
|
|
276
|
+
this.createdKeys.add(key);
|
|
277
|
+
}
|
|
205
278
|
}
|
|
206
279
|
for (const key of child.deleteBuffer) {
|
|
207
|
-
this.
|
|
280
|
+
this.deleteBuffer.add(key);
|
|
281
|
+
this.writeBuffer.delete(key);
|
|
282
|
+
this.createdKeys.delete(key);
|
|
208
283
|
this.keyVersions.set(key, newLocalVersion);
|
|
284
|
+
const deletedValue = child.deletedValues.get(key);
|
|
285
|
+
if (deletedValue !== void 0) {
|
|
286
|
+
this.deletedValues.set(key, deletedValue);
|
|
287
|
+
}
|
|
209
288
|
}
|
|
210
289
|
this.localVersion = newLocalVersion;
|
|
211
290
|
this.root.activeTransactions.delete(child);
|
|
@@ -218,7 +297,7 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
|
|
|
218
297
|
if (versions && versions.length > 0) {
|
|
219
298
|
const lastVer = versions[versions.length - 1].version;
|
|
220
299
|
if (lastVer > child.snapshotVersion) {
|
|
221
|
-
|
|
300
|
+
return `Commit conflict: Key '${key}' was modified by a newer transaction (v${lastVer})`;
|
|
222
301
|
}
|
|
223
302
|
}
|
|
224
303
|
}
|
|
@@ -231,6 +310,7 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
|
|
|
231
310
|
this.version = newVersion;
|
|
232
311
|
this._cleanupDeletedCache();
|
|
233
312
|
}
|
|
313
|
+
return null;
|
|
234
314
|
}
|
|
235
315
|
// --- Internal IO Helpers (Root Only) ---
|
|
236
316
|
_diskWrite(key, value, version) {
|
|
@@ -276,6 +356,24 @@ var SyncMVCCTransaction = class _SyncMVCCTransaction extends MVCCTransaction {
|
|
|
276
356
|
}
|
|
277
357
|
return null;
|
|
278
358
|
}
|
|
359
|
+
_diskExists(key, snapshotVersion) {
|
|
360
|
+
const strategy = this.strategy;
|
|
361
|
+
if (!strategy) throw new Error("Root Transaction missing strategy");
|
|
362
|
+
const versions = this.versionIndex.get(key);
|
|
363
|
+
if (!versions) {
|
|
364
|
+
return strategy.exists(key);
|
|
365
|
+
}
|
|
366
|
+
let targetVerObj = null;
|
|
367
|
+
for (const v of versions) {
|
|
368
|
+
if (v.version <= snapshotVersion) {
|
|
369
|
+
targetVerObj = v;
|
|
370
|
+
} else {
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
if (!targetVerObj) return strategy.exists(key);
|
|
375
|
+
return targetVerObj.exists;
|
|
376
|
+
}
|
|
279
377
|
_diskDelete(key, snapshotVersion) {
|
|
280
378
|
const strategy = this.strategy;
|
|
281
379
|
if (!strategy) throw new Error("Root Transaction missing strategy");
|
|
@@ -586,7 +684,39 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
|
|
|
586
684
|
this.lock.writeUnlock(lockId);
|
|
587
685
|
});
|
|
588
686
|
}
|
|
687
|
+
async create(key, value) {
|
|
688
|
+
if (this.committed) throw new Error("Transaction already committed");
|
|
689
|
+
if (this.writeBuffer.has(key) || !this.deleteBuffer.has(key) && await this.read(key) !== null) {
|
|
690
|
+
throw new Error(`Key already exists: ${key}`);
|
|
691
|
+
}
|
|
692
|
+
this._bufferCreate(key, value);
|
|
693
|
+
return this;
|
|
694
|
+
}
|
|
695
|
+
async write(key, value) {
|
|
696
|
+
if (this.committed) throw new Error("Transaction already committed");
|
|
697
|
+
if (!this.writeBuffer.has(key) && (this.deleteBuffer.has(key) || await this.read(key) === null)) {
|
|
698
|
+
throw new Error(`Key not found: ${key}`);
|
|
699
|
+
}
|
|
700
|
+
this._bufferWrite(key, value);
|
|
701
|
+
return this;
|
|
702
|
+
}
|
|
703
|
+
async delete(key) {
|
|
704
|
+
if (this.committed) throw new Error("Transaction already committed");
|
|
705
|
+
let valueToDelete = null;
|
|
706
|
+
if (this.writeBuffer.has(key)) {
|
|
707
|
+
valueToDelete = this.writeBuffer.get(key);
|
|
708
|
+
} else if (!this.deleteBuffer.has(key)) {
|
|
709
|
+
valueToDelete = await this.read(key);
|
|
710
|
+
}
|
|
711
|
+
if (valueToDelete === null) {
|
|
712
|
+
throw new Error(`Key not found: ${key}`);
|
|
713
|
+
}
|
|
714
|
+
this.deletedValues.set(key, valueToDelete);
|
|
715
|
+
this._bufferDelete(key);
|
|
716
|
+
return this;
|
|
717
|
+
}
|
|
589
718
|
createNested() {
|
|
719
|
+
if (this.committed) throw new Error("Transaction already committed");
|
|
590
720
|
const childVersion = this.isRoot() ? this.version : this.snapshotVersion;
|
|
591
721
|
const child = new _AsyncMVCCTransaction(void 0, this, childVersion);
|
|
592
722
|
this.root.activeTransactions.add(child);
|
|
@@ -598,6 +728,12 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
|
|
|
598
728
|
if (this.deleteBuffer.has(key)) return null;
|
|
599
729
|
return this.root._diskRead(key, this.snapshotVersion);
|
|
600
730
|
}
|
|
731
|
+
async exists(key) {
|
|
732
|
+
if (this.committed) throw new Error("Transaction already committed");
|
|
733
|
+
if (this.deleteBuffer.has(key)) return false;
|
|
734
|
+
if (this.writeBuffer.has(key)) return true;
|
|
735
|
+
return this.root._diskExists(key, this.snapshotVersion);
|
|
736
|
+
}
|
|
601
737
|
async _readSnapshot(key, snapshotVersion, snapshotLocalVersion) {
|
|
602
738
|
if (this.writeBuffer.has(key)) {
|
|
603
739
|
const keyModVersion = this.keyVersions.get(key);
|
|
@@ -619,20 +755,46 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
|
|
|
619
755
|
}
|
|
620
756
|
async commit() {
|
|
621
757
|
return this.writeLock(async () => {
|
|
622
|
-
if (this.committed)
|
|
758
|
+
if (this.committed) {
|
|
759
|
+
return { success: false, error: "Transaction already committed", created: [], updated: [], deleted: [] };
|
|
760
|
+
}
|
|
761
|
+
const created = [];
|
|
762
|
+
const updated = [];
|
|
763
|
+
for (const [key, data] of this.writeBuffer.entries()) {
|
|
764
|
+
if (this.createdKeys.has(key)) {
|
|
765
|
+
created.push({ key, data });
|
|
766
|
+
} else {
|
|
767
|
+
updated.push({ key, data });
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
const deleted = [];
|
|
771
|
+
for (const key of this.deleteBuffer) {
|
|
772
|
+
const data = this.deletedValues.get(key);
|
|
773
|
+
if (data !== void 0) {
|
|
774
|
+
deleted.push({ key, data });
|
|
775
|
+
}
|
|
776
|
+
}
|
|
623
777
|
if (this.parent) {
|
|
624
|
-
await this.parent._merge(this);
|
|
778
|
+
const error = await this.parent._merge(this);
|
|
779
|
+
if (error) {
|
|
780
|
+
return { success: false, error, created: [], updated: [], deleted: [] };
|
|
781
|
+
}
|
|
625
782
|
this.committed = true;
|
|
626
783
|
} else {
|
|
627
784
|
if (this.writeBuffer.size > 0 || this.deleteBuffer.size > 0) {
|
|
628
|
-
await this._merge(this);
|
|
785
|
+
const error = await this._merge(this);
|
|
786
|
+
if (error) {
|
|
787
|
+
return { success: false, error, created: [], updated: [], deleted: [] };
|
|
788
|
+
}
|
|
629
789
|
this.writeBuffer.clear();
|
|
630
790
|
this.deleteBuffer.clear();
|
|
791
|
+
this.createdKeys.clear();
|
|
792
|
+
this.deletedValues.clear();
|
|
631
793
|
this.keyVersions.clear();
|
|
632
794
|
this.localVersion = 0;
|
|
633
795
|
}
|
|
634
796
|
}
|
|
635
|
-
return
|
|
797
|
+
return { success: true, created, updated, deleted };
|
|
636
798
|
});
|
|
637
799
|
}
|
|
638
800
|
async _merge(child) {
|
|
@@ -641,23 +803,33 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
|
|
|
641
803
|
for (const key of child.writeBuffer.keys()) {
|
|
642
804
|
const lastModLocalVer = this.keyVersions.get(key);
|
|
643
805
|
if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
|
|
644
|
-
|
|
806
|
+
return `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`;
|
|
645
807
|
}
|
|
646
808
|
}
|
|
647
809
|
for (const key of child.deleteBuffer) {
|
|
648
810
|
const lastModLocalVer = this.keyVersions.get(key);
|
|
649
811
|
if (lastModLocalVer !== void 0 && lastModLocalVer > child.snapshotLocalVersion) {
|
|
650
|
-
|
|
812
|
+
return `Commit conflict: Key '${key}' was modified by a newer transaction (Local v${lastModLocalVer})`;
|
|
651
813
|
}
|
|
652
814
|
}
|
|
653
815
|
const newLocalVersion = this.localVersion + 1;
|
|
654
816
|
for (const key of child.writeBuffer.keys()) {
|
|
655
|
-
this.
|
|
817
|
+
this.writeBuffer.set(key, child.writeBuffer.get(key));
|
|
818
|
+
this.deleteBuffer.delete(key);
|
|
656
819
|
this.keyVersions.set(key, newLocalVersion);
|
|
820
|
+
if (child.createdKeys.has(key)) {
|
|
821
|
+
this.createdKeys.add(key);
|
|
822
|
+
}
|
|
657
823
|
}
|
|
658
824
|
for (const key of child.deleteBuffer) {
|
|
659
|
-
this.
|
|
825
|
+
this.deleteBuffer.add(key);
|
|
826
|
+
this.writeBuffer.delete(key);
|
|
827
|
+
this.createdKeys.delete(key);
|
|
660
828
|
this.keyVersions.set(key, newLocalVersion);
|
|
829
|
+
const deletedValue = child.deletedValues.get(key);
|
|
830
|
+
if (deletedValue !== void 0) {
|
|
831
|
+
this.deletedValues.set(key, deletedValue);
|
|
832
|
+
}
|
|
661
833
|
}
|
|
662
834
|
this.localVersion = newLocalVersion;
|
|
663
835
|
this.root.activeTransactions.delete(child);
|
|
@@ -670,7 +842,7 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
|
|
|
670
842
|
if (versions && versions.length > 0) {
|
|
671
843
|
const lastVer = versions[versions.length - 1].version;
|
|
672
844
|
if (lastVer > child.snapshotVersion) {
|
|
673
|
-
|
|
845
|
+
return `Commit conflict: Key '${key}' was modified by a newer transaction (v${lastVer})`;
|
|
674
846
|
}
|
|
675
847
|
}
|
|
676
848
|
}
|
|
@@ -683,6 +855,7 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
|
|
|
683
855
|
this.version = newVersion;
|
|
684
856
|
this._cleanupDeletedCache();
|
|
685
857
|
}
|
|
858
|
+
return null;
|
|
686
859
|
});
|
|
687
860
|
}
|
|
688
861
|
// --- Internal IO Helpers (Root Only) ---
|
|
@@ -729,6 +902,24 @@ var AsyncMVCCTransaction = class _AsyncMVCCTransaction extends MVCCTransaction {
|
|
|
729
902
|
}
|
|
730
903
|
return null;
|
|
731
904
|
}
|
|
905
|
+
async _diskExists(key, snapshotVersion) {
|
|
906
|
+
const strategy = this.strategy;
|
|
907
|
+
if (!strategy) throw new Error("Root Transaction missing strategy");
|
|
908
|
+
const versions = this.versionIndex.get(key);
|
|
909
|
+
if (!versions) {
|
|
910
|
+
return strategy.exists(key);
|
|
911
|
+
}
|
|
912
|
+
let targetVerObj = null;
|
|
913
|
+
for (const v of versions) {
|
|
914
|
+
if (v.version <= snapshotVersion) {
|
|
915
|
+
targetVerObj = v;
|
|
916
|
+
} else {
|
|
917
|
+
break;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
if (!targetVerObj) return strategy.exists(key);
|
|
921
|
+
return targetVerObj.exists;
|
|
922
|
+
}
|
|
732
923
|
async _diskDelete(key, snapshotVersion) {
|
|
733
924
|
const strategy = this.strategy;
|
|
734
925
|
if (!strategy) throw new Error("Root Transaction missing strategy");
|