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

Commit 2a78517d by Sushant Committed by GitHub

Generic Pool Update (#7109)

* generic pool update and other fixes

* connection internally removed

* doc entry

* review changes

* pooling changes
1 parent ee8194e5
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
- [FIXED] Enforce unique association aliases [#7025](https://github.com/sequelize/sequelize/pull/7025) - [FIXED] Enforce unique association aliases [#7025](https://github.com/sequelize/sequelize/pull/7025)
- [FIXED] Information warnings when findAll is given incorrect inputs [#7047](https://github.com/sequelize/sequelize/pull/7047) - [FIXED] Information warnings when findAll is given incorrect inputs [#7047](https://github.com/sequelize/sequelize/pull/7047)
- [FIXED] scope method syntax loses parameters when used multiple times [#7058](https://github.com/sequelize/sequelize/issues/7058) - [FIXED] scope method syntax loses parameters when used multiple times [#7058](https://github.com/sequelize/sequelize/issues/7058)
- [INTERNAL] Updated to `generic-pool@3.1.6` [#7109](https://github.com/sequelize/sequelize/issues/7109)
## BC breaks: ## BC breaks:
- `DATEONLY` now returns string in `YYYY-MM-DD` format rather than `Date` type - `DATEONLY` now returns string in `YYYY-MM-DD` format rather than `Date` type
......
...@@ -130,7 +130,7 @@ class ConnectionManager extends AbstractConnectionManager { ...@@ -130,7 +130,7 @@ class ConnectionManager extends AbstractConnectionManager {
const connection = connectionLock.unwrap(); const connection = connectionLock.unwrap();
// Dont disconnect a connection that is already disconnected // Dont disconnect a connection that is already disconnected
if (!!connection.closed) { if (connection.closed) {
return Promise.resolve(); return Promise.resolve();
} }
...@@ -143,7 +143,6 @@ class ConnectionManager extends AbstractConnectionManager { ...@@ -143,7 +143,6 @@ class ConnectionManager extends AbstractConnectionManager {
validate(connectionLock) { validate(connectionLock) {
const connection = connectionLock.unwrap(); const connection = connectionLock.unwrap();
return connection && connection.loggedIn; return connection && connection.loggedIn;
} }
} }
......
'use strict'; 'use strict';
var _ = require('lodash') const _ = require('lodash');
, Abstract = require('../abstract') const AbstractDialect = require('../abstract');
, ConnectionManager = require('./connection-manager') const ConnectionManager = require('./connection-manager');
, Query = require('./query') const Query = require('./query');
, QueryGenerator = require('./query-generator') const QueryGenerator = require('./query-generator');
, DataTypes = require('../../data-types').mssql; const DataTypes = require('../../data-types').mssql;
var MssqlDialect = function(sequelize) { class MssqlDialect extends AbstractDialect {
this.sequelize = sequelize; constructor(sequelize) {
this.connectionManager = new ConnectionManager(this, sequelize); super();
this.connectionManager.initPools(); this.sequelize = sequelize;
this.QueryGenerator = _.extend({}, QueryGenerator, { this.connectionManager = new ConnectionManager(this, sequelize);
options: sequelize.options, this.QueryGenerator = _.extend({}, QueryGenerator, {
_dialect: this, options: sequelize.options,
sequelize _dialect: this,
}); sequelize
}; });
}
}
MssqlDialect.prototype.supports = _.merge(_.cloneDeep(Abstract.prototype.supports), { MssqlDialect.prototype.supports = _.merge(_.cloneDeep(AbstractDialect.prototype.supports), {
'DEFAULT': true, 'DEFAULT': true,
'DEFAULT VALUES': true, 'DEFAULT VALUES': true,
'LIMIT ON UPDATE': true, 'LIMIT ON UPDATE': true,
...@@ -51,7 +53,7 @@ MssqlDialect.prototype.supports = _.merge(_.cloneDeep(Abstract.prototype.support ...@@ -51,7 +53,7 @@ MssqlDialect.prototype.supports = _.merge(_.cloneDeep(Abstract.prototype.support
tmpTableTrigger: true tmpTableTrigger: true
}); });
MssqlDialect.prototype.defaultVersion = '12.0.2000'; // SQL Server 2014 Express ConnectionManager.prototype.defaultVersion = '12.0.2000'; // SQL Server 2014 Express
MssqlDialect.prototype.Query = Query; MssqlDialect.prototype.Query = Query;
MssqlDialect.prototype.name = 'mssql'; MssqlDialect.prototype.name = 'mssql';
MssqlDialect.prototype.TICK_CHAR = '"'; MssqlDialect.prototype.TICK_CHAR = '"';
......
'use strict'; 'use strict';
var _ = require('lodash') const _ = require('lodash');
, Abstract = require('../abstract') const AbstractDialect = require('../abstract');
, ConnectionManager = require('./connection-manager') const ConnectionManager = require('./connection-manager');
, Query = require('./query') const Query = require('./query');
, QueryGenerator = require('./query-generator') const QueryGenerator = require('./query-generator');
, DataTypes = require('../../data-types').mysql; const DataTypes = require('../../data-types').mysql;
var MysqlDialect = function(sequelize) { class MysqlDialect extends AbstractDialect {
this.sequelize = sequelize; constructor(sequelize) {
this.connectionManager = new ConnectionManager(this, sequelize); super();
this.connectionManager.initPools(); this.sequelize = sequelize;
this.QueryGenerator = _.extend({}, QueryGenerator, { this.connectionManager = new ConnectionManager(this, sequelize);
options: sequelize.options, this.QueryGenerator = _.extend({}, QueryGenerator, {
_dialect: this, options: sequelize.options,
sequelize _dialect: this,
}); sequelize
}; });
}
}
MysqlDialect.prototype.supports = _.merge(_.cloneDeep(Abstract.prototype.supports), { MysqlDialect.prototype.supports = _.merge(_.cloneDeep(AbstractDialect.prototype.supports), {
'VALUES ()': true, 'VALUES ()': true,
'LIMIT ON UPDATE': true, 'LIMIT ON UPDATE': true,
'IGNORE': ' IGNORE', 'IGNORE': ' IGNORE',
......
...@@ -45,8 +45,8 @@ class ConnectionManager extends AbstractConnectionManager { ...@@ -45,8 +45,8 @@ class ConnectionManager extends AbstractConnectionManager {
if (dataType.types.postgres.array_oids) { if (dataType.types.postgres.array_oids) {
for (const oid of dataType.types.postgres.array_oids) { for (const oid of dataType.types.postgres.array_oids) {
this.lib.types.setTypeParser(oid, value => this.lib.types.setTypeParser(oid, value =>
this.lib.types.arrayParser.create(value, value => this.lib.types.arrayParser.create(value, (v) =>
dataType.parse(value, oid, this.lib.types.getTypeParser) dataType.parse(v, oid, this.lib.types.getTypeParser)
).parse() ).parse()
); );
} }
...@@ -172,7 +172,7 @@ class ConnectionManager extends AbstractConnectionManager { ...@@ -172,7 +172,7 @@ class ConnectionManager extends AbstractConnectionManager {
}); });
} }
disconnect(connection) { disconnect(connection) {
return new Promise((resolve, reject) => { return new Promise(resolve => {
connection.end(); connection.end();
resolve(); resolve();
}); });
......
...@@ -12,8 +12,6 @@ class PostgresDialect extends AbstractDialect { ...@@ -12,8 +12,6 @@ class PostgresDialect extends AbstractDialect {
super(); super();
this.sequelize = sequelize; this.sequelize = sequelize;
this.connectionManager = new ConnectionManager(this, sequelize); this.connectionManager = new ConnectionManager(this, sequelize);
this.connectionManager.initPools();
this.QueryGenerator = _.extend({}, QueryGenerator, { this.QueryGenerator = _.extend({}, QueryGenerator, {
options: sequelize.options, options: sequelize.options,
_dialect: this, _dialect: this,
......
...@@ -84,7 +84,8 @@ const _ = require('lodash'); ...@@ -84,7 +84,8 @@ const _ = require('lodash');
* @param {Integer} [options.pool.max] Maximum number of connection in pool. Default is 5 * @param {Integer} [options.pool.max] Maximum number of connection in pool. Default is 5
* @param {Integer} [options.pool.min] Minimum number of connection in pool. Default is 0 * @param {Integer} [options.pool.min] Minimum number of connection in pool. Default is 0
* @param {Integer} [options.pool.idle] The maximum time, in milliseconds, that a connection can be idle before being released * @param {Integer} [options.pool.idle] The maximum time, in milliseconds, that a connection can be idle before being released
* @param {Function} [options.pool.validateConnection] A function that validates a connection. Called with client. The default function checks that client is an object, and that its state is not disconnected * @param {Integer} [options.pool.acquire] The maximum time, in milliseconds, that pool will try to get connection before throwing error
* @param {Function} [options.pool.validate] A function that validates a connection. Called with client. The default function checks that client is an object, and that its state is not disconnected
* @param {Boolean} [options.quoteIdentifiers=true] Set to `false` to make table names and attributes case-insensitive on Postgres and skip double quoting of them. * @param {Boolean} [options.quoteIdentifiers=true] Set to `false` to make table names and attributes case-insensitive on Postgres and skip double quoting of them.
* @param {String} [options.transactionType='DEFERRED'] Set the default transaction type. See `Sequelize.Transaction.TYPES` for possible options. Sqlite only. * @param {String} [options.transactionType='DEFERRED'] Set the default transaction type. See `Sequelize.Transaction.TYPES` for possible options. Sqlite only.
* @param {String} [options.isolationLevel] Set the default transaction isolation level. See `Sequelize.Transaction.ISOLATION_LEVELS` for possible options. * @param {String} [options.isolationLevel] Set the default transaction isolation level. See `Sequelize.Transaction.ISOLATION_LEVELS` for possible options.
...@@ -265,10 +266,6 @@ class Sequelize { ...@@ -265,10 +266,6 @@ class Sequelize {
Sequelize.runHooks('afterInit', this); Sequelize.runHooks('afterInit', this);
} }
get connectorManager() {
return this.transactionManager.getConnectorManager();
}
refreshTypes() { refreshTypes() {
this.connectionManager.refreshTypeParser(DataTypes); this.connectionManager.refreshTypeParser(DataTypes);
} }
...@@ -500,7 +497,7 @@ class Sequelize { ...@@ -500,7 +497,7 @@ class Sequelize {
if (options.replacements && options.bind) { if (options.replacements && options.bind) {
throw new Error('Both `replacements` and `bind` cannot be set at the same time'); throw new Error('Both `replacements` and `bind` cannot be set at the same time');
} }
if (options.replacements) { if (options.replacements) {
if (Array.isArray(options.replacements)) { if (Array.isArray(options.replacements)) {
sql = Utils.format([sql].concat(options.replacements), this.options.dialect); sql = Utils.format([sql].concat(options.replacements), this.options.dialect);
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
"depd": "^1.1.0", "depd": "^1.1.0",
"dottie": "^2.0.0", "dottie": "^2.0.0",
"env-cmd": "^4.0.0", "env-cmd": "^4.0.0",
"generic-pool": "^2.4.4", "generic-pool": "^3.1.6",
"inflection": "1.10.0", "inflection": "1.10.0",
"lodash": "^4.17.1", "lodash": "^4.17.1",
"moment": "^2.13.0", "moment": "^2.13.0",
......
...@@ -46,7 +46,7 @@ describe(Support.getTestDialectTeaser('Multiple Level Filters'), function() { ...@@ -46,7 +46,7 @@ describe(Support.getTestDialectTeaser('Multiple Level Filters'), function() {
return Task.findAll({ return Task.findAll({
include: [ include: [
{ {
model: Project, model: Project,
include: [ include: [
{model: User, where: {username: 'leia'}} {model: User, where: {username: 'leia'}}
], ],
...@@ -105,7 +105,7 @@ describe(Support.getTestDialectTeaser('Multiple Level Filters'), function() { ...@@ -105,7 +105,7 @@ describe(Support.getTestDialectTeaser('Multiple Level Filters'), function() {
return Task.findAll({ return Task.findAll({
include: [ include: [
{ {
model: Project, model: Project,
include: [ include: [
{model: User, where: { {model: User, where: {
username: 'leia', username: 'leia',
...@@ -166,7 +166,7 @@ describe(Support.getTestDialectTeaser('Multiple Level Filters'), function() { ...@@ -166,7 +166,7 @@ describe(Support.getTestDialectTeaser('Multiple Level Filters'), function() {
return User.findAll({ return User.findAll({
include: [ include: [
{ {
model: Project, model: Project,
include: [ include: [
{model: Task, where: {title: 'fight empire'}} {model: Task, where: {title: 'fight empire'}}
], ],
......
...@@ -18,7 +18,7 @@ var poolEntry = { ...@@ -18,7 +18,7 @@ var poolEntry = {
pool: {} pool: {}
}; };
describe('Connction Manager', function() { describe('Connection Manager', function() {
var sandbox; var sandbox;
...@@ -37,7 +37,7 @@ describe('Connction Manager', function() { ...@@ -37,7 +37,7 @@ describe('Connction Manager', function() {
var sequelize = Support.createSequelizeInstance(options); var sequelize = Support.createSequelizeInstance(options);
var connectionManager = new ConnectionManager(Support.getTestDialect(), sequelize); var connectionManager = new ConnectionManager(Support.getTestDialect(), sequelize);
var poolSpy = sandbox.spy(Pooling, 'Pool'); var poolSpy = sandbox.spy(Pooling, 'createPool');
connectionManager.initPools(); connectionManager.initPools();
expect(poolSpy.calledOnce).to.be.true; expect(poolSpy.calledOnce).to.be.true;
}); });
...@@ -52,7 +52,7 @@ describe('Connction Manager', function() { ...@@ -52,7 +52,7 @@ describe('Connction Manager', function() {
var sequelize = Support.createSequelizeInstance(options); var sequelize = Support.createSequelizeInstance(options);
var connectionManager = new ConnectionManager(Support.getTestDialect(), sequelize); var connectionManager = new ConnectionManager(Support.getTestDialect(), sequelize);
var poolSpy = sandbox.spy(Pooling, 'Pool'); var poolSpy = sandbox.spy(Pooling, 'createPool');
connectionManager.initPools(); connectionManager.initPools();
expect(poolSpy.calledTwice).to.be.true; expect(poolSpy.calledTwice).to.be.true;
}); });
......
...@@ -22,10 +22,8 @@ if (dialect.match(/^mssql/)) { ...@@ -22,10 +22,8 @@ if (dialect.match(/^mssql/)) {
conn = connection; conn = connection;
// simulate a unexpected end // simulate a unexpected end
connection.unwrap().emit('error', {code: 'ECONNRESET'}); // connection removed from pool by MSSQL Conn Manager
}) conn.unwrap().emit('error', {code: 'ECONNRESET'});
.then(function() {
return cm.releaseConnection(conn);
}) })
.then(function() { .then(function() {
// Get next available connection // Get next available connection
......
...@@ -9,7 +9,7 @@ var chai = require('chai') ...@@ -9,7 +9,7 @@ var chai = require('chai')
, DataTypes = require(__dirname + '/../../../../lib/data-types'); , DataTypes = require(__dirname + '/../../../../lib/data-types');
if (dialect === 'mysql') { if (dialect === 'mysql') {
describe('[MYSQL Specific] Connector Manager', function() { describe('[MYSQL Specific] Connection Manager', function() {
it('works correctly after being idle', function() { it('works correctly after being idle', function() {
var User = this.sequelize.define('User', { username: DataTypes.STRING }) var User = this.sequelize.define('User', { username: DataTypes.STRING })
, spy = sinon.spy() , spy = sinon.spy()
......
'use strict';
/* jshint -W030 */
/* jshint -W110 */
const chai = require('chai');
const expect = chai.expect;
const Support = require(__dirname + '/support');
const dialect = Support.getTestDialect();
const sinon = require('sinon');
const Sequelize = Support.Sequelize;
describe(Support.getTestDialectTeaser('Pooling'), function() {
if (dialect === 'sqlite') return;
beforeEach(() => {
this.sinon = sinon.sandbox.create();
});
afterEach(() => {
this.sinon.restore();
});
it('should reject when unable to acquire connection in given time', () => {
this.testInstance = new Sequelize('localhost', 'ffd', 'dfdf', {
dialect,
databaseVersion: '1.2.3',
pool: {
acquire: 1000 //milliseconds
}
});
this.sinon.stub(this.testInstance.connectionManager, '_connect', () => new Sequelize.Promise(() => {}));
return expect(this.testInstance.authenticate())
.to.eventually.be.rejectedWith('TimeoutError: ResourceRequest timed out');
});
});
...@@ -2,16 +2,16 @@ ...@@ -2,16 +2,16 @@
/* jshint -W030 */ /* jshint -W030 */
/* jshint -W110 */ /* jshint -W110 */
var chai = require('chai') const chai = require('chai');
, expect = chai.expect const expect = chai.expect;
, Support = require(__dirname + '/support') const Support = require(__dirname + '/support');
, DataTypes = require(__dirname + '/../../lib/data-types') const DataTypes = require(__dirname + '/../../lib/data-types');
, dialect = Support.getTestDialect(); const dialect = Support.getTestDialect();
describe(Support.getTestDialectTeaser('Replication'), function() { describe(Support.getTestDialectTeaser('Replication'), function() {
if (dialect === 'sqlite') return; if (dialect === 'sqlite') return;
beforeEach(function () { beforeEach(() => {
this.sequelize = Support.getSequelizeInstance(null, null, null, { this.sequelize = Support.getSequelizeInstance(null, null, null, {
replication: { replication: {
write: Support.getConnectionOptions(), write: Support.getConnectionOptions(),
...@@ -32,13 +32,13 @@ describe(Support.getTestDialectTeaser('Replication'), function() { ...@@ -32,13 +32,13 @@ describe(Support.getTestDialectTeaser('Replication'), function() {
return this.User.sync({force: true}); return this.User.sync({force: true});
}); });
it('should be able to make a write', function () { it('should be able to make a write', () => {
return this.User.create({ return this.User.create({
firstName: Math.random().toString() firstName: Math.random().toString()
}); });
}); });
it('should be able to make a read', function () { it('should be able to make a read', () => {
return this.User.findAll(); return this.User.findAll();
}); });
}); });
\ No newline at end of file
'use strict'; 'use strict';
/* jshint -W030 */ /* jshint -W030 */
var chai = require('chai') const chai = require('chai');
, expect = chai.expect const expect = chai.expect;
, sinon = require('sinon') const sinon = require('sinon');
, Support = require(__dirname + '/support') const Support = require(__dirname + '/support');
, Sequelize = Support.Sequelize const Sequelize = Support.Sequelize;
, dialect = Support.getTestDialect() const dialect = Support.getTestDialect();
, current = Support.sequelize const current = Support.sequelize;
, Promise = Sequelize.Promise;
describe('Transaction', function() { describe('Transaction', function() {
before(() => {
before(function () { this.stub = sinon.stub(current, 'query').returns(Sequelize.Promise.resolve({}));
this.stub = sinon.stub(current, 'query').returns(Promise.resolve({}));
this.stubConnection = sinon.stub(current.connectionManager, 'getConnection') this.stubConnection = sinon.stub(current.connectionManager, 'getConnection')
.returns(Promise.resolve({ uuid: 'ssfdjd-434fd-43dfg23-2d', close : function() { }})); .returns(Sequelize.Promise.resolve({
uuid: 'ssfdjd-434fd-43dfg23-2d',
close(){}
}));
this.stubRelease = sinon.stub(current.connectionManager, 'releaseConnection')
.returns(Sequelize.Promise.resolve());
}); });
beforeEach(function () { beforeEach(() => {
this.stub.reset(); this.stub.reset();
this.stubConnection.reset(); this.stubConnection.reset();
this.stubRelease.reset();
}); });
after(function () { after(() => {
this.stub.restore(); this.stub.restore();
this.stubConnection.restore(); this.stubConnection.restore();
}); });
it('should run auto commit query only when needed', function() { it('should run auto commit query only when needed', () => {
var expectations = { const expectations = {
all: [ all: [
'START TRANSACTION;' 'START TRANSACTION;'
], ],
...@@ -43,7 +48,7 @@ describe('Transaction', function() { ...@@ -43,7 +48,7 @@ describe('Transaction', function() {
}; };
return current.transaction(() => { return current.transaction(() => {
expect(this.stub.args.map(arg => arg[0])).to.deep.equal(expectations[dialect] || expectations.all); expect(this.stub.args.map(arg => arg[0])).to.deep.equal(expectations[dialect] || expectations.all);
return Promise.resolve(); return Sequelize.Promise.resolve();
}); });
}); });
}); });
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!