Skip to content

Commit 85b530c

Browse files
feat(pool): emit 'connectionQueueAcquired' event on connection dequeue
1 parent ca78182 commit 85b530c

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
'use strict';
2+
3+
const assert = require('assert');
4+
// Corrected path based on file structure: ../common.test.cjs
5+
// const {test} = require('../common.test.cjs');
6+
const { test } = require('poku');
7+
const mysql = require('../..');
8+
const process = require('process'); // Ensure process is available
9+
10+
// Helper function to create a pool using test environment variables
11+
function createTestPool(options) {
12+
const config = {
13+
host: process.env.MYSQL_HOST,
14+
user: process.env.MYSQL_USER,
15+
password: process.env.MYSQL_PASSWORD,
16+
database: process.env.MYSQL_DATABASE,
17+
...options,
18+
};
19+
return mysql.createPool(config);
20+
}
21+
22+
// --- Test Case ---
23+
24+
test('Pool emits connectionQueueAcquired event and reports correct queue depth', function (done) {
25+
// 1. Setup Pool: Small limit to force queuing
26+
const connectionLimit = 2;
27+
const pool = createTestPool({
28+
connectionLimit: connectionLimit,
29+
waitForConnections: true,
30+
queueLimit: 0, // No queue limit
31+
});
32+
33+
let acquiredConnections = [];
34+
let queuedAcquiredEvents = [];
35+
const expectedQueueDepths = [1, 0]; // Expected depth after 1st dequeue, then 2nd
36+
37+
// 2. Listen for the new event
38+
pool.on('connectionQueueAcquired', (event) => {
39+
queuedAcquiredEvents.push(event);
40+
});
41+
42+
// Helper to get a connection and wrap it in a Promise for control flow
43+
const getConnectionPromise = () => new Promise((resolve, reject) => {
44+
pool.getConnection((err, conn) => {
45+
if (err) return reject(err);
46+
47+
// Store initial connections (1 and 2) for later release
48+
// We rely on the order of acquisition for this.
49+
acquiredConnections.push(conn);
50+
51+
resolve(conn);
52+
});
53+
});
54+
55+
// --- Execution Flow using Promises for reliability ---
56+
57+
let initialConnection1;
58+
let initialConnection2;
59+
60+
// 1 & 2. Saturate the pool (Acquire 2 connections)
61+
Promise.all([
62+
getConnectionPromise().then(c => initialConnection1 = c),
63+
getConnectionPromise().then(c => initialConnection2 = c)
64+
])
65+
.then(() => {
66+
// 3 & 4. Queue requests (Request 2 more connections, they must wait)
67+
// These will use the general callback logic below
68+
pool.getConnection(queuedConnectionCallback);
69+
pool.getConnection(queuedConnectionCallback);
70+
71+
// Give time for the requests to enter the queue before releasing connections
72+
return new Promise(r => setTimeout(r, 50));
73+
})
74+
.then(() => {
75+
// 5. Trigger Dequeue: Release the initial active connections
76+
// This is safe because the Promise.all ensures initialConnection1/2 are defined.
77+
78+
// Release 1: serves Queued Request 3 (event fired, depth 1)
79+
initialConnection1.release();
80+
81+
// Release 2: serves Queued Request 4 (event fired, depth 0)
82+
initialConnection2.release();
83+
84+
// Wait for the final two queued connections to be acquired and their callbacks to run
85+
return new Promise(r => setTimeout(r, 100));
86+
})
87+
.then(() => {
88+
// Final Assertions and Cleanup (after all acquisitions are complete)
89+
assert.strictEqual(queuedAcquiredEvents.length, 2, 'Should have emitted connectionQueueAcquired exactly twice.');
90+
91+
queuedAcquiredEvents.forEach((event, index) => {
92+
const expectedDepth = expectedQueueDepths[index];
93+
assert.strictEqual(
94+
event.queueDepth,
95+
expectedDepth,
96+
`Event ${index + 1} reported queueDepth ${event.queueDepth}, expected ${expectedDepth}.`
97+
);
98+
assert.ok(event.connection, `Event ${index + 1} is missing the connection object.`);
99+
100+
// Release connections acquired from the queue
101+
event.connection.release();
102+
});
103+
104+
pool.end(done);
105+
})
106+
.catch(err => {
107+
pool.end(() => done(err));
108+
});
109+
});
110+
111+
// For the purposes of this test, we don't need the queued connections to be stored,
112+
// as they are handled and released inside the final Promise block via the event payload.
113+
function queuedConnectionCallback(err, conn) {
114+
if (err) throw err
115+
}
116+

0 commit comments

Comments
 (0)