不要怂,就是干,撸起袖子干!

Commit fe4cded5 by Felix Becker Committed by Jan Aagaard Meier

ES6 refactor: Transaction (#6042)

* Make Transaction an ES6 class

* ES6 refactor of Transaction

let, const, arrow functions, export default
1 parent bf19d9a9
Showing with 152 additions and 160 deletions
'use strict'; 'use strict';
var Utils = require('./utils') const Utils = require('./utils');
, uuid = require('node-uuid'); const uuid = require('node-uuid');
/** /**
* The transaction object is used to identify a running transaction. It is created by calling `Sequelize.transaction()`. * The transaction object is used to identify a running transaction. It is created by calling `Sequelize.transaction()`.
...@@ -17,32 +17,153 @@ var Utils = require('./utils') ...@@ -17,32 +17,153 @@ var Utils = require('./utils')
* @param {String} options.isolationLevel=true Sets the isolation level of the transaction. * @param {String} options.isolationLevel=true Sets the isolation level of the transaction.
* @param {String} options.deferrable Sets the constraints to be deferred or immediately checked. * @param {String} options.deferrable Sets the constraints to be deferred or immediately checked.
*/ */
var Transaction = module.exports = function(sequelize, options) { class Transaction {
this.sequelize = sequelize; constructor(sequelize, options) {
this.savepoints = []; this.sequelize = sequelize;
this.savepoints = [];
// get dialect specific transaction options // get dialect specific transaction options
var transactionOptions = sequelize.dialect.supports.transactionOptions || {}; const transactionOptions = sequelize.dialect.supports.transactionOptions || {};
this.options = Utils._.extend({ this.options = Utils._.extend({
autocommit: transactionOptions.autocommit || null, autocommit: transactionOptions.autocommit || null,
type: sequelize.options.transactionType, type: sequelize.options.transactionType,
isolationLevel: sequelize.options.isolationLevel isolationLevel: sequelize.options.isolationLevel
}, options || {}); }, options || {});
this.parent = this.options.transaction; this.parent = this.options.transaction;
this.id = this.parent ? this.parent.id : uuid.v4(); this.id = this.parent ? this.parent.id : uuid.v4();
if (this.parent) { if (this.parent) {
this.id = this.parent.id; this.id = this.parent.id;
this.parent.savepoints.push(this); this.parent.savepoints.push(this);
this.name = this.id + '-savepoint-' + this.parent.savepoints.length; this.name = this.id + '-savepoint-' + this.parent.savepoints.length;
} else { } else {
this.id = this.name = uuid.v4(); this.id = this.name = uuid.v4();
}
delete this.options.transaction;
} }
delete this.options.transaction; /**
}; * Commit the transaction
*
* @return {Promise}
*/
commit() {
if (this.finished) {
throw new Error('Transaction cannot be committed because it has been finished with state: ' + this.finished);
}
this.$clearCls();
return this
.sequelize
.getQueryInterface()
.commitTransaction(this, this.options)
.finally(() => {
this.finished = 'commit';
if (!this.parent) {
return this.cleanup();
}
return null;
});
}
/**
* Rollback (abort) the transaction
*
* @return {Promise}
*/
rollback() {
if (this.finished) {
throw new Error('Transaction cannot be rolled back because it has been finished with state: ' + this.finished);
}
this.$clearCls();
return this
.sequelize
.getQueryInterface()
.rollbackTransaction(this, this.options)
.finally(() => {
if (!this.parent) {
return this.cleanup();
}
return this;
});
}
prepareEnvironment() {
return Utils.Promise.resolve(this.parent ? this.parent.connection : this.sequelize.connectionManager.getConnection({ uuid: this.id }))
.then(connection => {
this.connection = connection;
this.connection.uuid = this.id;
})
.then(() => this.begin())
.then(() => this.setDeferrable())
.then(() => this.setIsolationLevel())
.then(() => this.setAutocommit())
.catch(setupErr => this.rollback().finally(() => {
throw setupErr;
}))
.tap(() => {
if (this.sequelize.constructor.cls) {
this.sequelize.constructor.cls.set('transaction', this);
}
return null;
});
}
begin() {
return this
.sequelize
.getQueryInterface()
.startTransaction(this, this.options);
}
setDeferrable () {
if (this.options.deferrable) {
return this
.sequelize
.getQueryInterface()
.deferConstraints(this, this.options);
}
}
setAutocommit() {
return this
.sequelize
.getQueryInterface()
.setAutocommit(this, this.options.autocommit, this.options);
}
setIsolationLevel() {
return this
.sequelize
.getQueryInterface()
.setIsolationLevel(this, this.options.isolationLevel, this.options);
}
cleanup() {
const res = this.sequelize.connectionManager.releaseConnection(this.connection);
this.connection.uuid = undefined;
return res;
}
$clearCls () {
const cls = this.sequelize.constructor.cls;
if (cls) {
if (cls.get('transaction') === this) {
cls.set('transaction', null);
}
}
}
}
/** /**
* Types can be set per-transaction by passing `options.type` to `sequelize.transaction`. * Types can be set per-transaction by passing `options.type` to `sequelize.transaction`.
...@@ -62,15 +183,13 @@ var Transaction = module.exports = function(sequelize, options) { ...@@ -62,15 +183,13 @@ var Transaction = module.exports = function(sequelize, options) {
* Pass in the desired level as the first argument: * Pass in the desired level as the first argument:
* *
* ```js * ```js
* return sequelize.transaction({ * return sequelize.transaction({type: Sequelize.Transaction.EXCLUSIVE}, transaction => {
* type: Sequelize.Transaction.EXCLUSIVE
* }, function (t) {
* *
* // your transactions * // your transactions
* *
* }).then(function(result) { * }).then(result => {
* // transaction has been committed. Do something after the commit if required. * // transaction has been committed. Do something after the commit if required.
* }).catch(function(err) { * }).catch(err => {
* // do something with the err. * // do something with the err.
* }); * });
* ``` * ```
...@@ -83,7 +202,6 @@ Transaction.TYPES = { ...@@ -83,7 +202,6 @@ Transaction.TYPES = {
EXCLUSIVE: 'EXCLUSIVE' EXCLUSIVE: 'EXCLUSIVE'
}; };
/** /**
* Isolations levels can be set per-transaction by passing `options.isolationLevel` to `sequelize.transaction`. * Isolations levels can be set per-transaction by passing `options.isolationLevel` to `sequelize.transaction`.
* Default to `REPEATABLE_READ` but you can override the default isolation level by passing `options.isolationLevel` in `new Sequelize`. * Default to `REPEATABLE_READ` but you can override the default isolation level by passing `options.isolationLevel` in `new Sequelize`.
...@@ -102,15 +220,13 @@ Transaction.TYPES = { ...@@ -102,15 +220,13 @@ Transaction.TYPES = {
* Pass in the desired level as the first argument: * Pass in the desired level as the first argument:
* *
* ```js * ```js
* return sequelize.transaction({ * return sequelize.transaction({isolationLevel: Sequelize.Transaction.SERIALIZABLE}, transaction => {
* isolationLevel: Sequelize.Transaction.SERIALIZABLE
* }, function (t) {
* *
* // your transactions * // your transactions
* *
* }).then(function(result) { * }).then(result => {
* // transaction has been committed. Do something after the commit if required. * // transaction has been committed. Do something after the commit if required.
* }).catch(function(err) { * }).catch(err => {
* // do something with the err. * // do something with the err.
* }); * });
* ``` * ```
...@@ -168,130 +284,6 @@ Transaction.LOCK = Transaction.prototype.LOCK = { ...@@ -168,130 +284,6 @@ Transaction.LOCK = Transaction.prototype.LOCK = {
NO_KEY_UPDATE: 'NO KEY UPDATE' NO_KEY_UPDATE: 'NO KEY UPDATE'
}; };
/** module.exports = Transaction;
* Commit the transaction module.exports.Transaction = Transaction;
* module.exports.default = Transaction;
* @return {Promise}
*/
Transaction.prototype.commit = function() {
var self = this;
if (this.finished) {
throw new Error('Transaction cannot be committed because it has been finished with state: ' + self.finished);
}
this.$clearCls();
return this
.sequelize
.getQueryInterface()
.commitTransaction(this, this.options)
.finally(function() {
self.finished = 'commit';
if (!self.parent) {
return self.cleanup();
}
return null;
});
};
/**
* Rollback (abort) the transaction
*
* @return {Promise}
*/
Transaction.prototype.rollback = function() {
var self = this;
if (this.finished) {
throw new Error('Transaction cannot be rolled back because it has been finished with state: ' + self.finished);
}
this.$clearCls();
return this
.sequelize
.getQueryInterface()
.rollbackTransaction(this, this.options)
.finally(function() {
if (!self.parent) {
return self.cleanup();
}
return self;
});
};
Transaction.prototype.prepareEnvironment = function() {
var self = this;
return Utils.Promise.resolve(
self.parent ? self.parent.connection : self.sequelize.connectionManager.getConnection({ uuid: self.id })
).then(function (connection) {
self.connection = connection;
self.connection.uuid = self.id;
}).then(function () {
return self.begin();
}).then(function () {
return self.setDeferrable();
}).then(function () {
return self.setIsolationLevel();
}).then(function () {
return self.setAutocommit();
}).catch(function (setupErr) {
return self.rollback().finally(function () {
throw setupErr;
});
}).tap(function () {
if (self.sequelize.constructor.cls) {
self.sequelize.constructor.cls.set('transaction', self);
}
return null;
});
};
Transaction.prototype.begin = function() {
return this
.sequelize
.getQueryInterface()
.startTransaction(this, this.options);
};
Transaction.prototype.setDeferrable = function () {
if (this.options.deferrable) {
return this
.sequelize
.getQueryInterface()
.deferConstraints(this, this.options);
}
};
Transaction.prototype.setAutocommit = function() {
return this
.sequelize
.getQueryInterface()
.setAutocommit(this, this.options.autocommit, this.options);
};
Transaction.prototype.setIsolationLevel = function() {
return this
.sequelize
.getQueryInterface()
.setIsolationLevel(this, this.options.isolationLevel, this.options);
};
Transaction.prototype.cleanup = function() {
var res = this.sequelize.connectionManager.releaseConnection(this.connection);
this.connection.uuid = undefined;
return res;
};
Transaction.prototype.$clearCls = function () {
var cls = this.sequelize.constructor.cls;
if (cls) {
if (cls.get('transaction') === this) {
cls.set('transaction', null);
}
}
};
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!