@matrixai/db
Advanced tools
Comparing version
@@ -51,2 +51,4 @@ /// <reference types="node" /> | ||
transaction(): ResourceAcquire<DBTransaction>; | ||
withTransactionF<T>(f: (tran: DBTransaction) => Promise<T>): Promise<T>; | ||
withTransactionG<T, TReturn, TNext>(g: (tran: DBTransaction) => AsyncGenerator<T, TReturn, TNext>): AsyncGenerator<T, TReturn, TNext>; | ||
/** | ||
@@ -53,0 +55,0 @@ * Gets a value from the DB |
@@ -35,2 +35,3 @@ "use strict"; | ||
const logger_1 = __importDefault(require("@matrixai/logger")); | ||
const resources_1 = require("@matrixai/resources"); | ||
const CreateDestroyStartStop_1 = require("@matrixai/async-init/dist/CreateDestroyStartStop"); | ||
@@ -150,2 +151,8 @@ const DBTransaction_1 = __importDefault(require("./DBTransaction")); | ||
} | ||
async withTransactionF(f) { | ||
return resources_1.withF([this.transaction()], ([tran]) => f(tran)); | ||
} | ||
withTransactionG(g) { | ||
return resources_1.withG([this.transaction()], ([tran]) => g(tran)); | ||
} | ||
async get(keyPath, raw = false) { | ||
@@ -152,0 +159,0 @@ if (!Array.isArray(keyPath)) { |
@@ -38,2 +38,4 @@ /// <reference types="node" /> | ||
readonly transactionPath: LevelPath; | ||
readonly transactionDataPath: LevelPath; | ||
readonly transactionTombstonePath: LevelPath; | ||
protected db: DB; | ||
@@ -40,0 +42,0 @@ protected logger: Logger; |
@@ -45,2 +45,6 @@ "use strict"; | ||
this.transactionPath = ['transactions', this.transactionId.toString()]; | ||
this.transactionDataPath = [...this.transactionPath, 'data']; | ||
// If tombstone is undefined, it has not been deleted | ||
// If tombstone is true, then it has been deleted | ||
this.transactionTombstonePath = [...this.transactionPath, 'tombstone']; | ||
} | ||
@@ -79,5 +83,10 @@ static async createTransaction({ db, transactionId, logger = new logger_1.default(this.name), }) { | ||
} | ||
let value = await this.db._get([...this.transactionPath, ...keyPath], raw); | ||
let value = await this.db._get([...this.transactionDataPath, ...keyPath], raw); | ||
if (value === undefined) { | ||
value = await this.db.get(keyPath, raw); | ||
if ((await this.db._get([ | ||
...this.transactionTombstonePath, | ||
...keyPath, | ||
])) !== true) { | ||
value = await this.db.get(keyPath, raw); | ||
} | ||
// Don't set it in the transaction DB | ||
@@ -95,3 +104,4 @@ // Because this is not a repeatable-read "snapshot" | ||
} | ||
await this.db._put([...this.transactionPath, ...keyPath], value, raw); | ||
await this.db._put([...this.transactionDataPath, ...keyPath], value, raw); | ||
await this.db._del([...this.transactionTombstonePath, ...keyPath]); | ||
this._ops.push({ | ||
@@ -111,3 +121,4 @@ type: 'put', | ||
} | ||
await this.db._del([...this.transactionPath, ...keyPath]); | ||
await this.db._del([...this.transactionDataPath, ...keyPath]); | ||
await this.db._put([...this.transactionTombstonePath, ...keyPath], true); | ||
this._ops.push({ | ||
@@ -130,3 +141,3 @@ type: 'del', | ||
valueAsBuffer: true, | ||
}, [...this.transactionPath, ...levelPath]); | ||
}, [...this.transactionDataPath, ...levelPath]); | ||
const order = options?.reverse ? 'desc' : 'asc'; | ||
@@ -166,44 +177,70 @@ const iterator = { | ||
try { | ||
const tranKV = (await tranIterator.next()); | ||
const dataKV = (await dataIterator.next()); | ||
// If both are finished, iterator is finished | ||
if (tranKV == null && dataKV == null) { | ||
return undefined; | ||
} | ||
// If tranIterator is not finished but dataIterator is finished | ||
// continue with tranIterator | ||
if (tranKV != null && dataKV == null) { | ||
return tranKV; | ||
} | ||
// If tranIterator is finished but dataIterator is not finished | ||
// continue with the dataIterator | ||
if (tranKV == null && dataKV != null) { | ||
return dataKV; | ||
} | ||
const [tranKey, tranData] = tranKV; | ||
const [dataKey, dataData] = dataKV; | ||
const keyCompare = Buffer.compare(tranKey, dataKey); | ||
if (keyCompare < 0) { | ||
if (order === 'asc') { | ||
dataIterator.seek(tranKey); | ||
return [tranKey, tranData]; | ||
while (true) { | ||
const tranKV = (await tranIterator.next()); | ||
const dataKV = (await dataIterator.next()); | ||
// If both are finished, iterator is finished | ||
if (tranKV == null && dataKV == null) { | ||
return undefined; | ||
} | ||
else if (order === 'desc') { | ||
tranIterator.seek(dataKey); | ||
return [dataKey, dataData]; | ||
// If tranIterator is not finished but dataIterator is finished | ||
// continue with tranIterator | ||
if (tranKV != null && dataKV == null) { | ||
return tranKV; | ||
} | ||
} | ||
else if (keyCompare > 0) { | ||
if (order === 'asc') { | ||
tranIterator.seek(dataKey); | ||
return [dataKey, dataData]; | ||
// If tranIterator is finished but dataIterator is not finished | ||
// continue with the dataIterator | ||
if (tranKV == null && dataKV != null) { | ||
// If the dataKey is entombed, skip iteration | ||
if ((await this.db._get([ | ||
...this.transactionTombstonePath, | ||
...levelPath, | ||
dataKV[0], | ||
])) === true) { | ||
continue; | ||
} | ||
return dataKV; | ||
} | ||
else if (order === 'desc') { | ||
dataIterator.seek(tranKey); | ||
const [tranKey, tranData] = tranKV; | ||
const [dataKey, dataData] = dataKV; | ||
const keyCompare = Buffer.compare(tranKey, dataKey); | ||
if (keyCompare < 0) { | ||
if (order === 'asc') { | ||
dataIterator.seek(tranKey); | ||
return [tranKey, tranData]; | ||
} | ||
else if (order === 'desc') { | ||
tranIterator.seek(dataKey); | ||
// If the dataKey is entombed, skip iteration | ||
if ((await this.db._get([ | ||
...this.transactionTombstonePath, | ||
...levelPath, | ||
dataKey, | ||
])) === true) { | ||
continue; | ||
} | ||
return [dataKey, dataData]; | ||
} | ||
} | ||
else if (keyCompare > 0) { | ||
if (order === 'asc') { | ||
tranIterator.seek(dataKey); | ||
// If the dataKey is entombed, skip iteration | ||
if ((await this.db._get([ | ||
...this.transactionTombstonePath, | ||
...levelPath, | ||
dataKey, | ||
])) === true) { | ||
continue; | ||
} | ||
return [dataKey, dataData]; | ||
} | ||
else if (order === 'desc') { | ||
dataIterator.seek(tranKey); | ||
return [tranKey, tranData]; | ||
} | ||
} | ||
else { | ||
return [tranKey, tranData]; | ||
} | ||
} | ||
else { | ||
return [tranKey, tranData]; | ||
} | ||
} | ||
@@ -210,0 +247,0 @@ finally { |
{ | ||
"name": "@matrixai/db", | ||
"version": "3.2.3", | ||
"version": "3.3.0", | ||
"author": "Roger Qiu", | ||
@@ -5,0 +5,0 @@ "description": "DB", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
104907
4.05%1608
3.08%