1
1
var mysql = require ( '../index.js' ) ;
2
2
3
3
var EventEmitter = require ( 'events' ) . EventEmitter ;
4
+ var Timers = require ( 'timers' ) ;
4
5
var Util = require ( 'util' ) ;
5
6
var PoolConnection = require ( './pool_connection.js' ) ;
6
7
var Queue = require ( 'denque' ) ;
@@ -18,6 +19,22 @@ function Pool(options) {
18
19
this . _freeConnections = new Queue ( ) ;
19
20
this . _connectionQueue = new Queue ( ) ;
20
21
this . _closed = false ;
22
+ if ( this . config . autoOpenConnections ) {
23
+ this . _openingConnections = true ;
24
+ var self = this ;
25
+ var opened = 0 ;
26
+ for ( var i = 0 ; i < this . config . minConnections ; i ++ ) {
27
+ this . getConnection ( function ( conn ) {
28
+ process . nextTick ( function ( ) {
29
+ self . releaseConnection ( conn ) ;
30
+ if ( ++ opened === self . config . minConnections ) {
31
+ self . _openingConnections = false ;
32
+ }
33
+ } ) ;
34
+ } ) ;
35
+ }
36
+
37
+ }
21
38
}
22
39
23
40
Pool . prototype . getConnection = function ( cb ) {
@@ -26,6 +43,10 @@ Pool.prototype.getConnection = function(cb) {
26
43
return cb ( new Error ( 'Pool is closed.' ) ) ;
27
44
} ) ;
28
45
}
46
+ if ( this . _openingConnections ) {
47
+ // We are opening a connect, use it when ready
48
+ return this . _connectionQueue . push ( cb ) ;
49
+ }
29
50
30
51
var connection ;
31
52
@@ -82,6 +103,7 @@ Pool.prototype.getConnection = function(cb) {
82
103
Pool . prototype . releaseConnection = function ( connection ) {
83
104
var cb ;
84
105
106
+ connection . _lastReleased = Date . now ( ) ;
85
107
if ( ! connection . _pool ) {
86
108
// The connection has been removed from the pool and is no longer good.
87
109
if ( this . _connectionQueue . length ) {
@@ -95,6 +117,7 @@ Pool.prototype.releaseConnection = function(connection) {
95
117
process . nextTick ( cb . bind ( null , null , connection ) ) ;
96
118
} else {
97
119
this . _freeConnections . push ( connection ) ;
120
+ this . _manageExpiredTimer ( ) ;
98
121
}
99
122
} ;
100
123
@@ -111,14 +134,14 @@ Pool.prototype.end = function(cb) {
111
134
112
135
var calledBack = false ;
113
136
var closedConnections = 0 ;
114
- var connection ;
137
+ var numConnections = this . _allConnections . length ;
115
138
116
139
var endCB = function ( err ) {
117
140
if ( calledBack ) {
118
141
return ;
119
142
}
120
143
121
- if ( err || ++ closedConnections >= this . _allConnections . length ) {
144
+ if ( err || ++ closedConnections >= numConnections ) {
122
145
calledBack = true ;
123
146
cb ( err ) ;
124
147
return ;
@@ -130,9 +153,9 @@ Pool.prototype.end = function(cb) {
130
153
return ;
131
154
}
132
155
133
- for ( var i = 0 ; i < this . _allConnections . length ; i ++ ) {
134
- connection = this . _allConnections . get ( i ) ;
135
- connection . _realEnd ( endCB ) ;
156
+ var connection ;
157
+ while ( ( connection = this . _allConnections . shift ( ) ) ) {
158
+ this . _closeConnection ( connection , endCB ) ;
136
159
}
137
160
} ;
138
161
@@ -184,14 +207,56 @@ Pool.prototype.execute = function(sql, values, cb) {
184
207
} ) ;
185
208
} ;
186
209
210
+ Pool . prototype . _manageExpiredTimer = function ( ) {
211
+ var hasExtra = this . _allConnections . length > this . config . minConnections ;
212
+ if ( hasExtra && ! this . _expiredTimer ) {
213
+ this . _expiredTimer = Timers . setInterval (
214
+ Pool . prototype . _closeIdleConnections . bind ( this ) ,
215
+ Math . min ( 15 , this . config . idleTimeout ) * 1000
216
+ ) ;
217
+ } else if ( ! hasExtra && this . _expiredTimer ) {
218
+ Timers . clearInterval ( this . _expiredTimer ) ;
219
+ this . _expiredTimer = null ;
220
+ }
221
+ } ;
222
+
223
+ Pool . prototype . _closeIdleConnections = function ( ) {
224
+ var now = Date . now ( ) ;
225
+ var timeout = this . config . idleTimeout * 1000 ;
226
+ var length = this . _freeConnections . length ;
227
+ var numExtra = this . _allConnections . length - this . config . minConnections ;
228
+ for ( var i = 0 ; numExtra > 0 && i < length ; i ++ ) {
229
+ var conn = this . _freeConnections . get ( i ) ;
230
+
231
+ if ( now > conn . _lastReleased + timeout ) {
232
+ // This connection has been unused for longer than the timeout
233
+ this . _closeConnection ( conn ) ;
234
+ // decrement i and length as the length will be reduced by 1 by closeConnection
235
+ i -- ;
236
+ length -- ;
237
+ numExtra -- ;
238
+ }
239
+ }
240
+ this . _manageExpiredTimer ( ) ;
241
+ } ;
242
+
187
243
Pool . prototype . _removeConnection = function ( connection ) {
188
244
// Remove connection from all connections
189
245
spliceConnection ( this . _allConnections , connection ) ;
190
246
191
247
// Remove connection from free connections
192
248
spliceConnection ( this . _freeConnections , connection ) ;
193
249
194
- this . releaseConnection ( connection ) ;
250
+ if ( ! connection . _closing && ! connection . _closed ) {
251
+ this . releaseConnection ( connection ) ;
252
+ }
253
+
254
+ this . _manageExpiredTimer ( ) ;
255
+ } ;
256
+
257
+ Pool . prototype . _closeConnection = function ( connection , cb ) {
258
+ connection . _realEnd ( cb ) ;
259
+ this . _removeConnection ( connection ) ;
195
260
} ;
196
261
197
262
Pool . prototype . format = function ( sql , values ) {
0 commit comments