11var mysql = require ( '../index.js' ) ;
22
33var EventEmitter = require ( 'events' ) . EventEmitter ;
4+ var Timers = require ( 'timers' ) ;
45var Util = require ( 'util' ) ;
56var PoolConnection = require ( './pool_connection.js' ) ;
67var Queue = require ( 'denque' ) ;
@@ -18,6 +19,24 @@ function Pool(options) {
1819 this . _freeConnections = new Queue ( ) ;
1920 this . _connectionQueue = new Queue ( ) ;
2021 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+ }
2140}
2241
2342Pool . prototype . getConnection = function ( cb ) {
@@ -26,6 +45,10 @@ Pool.prototype.getConnection = function(cb) {
2645 return cb ( new Error ( 'Pool is closed.' ) ) ;
2746 } ) ;
2847 }
48+ if ( this . _openingConnections ) {
49+ // We are opening a connect, use it when ready
50+ return this . _connectionQueue . push ( cb ) ;
51+ }
2952
3053 var connection ;
3154
@@ -82,6 +105,7 @@ Pool.prototype.getConnection = function(cb) {
82105Pool . prototype . releaseConnection = function ( connection ) {
83106 var cb ;
84107
108+ connection . _lastReleased = Date . now ( ) ;
85109 if ( ! connection . _pool ) {
86110 // The connection has been removed from the pool and is no longer good.
87111 if ( this . _connectionQueue . length ) {
@@ -95,6 +119,7 @@ Pool.prototype.releaseConnection = function(connection) {
95119 process . nextTick ( cb . bind ( null , null , connection ) ) ;
96120 } else {
97121 this . _freeConnections . push ( connection ) ;
122+ this . _manageExpiredTimer ( ) ;
98123 }
99124} ;
100125
@@ -111,14 +136,14 @@ Pool.prototype.end = function(cb) {
111136
112137 var calledBack = false ;
113138 var closedConnections = 0 ;
114- var connection ;
139+ var numConnections = this . _allConnections . length ;
115140
116141 var endCB = function ( err ) {
117142 if ( calledBack ) {
118143 return ;
119144 }
120145
121- if ( err || ++ closedConnections >= this . _allConnections . length ) {
146+ if ( err || ++ closedConnections >= numConnections ) {
122147 calledBack = true ;
123148 cb ( err ) ;
124149 return ;
@@ -130,9 +155,9 @@ Pool.prototype.end = function(cb) {
130155 return ;
131156 }
132157
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 ) ;
136161 }
137162} ;
138163
@@ -184,14 +209,56 @@ Pool.prototype.execute = function(sql, values, cb) {
184209 } ) ;
185210} ;
186211
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+
187245Pool . prototype . _removeConnection = function ( connection ) {
188246 // Remove connection from all connections
189247 spliceConnection ( this . _allConnections , connection ) ;
190248
191249 // Remove connection from free connections
192250 spliceConnection ( this . _freeConnections , connection ) ;
193251
194- this . releaseConnection ( connection ) ;
252+ if ( ! connection . _closing && ! connection . _closed ) {
253+ this . releaseConnection ( connection ) ;
254+ }
255+
256+ this . _manageExpiredTimer ( ) ;
257+ } ;
258+
259+ Pool . prototype . _closeConnection = function ( connection , cb ) {
260+ connection . _realEnd ( cb ) ;
261+ this . _removeConnection ( connection ) ;
195262} ;
196263
197264Pool . prototype . format = function ( sql , values ) {
0 commit comments