connection-manager.test.js
4.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
'use strict';
const chai = require('chai'),
expect = chai.expect,
Support = require(__dirname + '/../../support'),
sinon = require('sinon'),
Config = require(__dirname + '/../../../config/config'),
ConnectionManager = require(__dirname + '/../../../../lib/dialects/abstract/connection-manager'),
Pooling = require('generic-pool'),
_ = require('lodash'),
Promise = require(__dirname + '/../../../../lib/promise');
const baseConf = Config[Support.getTestDialect()];
const poolEntry = {
host: baseConf.host,
port: baseConf.port,
pool: {}
};
describe('Connection Manager', () => {
let sandbox;
beforeEach(() => {
sandbox = sinon.createSandbox();
});
afterEach(() => {
sandbox.restore();
});
it('should initialize a single pool without replication', () => {
const options = {
replication: null
};
const sequelize = Support.createSequelizeInstance(options);
const connectionManager = new ConnectionManager(Support.getTestDialect(), sequelize);
const poolSpy = sandbox.spy(Pooling, 'createPool');
connectionManager.initPools();
expect(poolSpy.calledOnce).to.be.true;
});
it('should initialize a multiple pools with replication', () => {
const options = {
replication: {
write: _.clone(poolEntry),
read: [_.clone(poolEntry), _.clone(poolEntry)]
}
};
const sequelize = Support.createSequelizeInstance(options);
const connectionManager = new ConnectionManager(Support.getTestDialect(), sequelize);
const poolSpy = sandbox.spy(Pooling, 'createPool');
connectionManager.initPools();
expect(poolSpy.calledTwice).to.be.true;
});
it('should round robin calls to the read pool', () => {
if (Support.getTestDialect() === 'sqlite') {
return;
}
const slave1 = _.clone(poolEntry);
const slave2 = _.clone(poolEntry);
slave1.host = 'slave1';
slave2.host = 'slave2';
const options = {
replication: {
write: _.clone(poolEntry),
read: [slave1, slave2]
}
};
const sequelize = Support.createSequelizeInstance(options);
const connectionManager = new ConnectionManager(Support.getTestDialect(), sequelize);
const resolvedPromise = new Promise(resolve => {
resolve({
queryType: 'read'
});
});
const connectStub = sandbox.stub(connectionManager, '_connect').returns(resolvedPromise);
sandbox.stub(connectionManager, '_disconnect').returns(resolvedPromise);
sandbox.stub(sequelize, 'databaseVersion').returns(resolvedPromise);
connectionManager.initPools();
const queryOptions = {
priority: 0,
type: 'SELECT',
useMaster: false
};
const _getConnection = _.bind(connectionManager.getConnection, connectionManager, queryOptions);
return _getConnection()
.then(_getConnection)
.then(_getConnection)
.then(() => {
chai.expect(connectStub.callCount).to.equal(4);
// First call is the get connection for DB versions - ignore
const calls = connectStub.getCalls();
chai.expect(calls[1].args[0].host).to.eql('slave1');
chai.expect(calls[2].args[0].host).to.eql('slave2');
chai.expect(calls[3].args[0].host).to.eql('slave1');
});
});
it('should allow forced reads from the write pool', () => {
const master = _.clone(poolEntry);
master.host = 'the-boss';
const options = {
replication: {
write: master,
read: [_.clone(poolEntry)]
}
};
const sequelize = Support.createSequelizeInstance(options);
const connectionManager = new ConnectionManager(Support.getTestDialect(), sequelize);
const resolvedPromise = new Promise(resolve => {
resolve({
queryType: 'read'
});
});
const connectStub = sandbox.stub(connectionManager, '_connect').returns(resolvedPromise);
sandbox.stub(connectionManager, '_disconnect').returns(resolvedPromise);
sandbox.stub(sequelize, 'databaseVersion').returns(resolvedPromise);
connectionManager.initPools();
const queryOptions = {
priority: 0,
type: 'SELECT',
useMaster: true
};
return connectionManager.getConnection(queryOptions)
.then(() => {
chai.expect(connectStub).to.have.been.calledTwice; // Once to get DB version, and once to actually get the connection.
const calls = connectStub.getCalls();
chai.expect(calls[1].args[0].host).to.eql('the-boss');
});
});
it('should clear the pool after draining it', () => {
const options = {
replication: null
};
const sequelize = Support.createSequelizeInstance(options);
const connectionManager = new ConnectionManager(Support.getTestDialect(), sequelize);
connectionManager.initPools();
const poolDrainSpy = sandbox.spy(connectionManager.pool, 'drain');
const poolClearSpy = sandbox.spy(connectionManager.pool, 'clear');
return connectionManager.close().then(() => {
expect(poolDrainSpy.calledOnce).to.be.true;
expect(poolClearSpy.calledOnce).to.be.true;
});
});
});