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,24 @@ 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 && this . config . minConnections ) {
23
+ var self = this ;
24
+ var opened = 0 ;
25
+ for ( var i = 0 ; i < this . config . minConnections ; i ++ ) {
26
+ this . getConnection ( function ( err , conn ) {
27
+ if ( conn ) {
28
+ process . nextTick ( function ( ) {
29
+ if ( ++ opened === self . config . minConnections ) {
30
+ self . _openingConnections = false ;
31
+ }
32
+ self . releaseConnection ( conn ) ;
33
+ } ) ;
34
+ }
35
+ } ) ;
36
+ }
37
+ // This must be after the getConnection, or else its enqueued
38
+ this . _openingConnections = true ;
39
+ }
21
40
}
22
41
23
42
Pool . prototype . getConnection = function ( cb ) {
@@ -26,6 +45,10 @@ Pool.prototype.getConnection = function(cb) {
26
45
return cb ( new Error ( 'Pool is closed.' ) ) ;
27
46
} ) ;
28
47
}
48
+ if ( this . _openingConnections ) {
49
+ // We are opening a connect, use it when ready
50
+ return this . _connectionQueue . push ( cb ) ;
51
+ }
29
52
30
53
var connection ;
31
54
@@ -82,7 +105,8 @@ Pool.prototype.getConnection = function(cb) {
82
105
Pool . prototype . releaseConnection = function ( connection ) {
83
106
var cb ;
84
107
85
- if ( ! connection . _pool ) {
108
+ connection . _lastReleased = Date . now ( ) ;
109
+ if ( ! connection . _pool || connection . _closed || connection . _closing ) {
86
110
// The connection has been removed from the pool and is no longer good.
87
111
if ( this . _connectionQueue . length ) {
88
112
cb = this . _connectionQueue . shift ( ) ;
@@ -95,6 +119,7 @@ Pool.prototype.releaseConnection = function(connection) {
95
119
process . nextTick ( cb . bind ( null , null , connection ) ) ;
96
120
} else {
97
121
this . _freeConnections . push ( connection ) ;
122
+ this . _manageExpiredTimer ( ) ;
98
123
}
99
124
} ;
100
125
@@ -111,14 +136,14 @@ Pool.prototype.end = function(cb) {
111
136
112
137
var calledBack = false ;
113
138
var closedConnections = 0 ;
114
- var connection ;
139
+ var numConnections = this . _allConnections . length ;
115
140
116
141
var endCB = function ( err ) {
117
142
if ( calledBack ) {
118
143
return ;
119
144
}
120
145
121
- if ( err || ++ closedConnections >= this . _allConnections . length ) {
146
+ if ( err || ++ closedConnections >= numConnections ) {
122
147
calledBack = true ;
123
148
cb ( err ) ;
124
149
return ;
@@ -130,9 +155,9 @@ Pool.prototype.end = function(cb) {
130
155
return ;
131
156
}
132
157
133
- for ( var i = 0 ; i < this . _allConnections . length ; i ++ ) {
134
- connection = this . _allConnections . get ( i ) ;
135
- connection . _realEnd ( endCB ) ;
158
+ var connection ;
159
+ while ( ( connection = this . _allConnections . shift ( ) ) ) {
160
+ this . _closeConnection ( connection , endCB ) ;
136
161
}
137
162
} ;
138
163
@@ -184,6 +209,39 @@ Pool.prototype.execute = function(sql, values, cb) {
184
209
} ) ;
185
210
} ;
186
211
212
+ Pool . prototype . _manageExpiredTimer = function ( ) {
213
+ var hasExtra = this . _allConnections . length > this . config . minConnections ;
214
+ if ( hasExtra && ! this . _expiredTimer ) {
215
+ this . _expiredTimer = Timers . setInterval (
216
+ Pool . prototype . _closeIdleConnections . bind ( this ) ,
217
+ Math . min ( 15 , this . config . idleTimeout ) * 1000
218
+ ) ;
219
+ } else if ( ! hasExtra && this . _expiredTimer ) {
220
+ Timers . clearInterval ( this . _expiredTimer ) ;
221
+ this . _expiredTimer = null ;
222
+ }
223
+ } ;
224
+
225
+ Pool . prototype . _closeIdleConnections = function ( ) {
226
+ var now = Date . now ( ) ;
227
+ var timeout = this . config . idleTimeout * 1000 ;
228
+ var length = this . _freeConnections . length ;
229
+ var numExtra = this . _allConnections . length - this . config . minConnections ;
230
+ for ( var i = 0 ; numExtra > 0 && i < length ; i ++ ) {
231
+ var conn = this . _freeConnections . get ( i ) ;
232
+
233
+ if ( now > conn . _lastReleased + timeout ) {
234
+ // This connection has been unused for longer than the timeout
235
+ this . _closeConnection ( conn ) ;
236
+ // decrement i and length as the length will be reduced by 1 by closeConnection
237
+ i -- ;
238
+ length -- ;
239
+ numExtra -- ;
240
+ }
241
+ }
242
+ this . _manageExpiredTimer ( ) ;
243
+ } ;
244
+
187
245
Pool . prototype . _removeConnection = function ( connection ) {
188
246
// Remove connection from all connections
189
247
spliceConnection ( this . _allConnections , connection ) ;
@@ -192,6 +250,13 @@ Pool.prototype._removeConnection = function(connection) {
192
250
spliceConnection ( this . _freeConnections , connection ) ;
193
251
194
252
this . releaseConnection ( connection ) ;
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