feathers-knex
Version:
A service plugin for KnexJS a query builder for PostgreSQL, MySQL and SQLite3
105 lines (81 loc) • 2.4 kB
JavaScript
const debug = require('debug')('feathers-knex-transaction');
const ROLLBACK = { rollback: true };
const getKnex = (hook) => {
const knex = hook.service.Model;
return knex && typeof knex.transaction === 'function' ? knex : undefined;
};
const start = (options = {}) => {
options = Object.assign({ getKnex }, options);
return hook => {
const { transaction } = hook.params;
const parent = transaction;
const knex = transaction ? transaction.trx : options.getKnex(hook);
if (!knex) {
return;
}
return new Promise((resolve, reject) => {
const transaction = {};
if (parent) {
transaction.parent = parent;
transaction.committed = parent.committed;
} else {
transaction.committed = new Promise(resolve => {
transaction.resolve = resolve;
});
}
transaction.starting = true;
transaction.promise = knex.transaction(trx => {
transaction.trx = trx;
transaction.id = Date.now();
hook.params = { ...hook.params, transaction };
debug('started a new transaction %s', transaction.id);
resolve();
}).catch((error) => {
if (transaction.starting) {
reject(error);
} else if (error !== ROLLBACK) {
throw error;
}
});
});
};
};
const end = () => {
return hook => {
const { transaction } = hook.params;
if (!transaction) {
return;
}
const { trx, id, promise, parent } = transaction;
hook.params = { ...hook.params, transaction: parent };
transaction.starting = false;
return trx.commit()
.then(() => promise)
.then(() => transaction.resolve && transaction.resolve(true))
.then(() => debug('ended transaction %s', id))
.then(() => hook);
};
};
const rollback = () => {
return hook => {
const { transaction } = hook.params;
if (!transaction) {
return;
}
const { trx, id, promise, parent } = transaction;
hook.params = { ...hook.params, transaction: parent };
transaction.starting = false;
return trx.rollback(ROLLBACK)
.then(() => promise)
.then(() => transaction.resolve && transaction.resolve(false))
.then(() => debug('rolled back transaction %s', id))
.then(() => hook);
};
};
module.exports = {
transaction: {
start,
end,
rollback
}
};