mirror of
https://github.com/knex/knex.git
synced 2025-07-24 17:31:01 +00:00
177 lines
4.9 KiB
JavaScript
177 lines
4.9 KiB
JavaScript
'use strict';
|
|
|
|
const test = require('tape');
|
|
const Client = require('../../lib/dialects/sqlite3');
|
|
const tarn = require('tarn');
|
|
const Pool = tarn.Pool;
|
|
const knexfile = require('../knexfile');
|
|
const makeKnex = require('../../knex');
|
|
const delay = require('../../lib/execution/internal/delay');
|
|
|
|
test(`pool evicts dead resources when factory.validate rejects`, async (t) => {
|
|
t.plan(10);
|
|
|
|
let i = 0;
|
|
const pool = new Pool({
|
|
min: 2,
|
|
max: 5,
|
|
idleTimeoutMillis: 100,
|
|
acquireTimeoutMillis: 100,
|
|
|
|
create: () => {
|
|
return { id: i++ };
|
|
},
|
|
|
|
validate: (res) => {
|
|
return res.error ? false : true;
|
|
},
|
|
|
|
destroy: (res) => {
|
|
return true;
|
|
},
|
|
});
|
|
const fiveElements = Array.from(Array(5));
|
|
const allocateConnections = () =>
|
|
Promise.all(
|
|
fiveElements.map(() =>
|
|
pool.acquire().promise.catch((e) => {
|
|
t.fail('Could not get resource from pool', e);
|
|
})
|
|
)
|
|
);
|
|
|
|
const connectionsGroup1 = await allocateConnections();
|
|
connectionsGroup1.forEach((con) => pool.release(con));
|
|
connectionsGroup1.forEach((con) => {
|
|
// fake kill connections
|
|
con.error = 'connection lost';
|
|
});
|
|
|
|
const connectionsGroup2 = await allocateConnections();
|
|
connectionsGroup2.forEach((con) =>
|
|
t.ok(con.id > 4, 'old dead connections were not reused')
|
|
);
|
|
connectionsGroup2.forEach((con) => pool.release(con));
|
|
|
|
const connectionsGroup3 = await allocateConnections();
|
|
connectionsGroup3.forEach((con) =>
|
|
t.ok(con.id > 4 && con.id < 11, 'Released working connection was used')
|
|
);
|
|
connectionsGroup3.forEach((con) => pool.release(con));
|
|
|
|
await pool.destroy();
|
|
t.end();
|
|
});
|
|
|
|
test('#822, pool config, max: 0 should skip pool construction', function (t) {
|
|
const client = new Client({
|
|
connection: { filename: ':memory:' },
|
|
pool: { max: 0 },
|
|
});
|
|
|
|
try {
|
|
t.equal(client.pool, undefined);
|
|
t.end();
|
|
} finally {
|
|
client.destroy();
|
|
}
|
|
});
|
|
|
|
test('#823, should not skip pool construction pool config is not defined', function (t) {
|
|
const client = new Client({ connection: { filename: ':memory:' } });
|
|
try {
|
|
t.ok(client.pool instanceof Pool);
|
|
t.end();
|
|
} finally {
|
|
client.destroy();
|
|
}
|
|
});
|
|
|
|
test('#2321 dead connections are not evicted from pool (mysql)', async (t) => {
|
|
if (knexfile['mysql']) {
|
|
const knex = makeKnex(knexfile['mysql']);
|
|
|
|
t.plan(10);
|
|
try {
|
|
await Promise.all(
|
|
Array.from(Array(30)).map(() => {
|
|
// kill all connections in pool
|
|
return knex.raw(`KILL connection_id()`).catch(() => {
|
|
// just ignore errors
|
|
});
|
|
})
|
|
);
|
|
|
|
// TODO: It looks like this test case can trigger the race condition
|
|
// outlined in this issue comment:
|
|
//
|
|
// https://github.com/knex/knex/issues/3636#issuecomment-592005391
|
|
//
|
|
// For now, we're working around this problem by introducing a
|
|
// 1 second delay. But, we should revisit this once the connection
|
|
// pool logic has been refactored.
|
|
await delay(1000); // wait driver to notice connection errors (2ms was enough locally)
|
|
|
|
// all connections are dead, so they should be evicted from pool and this should work
|
|
await Promise.all(
|
|
Array.from(Array(10)).map(() =>
|
|
knex.select(1).then(() => t.pass('Read data'))
|
|
)
|
|
);
|
|
} catch (e) {
|
|
t.fail(
|
|
`Should have created new connection and execute the query, got : ${e}`
|
|
);
|
|
} finally {
|
|
t.end();
|
|
await knex.destroy();
|
|
}
|
|
} else {
|
|
t.end();
|
|
}
|
|
});
|
|
|
|
test('#2321 dead connections are not evicted from pool (mysql2)', async (t) => {
|
|
if (knexfile['mysql2']) {
|
|
const knex = makeKnex(knexfile['mysql2']);
|
|
|
|
t.plan(10);
|
|
try {
|
|
await Promise.all(
|
|
Array.from(Array(30)).map(() => {
|
|
// kill all connections in pool
|
|
return knex.raw(`KILL connection_id()`).catch(() => {
|
|
// just ignore errors
|
|
});
|
|
})
|
|
);
|
|
|
|
// TODO: It looks like this test case can trigger the race condition
|
|
// outlined in this issue comment:
|
|
//
|
|
// https://github.com/knex/knex/issues/3636#issuecomment-592005391
|
|
//
|
|
// For now, we're working around this problem by introducing a
|
|
// 1 second delay. But, we should revisit this once the connection
|
|
// pool logic has been refactored.
|
|
await delay(1000); // wait driver to notice connection errors (2ms was enough locally)
|
|
|
|
// all connections are dead, so they should be evicted from pool and this should work
|
|
await Promise.all(
|
|
Array.from(Array(10)).map(() =>
|
|
knex.select(1).then(() => t.pass('Read data'))
|
|
)
|
|
);
|
|
} catch (e) {
|
|
t.fail(
|
|
`Should have created new connection and execute the query, got : ${e}`
|
|
);
|
|
} finally {
|
|
t.end();
|
|
await knex.destroy();
|
|
}
|
|
} else {
|
|
t.end();
|
|
}
|
|
});
|