mirror of
https://github.com/knex/knex.git
synced 2025-07-07 09:01:19 +00:00
95 lines
3.1 KiB
JavaScript
95 lines
3.1 KiB
JavaScript
'use strict';
|
|
|
|
// Transaction
|
|
// -------
|
|
var Promise = require('./promise');
|
|
var inherits = require('inherits');
|
|
var EventEmitter = require('events').EventEmitter;
|
|
|
|
// Creates a new wrapper object for constructing a transaction.
|
|
// Called by the `knex.transaction`, which sets the correct client
|
|
// and handles the `container` object, passing along the correct
|
|
// `connection` to keep all of the transactions on the correct connection.
|
|
function Transaction(container) {
|
|
this.container = container;
|
|
}
|
|
inherits(Transaction, EventEmitter);
|
|
|
|
// Build the knex instance passed around inside the transaction container.
|
|
// It can be used both as a fully functional knex instance, or assimilated
|
|
// into existing knex chains via the ".transacting" method call.
|
|
Transaction.prototype.containerObject = function(runner) {
|
|
var Knex = require('../knex');
|
|
|
|
// Create an entirely new knex instance just for this transaction
|
|
var transactor = Knex.initialize({
|
|
__client__ : this.client,
|
|
__transactor__ : {_runner: runner}
|
|
});
|
|
|
|
// Remove the ability to start a transaction or destroy
|
|
// the entire pool within a transaction.
|
|
transactor.destroy = transactor.transaction = void 0;
|
|
|
|
// Commits the transaction:
|
|
transactor.commit = function(message) {
|
|
runner.finishTransaction(0, transactor, message);
|
|
};
|
|
|
|
// Rolls back the transaction.
|
|
transactor.rollback = function(error) {
|
|
runner.finishTransaction(1, transactor, error);
|
|
};
|
|
|
|
transactor._runner = runner;
|
|
|
|
return transactor;
|
|
};
|
|
|
|
Transaction.prototype.initiateDeferred = function(transactor) {
|
|
|
|
// Initiate a deferred object, bound to the container object,
|
|
// so we know when the transaction completes or fails
|
|
// and can continue from there.
|
|
var dfd = transactor.__dfd__ = Promise.pending();
|
|
|
|
// Call the container with the transaction
|
|
// commit & rollback objects.
|
|
var result = this.container(transactor);
|
|
|
|
// If we've returned a "thenable" from the transaction container,
|
|
// and it's got the transaction object we're running for this, assume
|
|
// the rollback and commit are chained to this object's success / failure.
|
|
if (result && result.then && typeof result.then === 'function') {
|
|
result.then(function(val) { transactor.commit(val); }).catch(function(err) { transactor.rollback(err); });
|
|
}
|
|
|
|
// Return the promise for the entire transaction.
|
|
return dfd.promise;
|
|
};
|
|
|
|
// Allow the `Transaction` object to be utilized with full access to the relevant
|
|
// promise API.
|
|
require('./interface')(Transaction);
|
|
|
|
// Passed a `container` function, this method runs the current
|
|
// transaction, returning a promise.
|
|
Transaction.prototype.then = function(onFulfilled, onRejected) {
|
|
var Runner = this.client.Runner;
|
|
var promise = this;
|
|
|
|
// Create a new "runner" object, passing the "runner"
|
|
// object along, so we can easily keep track of every
|
|
// query run on the current connection.
|
|
return new Runner(this)
|
|
.startTransaction()
|
|
.then(function(obj) {
|
|
return promise.containerObject(obj);
|
|
})
|
|
.then(function(obj) {
|
|
return promise.initiateDeferred(obj);
|
|
})
|
|
.then(onFulfilled, onRejected);
|
|
};
|
|
|
|
module.exports = Transaction; |