123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- import { Db } from '../index';
- import { CollectionReference } from '../collection';
- import { ERRORS } from '../const/code';
- const START = 'database.startTransaction';
- const COMMIT = 'database.commitTransaction';
- const ABORT = 'database.abortTransaction';
- export class Transaction {
- constructor(db) {
- this._db = db;
- this._request = new Db.reqClass(this._db.config);
- this.aborted = false;
- this.commited = false;
- this.inited = false;
- }
- async init() {
- const res = await this._request.send(START);
- if (res.code) {
- throw res;
- }
- this.inited = true;
- this._id = res.transactionId;
- }
- collection(collName) {
- if (!collName) {
- throw new Error('Collection name is required');
- }
- return new CollectionReference(this._db, collName, {}, this._id);
- }
- getTransactionId() {
- return this._id;
- }
- getRequestMethod() {
- return this._request;
- }
- async commit() {
- const param = {
- transactionId: this._id
- };
- const res = await this._request.send(COMMIT, param);
- if (res.code)
- throw res;
- this.commited = true;
- return res;
- }
- async rollback(customRollbackRes) {
- const param = {
- transactionId: this._id
- };
- const res = await this._request.send(ABORT, param);
- if (res.code)
- throw res;
- this.aborted = true;
- this.abortReason = customRollbackRes;
- return res;
- }
- }
- export async function startTransaction() {
- const transaction = new Transaction(this);
- await transaction.init();
- return transaction;
- }
- export async function runTransaction(callback, times = 3) {
- let transaction;
- try {
- transaction = new Transaction(this);
- await transaction.init();
- const callbackRes = await callback(transaction);
- if (transaction.aborted === true) {
- throw transaction.abortReason;
- }
- await transaction.commit();
- return callbackRes;
- }
- catch (error) {
- if (transaction.inited === false) {
- throw error;
- }
- const throwWithRollback = async (error) => {
- if (!transaction.aborted && !transaction.commited) {
- try {
- await transaction.rollback();
- }
- catch (err) {
- }
- throw error;
- }
- if (transaction.aborted === true) {
- throw transaction.abortReason;
- }
- throw error;
- };
- if (times <= 0) {
- await throwWithRollback(error);
- }
- if (error && error.code === ERRORS.DATABASE_TRANSACTION_CONFLICT.code) {
- return await runTransaction.bind(this)(callback, --times);
- }
- await throwWithRollback(error);
- }
- }
|