| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 | 
							- 'use strict'
 
- const net = require('net')
 
- const co = require('co')
 
- const expect = require('expect.js')
 
- const describe = require('mocha').describe
 
- const it = require('mocha').it
 
- const before = require('mocha').before
 
- const after = require('mocha').after
 
- const Pool = require('../')
 
- describe('connection timeout', () => {
 
-   const connectionFailure = new Error('Temporary connection failure')
 
-   before((done) => {
 
-     this.server = net.createServer((socket) => {
 
-       socket.on('data', () => {
 
-         // discard any buffered data or the server wont terminate
 
-       })
 
-     })
 
-     this.server.listen(() => {
 
-       this.port = this.server.address().port
 
-       done()
 
-     })
 
-   })
 
-   after((done) => {
 
-     this.server.close(done)
 
-   })
 
-   it('should callback with an error if timeout is passed', (done) => {
 
-     const pool = new Pool({ connectionTimeoutMillis: 10, port: this.port, host: 'localhost' })
 
-     pool.connect((err, client, release) => {
 
-       expect(err).to.be.an(Error)
 
-       expect(err.message).to.contain('timeout')
 
-       expect(client).to.equal(undefined)
 
-       expect(pool.idleCount).to.equal(0)
 
-       done()
 
-     })
 
-   })
 
-   it('should reject promise with an error if timeout is passed', (done) => {
 
-     const pool = new Pool({ connectionTimeoutMillis: 10, port: this.port, host: 'localhost' })
 
-     pool.connect().catch((err) => {
 
-       expect(err).to.be.an(Error)
 
-       expect(err.message).to.contain('timeout')
 
-       expect(pool.idleCount).to.equal(0)
 
-       done()
 
-     })
 
-   })
 
-   it(
 
-     'should handle multiple timeouts',
 
-     co.wrap(
 
-       function* () {
 
-         const errors = []
 
-         const pool = new Pool({ connectionTimeoutMillis: 1, port: this.port, host: 'localhost' })
 
-         for (var i = 0; i < 15; i++) {
 
-           try {
 
-             yield pool.connect()
 
-           } catch (e) {
 
-             errors.push(e)
 
-           }
 
-         }
 
-         expect(errors).to.have.length(15)
 
-       }.bind(this)
 
-     )
 
-   )
 
-   it('should timeout on checkout of used connection', (done) => {
 
-     const pool = new Pool({ connectionTimeoutMillis: 100, max: 1 })
 
-     pool.connect((err, client, release) => {
 
-       expect(err).to.be(undefined)
 
-       expect(client).to.not.be(undefined)
 
-       pool.connect((err, client) => {
 
-         expect(err).to.be.an(Error)
 
-         expect(client).to.be(undefined)
 
-         release()
 
-         pool.end(done)
 
-       })
 
-     })
 
-   })
 
-   it('should not break further pending checkouts on a timeout', (done) => {
 
-     const pool = new Pool({ connectionTimeoutMillis: 200, max: 1 })
 
-     pool.connect((err, client, releaseOuter) => {
 
-       expect(err).to.be(undefined)
 
-       pool.connect((err, client) => {
 
-         expect(err).to.be.an(Error)
 
-         expect(client).to.be(undefined)
 
-         releaseOuter()
 
-       })
 
-       setTimeout(() => {
 
-         pool.connect((err, client, releaseInner) => {
 
-           expect(err).to.be(undefined)
 
-           expect(client).to.not.be(undefined)
 
-           releaseInner()
 
-           pool.end(done)
 
-         })
 
-       }, 100)
 
-     })
 
-   })
 
-   it('should timeout on query if all clients are busy', (done) => {
 
-     const pool = new Pool({ connectionTimeoutMillis: 100, max: 1 })
 
-     pool.connect((err, client, release) => {
 
-       expect(err).to.be(undefined)
 
-       expect(client).to.not.be(undefined)
 
-       pool.query('select now()', (err, result) => {
 
-         expect(err).to.be.an(Error)
 
-         expect(result).to.be(undefined)
 
-         release()
 
-         pool.end(done)
 
-       })
 
-     })
 
-   })
 
-   it('should recover from timeout errors', (done) => {
 
-     const pool = new Pool({ connectionTimeoutMillis: 100, max: 1 })
 
-     pool.connect((err, client, release) => {
 
-       expect(err).to.be(undefined)
 
-       expect(client).to.not.be(undefined)
 
-       pool.query('select now()', (err, result) => {
 
-         expect(err).to.be.an(Error)
 
-         expect(result).to.be(undefined)
 
-         release()
 
-         pool.query('select $1::text as name', ['brianc'], (err, res) => {
 
-           expect(err).to.be(undefined)
 
-           expect(res.rows).to.have.length(1)
 
-           pool.end(done)
 
-         })
 
-       })
 
-     })
 
-   })
 
-   it('continues processing after a connection failure', (done) => {
 
-     const Client = require('pg').Client
 
-     const orgConnect = Client.prototype.connect
 
-     let called = false
 
-     Client.prototype.connect = function (cb) {
 
-       // Simulate a failure on first call
 
-       if (!called) {
 
-         called = true
 
-         return setTimeout(() => {
 
-           cb(connectionFailure)
 
-         }, 100)
 
-       }
 
-       // And pass-through the second call
 
-       orgConnect.call(this, cb)
 
-     }
 
-     const pool = new Pool({
 
-       Client: Client,
 
-       connectionTimeoutMillis: 1000,
 
-       max: 1,
 
-     })
 
-     pool.connect((err, client, release) => {
 
-       expect(err).to.be(connectionFailure)
 
-       pool.query('select $1::text as name', ['brianc'], (err, res) => {
 
-         expect(err).to.be(undefined)
 
-         expect(res.rows).to.have.length(1)
 
-         pool.end(done)
 
-       })
 
-     })
 
-   })
 
-   it('releases newly connected clients if the queued already timed out', (done) => {
 
-     const Client = require('pg').Client
 
-     const orgConnect = Client.prototype.connect
 
-     let connection = 0
 
-     Client.prototype.connect = function (cb) {
 
-       // Simulate a failure on first call
 
-       if (connection === 0) {
 
-         connection++
 
-         return setTimeout(() => {
 
-           cb(connectionFailure)
 
-         }, 300)
 
-       }
 
-       // And second connect taking > connection timeout
 
-       if (connection === 1) {
 
-         connection++
 
-         return setTimeout(() => {
 
-           orgConnect.call(this, cb)
 
-         }, 1000)
 
-       }
 
-       orgConnect.call(this, cb)
 
-     }
 
-     const pool = new Pool({
 
-       Client: Client,
 
-       connectionTimeoutMillis: 1000,
 
-       max: 1,
 
-     })
 
-     // Direct connect
 
-     pool.connect((err, client, release) => {
 
-       expect(err).to.be(connectionFailure)
 
-     })
 
-     // Queued
 
-     let called = 0
 
-     pool.connect((err, client, release) => {
 
-       // Verify the callback is only called once
 
-       expect(called++).to.be(0)
 
-       expect(err).to.be.an(Error)
 
-       pool.query('select $1::text as name', ['brianc'], (err, res) => {
 
-         expect(err).to.be(undefined)
 
-         expect(res.rows).to.have.length(1)
 
-         pool.end(done)
 
-       })
 
-     })
 
-   })
 
- })
 
 
  |