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