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

Commit 437b8499 by Daniel Sim Committed by Sushant

read-only transactions for read replicas (#7329)

1 parent 5da749c8
# Future
- [ADDED] Ability to run transactions on a read-replica by marking transactions as read only [#7323](https://github.com/sequelize/sequelize/issues/7323)
- [FIXED] Add quotes around column names for unique constraints in sqlite [#4407](https://github.com/sequelize/sequelize/issues/4407)
# 3.30.2
......
......@@ -15,6 +15,8 @@ var Utils = require('./utils');
* @param {String} options.type=true Sets the type 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.readOnly=false Sets the read-only property of the transaction. Such transactions
* will use read replicas when available
*/
function Transaction(sequelize, options) {
this.sequelize = sequelize;
......@@ -24,7 +26,8 @@ function Transaction(sequelize, options) {
this.options = Utils._.extend({
autocommit: true,
type: sequelize.options.transactionType,
isolationLevel: sequelize.options.isolationLevel
isolationLevel: sequelize.options.isolationLevel,
readOnly: false
}, options || {});
this.parent = this.options.transaction;
......@@ -221,10 +224,22 @@ Transaction.prototype.rollback = function() {
Transaction.prototype.prepareEnvironment = function() {
var self = this;
var connectionPromise;
return Utils.Promise.resolve(
self.parent ? self.parent.connection : self.sequelize.connectionManager.getConnection({ uuid: self.id })
).then(function (connection) {
if (this.parent) {
connectionPromise = Utils.Promise.resolve(this.parent.connection);
} else {
var acquireOptions = {uuid: this.id};
if (this.options.readOnly) {
acquireOptions.type = 'SELECT';
}
connectionPromise = this.sequelize.connectionManager.getConnection(acquireOptions);
}
return connectionPromise
.then(function (connection) {
self.connection = connection;
self.connection.uuid = self.id;
}).then(function () {
......
......@@ -6,12 +6,20 @@ var chai = require('chai')
, expect = chai.expect
, Support = require(__dirname + '/support')
, DataTypes = require(__dirname + '/../../lib/data-types')
, dialect = Support.getTestDialect();
, dialect = Support.getTestDialect()
, sinon = require('sinon');
describe(Support.getTestDialectTeaser('Replication'), function() {
if (dialect === 'sqlite') return;
var sandbox;
var readSpy, writeSpy;
beforeEach(function () {
var self = this;
sandbox = sinon.sandbox.create();
this.sequelize = Support.getSequelizeInstance(null, null, null, {
replication: {
write: Support.getConnectionOptions(),
......@@ -29,16 +37,52 @@ describe(Support.getTestDialectTeaser('Replication'), function() {
}
});
return this.User.sync({force: true});
return this.User.sync({force: true})
.then(function () {
readSpy = sandbox.spy(self.sequelize.connectionManager.pool.read, 'acquire');
writeSpy = sandbox.spy(self.sequelize.connectionManager.pool.write, 'acquire');
});
});
afterEach(function () {
sandbox.restore();
});
function expectReadCalls() {
chai.expect(readSpy.callCount).least(1);
chai.expect(writeSpy.notCalled).eql(true);
}
function expectWriteCalls() {
chai.expect(writeSpy.callCount).least(1);
chai.expect(readSpy.notCalled).eql(true);
}
it('should be able to make a write', function () {
return this.User.create({
firstName: Math.random().toString()
});
})
.then(expectWriteCalls);
});
it('should be able to make a read', function () {
return this.User.findAll();
return this.User.findAll()
.then(expectReadCalls);
});
it('should run read-only transactions on the replica', function () {
var self = this;
return this.sequelize.transaction({readOnly: true}, function (transaction) {
return self.User.findAll({transaction: transaction});
})
.then(expectReadCalls);
});
it('should run non-read-only transactions on the primary', function () {
var self = this;
return self.sequelize.transaction(function (transaction) {
return self.User.findAll({transaction: transaction});
})
.then(expectWriteCalls);
});
});
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!