@electric-sql/drivers
Version:
ElectricSQL database drivers.
114 lines • 3.07 kB
JavaScript
import { Mutex } from "async-mutex";
class DatabaseAdapter {
txMutex;
constructor() {
this.txMutex = new Mutex();
}
async _transaction(f) {
await this._run({ sql: "BEGIN" });
return new Promise((resolve, reject) => {
const tx = new Transaction(this, reject);
f(tx, (res) => {
this._run({ sql: "COMMIT" }).then(() => {
resolve(res);
}).catch(reject);
});
}).catch((err) => {
return this._run({ sql: "ROLLBACK" }).then(() => {
throw err;
});
});
}
async transaction(f) {
return this.txMutex.runExclusive(() => {
return this._transaction(f);
});
}
run(stmt) {
return this.txMutex.runExclusive(() => {
return this._run(stmt);
});
}
query(stmt) {
return this.txMutex.runExclusive(() => {
return this._query(stmt);
});
}
runInTransaction(...statements) {
return this.txMutex.runExclusive(() => {
return this._runInTransaction(...statements);
});
}
async _runExclusively(f) {
const adapter = {
run: this._run.bind(this),
query: this._query.bind(this),
transaction: this._transaction.bind(this),
runInTransaction: this._runInTransaction.bind(this)
};
return await f(adapter);
}
runExclusively(f) {
return this.txMutex.runExclusive(() => {
return this._runExclusively(f);
});
}
get isLocked() {
return this.txMutex.isLocked();
}
}
class BatchDatabaseAdapter extends DatabaseAdapter {
async _runInTransaction(...statements) {
return this.execBatch(statements);
}
}
class SerialDatabaseAdapter extends DatabaseAdapter {
async _runInTransaction(...statements) {
let transactionBegan = false;
let rowsAffected = 0;
try {
await this._run({ sql: "BEGIN" });
transactionBegan = true;
for (const stmt of statements) {
const { rowsAffected: rowsModified } = await this._run(stmt);
rowsAffected += rowsModified;
}
await this._run({ sql: "COMMIT" });
return {
rowsAffected
};
} catch (error) {
if (transactionBegan) {
await this._run({ sql: "ROLLBACK" });
}
throw error;
}
}
}
class Transaction {
constructor(adapter, signalFailure) {
this.adapter = adapter;
this.signalFailure = signalFailure;
}
invokeCallback(prom, successCallback, errorCallback) {
prom.then((res) => {
if (typeof successCallback !== "undefined") successCallback(this, res);
}).catch((err) => {
if (typeof errorCallback !== "undefined") errorCallback(err);
this.signalFailure(err);
});
}
run(statement, successCallback, errorCallback) {
const prom = this.adapter._run(statement);
this.invokeCallback(prom, successCallback, errorCallback);
}
query(statement, successCallback, errorCallback) {
const prom = this.adapter._query(statement);
this.invokeCallback(prom, successCallback, errorCallback);
}
}
export {
BatchDatabaseAdapter,
SerialDatabaseAdapter
};
//# sourceMappingURL=adapter.js.map