idle-timeout.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. 'use strict'
  2. const co = require('co')
  3. const expect = require('expect.js')
  4. const describe = require('mocha').describe
  5. const it = require('mocha').it
  6. const { fork } = require('child_process')
  7. const path = require('path')
  8. const Pool = require('../')
  9. const wait = (time) => new Promise((resolve) => setTimeout(resolve, time))
  10. describe('idle timeout', () => {
  11. it('should timeout and remove the client', (done) => {
  12. const pool = new Pool({ idleTimeoutMillis: 10 })
  13. pool.query('SELECT NOW()')
  14. pool.on('remove', () => {
  15. expect(pool.idleCount).to.equal(0)
  16. expect(pool.totalCount).to.equal(0)
  17. done()
  18. })
  19. })
  20. it(
  21. 'times out and removes clients when others are also removed',
  22. co.wrap(function* () {
  23. const pool = new Pool({ idleTimeoutMillis: 10 })
  24. const clientA = yield pool.connect()
  25. const clientB = yield pool.connect()
  26. clientA.release()
  27. clientB.release(new Error())
  28. const removal = new Promise((resolve) => {
  29. pool.on('remove', () => {
  30. expect(pool.idleCount).to.equal(0)
  31. expect(pool.totalCount).to.equal(0)
  32. resolve()
  33. })
  34. })
  35. const timeout = wait(100).then(() => Promise.reject(new Error('Idle timeout failed to occur')))
  36. try {
  37. yield Promise.race([removal, timeout])
  38. } finally {
  39. pool.end()
  40. }
  41. })
  42. )
  43. it(
  44. 'can remove idle clients and recreate them',
  45. co.wrap(function* () {
  46. const pool = new Pool({ idleTimeoutMillis: 1 })
  47. const results = []
  48. for (var i = 0; i < 20; i++) {
  49. let query = pool.query('SELECT NOW()')
  50. expect(pool.idleCount).to.equal(0)
  51. expect(pool.totalCount).to.equal(1)
  52. results.push(yield query)
  53. yield wait(2)
  54. expect(pool.idleCount).to.equal(0)
  55. expect(pool.totalCount).to.equal(0)
  56. }
  57. expect(results).to.have.length(20)
  58. })
  59. )
  60. it(
  61. 'does not time out clients which are used',
  62. co.wrap(function* () {
  63. const pool = new Pool({ idleTimeoutMillis: 1 })
  64. const results = []
  65. for (var i = 0; i < 20; i++) {
  66. let client = yield pool.connect()
  67. expect(pool.totalCount).to.equal(1)
  68. expect(pool.idleCount).to.equal(0)
  69. yield wait(10)
  70. results.push(yield client.query('SELECT NOW()'))
  71. client.release()
  72. expect(pool.idleCount).to.equal(1)
  73. expect(pool.totalCount).to.equal(1)
  74. }
  75. expect(results).to.have.length(20)
  76. return pool.end()
  77. })
  78. )
  79. it('unrefs the connections and timeouts so the program can exit when idle when the allowExitOnIdle option is set', function (done) {
  80. const child = fork(path.join(__dirname, 'idle-timeout-exit.js'), [], {
  81. silent: true,
  82. env: { ...process.env, ALLOW_EXIT_ON_IDLE: '1' },
  83. })
  84. let result = ''
  85. child.stdout.setEncoding('utf8')
  86. child.stdout.on('data', (chunk) => (result += chunk))
  87. child.on('error', (err) => done(err))
  88. child.on('close', () => {
  89. expect(result).to.equal('completed first\ncompleted second\n')
  90. done()
  91. })
  92. })
  93. it('keeps old behavior when allowExitOnIdle option is not set', function (done) {
  94. const child = fork(path.join(__dirname, 'idle-timeout-exit.js'), [], {
  95. silent: true,
  96. })
  97. let result = ''
  98. child.stdout.setEncoding('utf8')
  99. child.stdout.on('data', (chunk) => (result += chunk))
  100. child.on('error', (err) => done(err))
  101. child.on('close', () => {
  102. expect(result).to.equal('completed first\ncompleted second\nremoved\n')
  103. done()
  104. })
  105. })
  106. })