Socket
Socket
Sign inDemoInstall

slonik

Package Overview
Dependencies
Maintainers
0
Versions
395
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

slonik - npm Package Compare versions

Comparing version 46.0.1 to 46.1.0

7

dist/factories/createClientConfiguration.js

@@ -19,2 +19,3 @@ "use strict";

maximumPoolSize: 10,
minimumPoolSize: 0,
queryRetryLimit: 5,

@@ -32,2 +33,8 @@ resetConnection: ({ query }) => {

}
if (configuration.minimumPoolSize < 0) {
throw new errors_1.InvalidConfigurationError('minimumPoolSize must be equal to or greater than 0.');
}
if (configuration.maximumPoolSize < configuration.minimumPoolSize) {
throw new errors_1.InvalidConfigurationError('maximumPoolSize must be equal to or greater than minimumPoolSize.');
}
if (!configuration.typeParsers || configuration.typeParsers === typeParsers) {

@@ -34,0 +41,0 @@ configuration.typeParsers = (0, createTypeParserPreset_1.createTypeParserPreset)();

7

dist/factories/createConnectionPool.d.ts

@@ -32,8 +32,9 @@ import { type Driver, type DriverClientEventEmitter, type DriverClientState, type DriverQueryResult, type DriverStream, type DriverStreamResult } from '@slonik/driver';

};
export declare const createConnectionPool: ({ driver, poolSize, }: {
export declare const createConnectionPool: ({ driver, maximumPoolSize, minimumPoolSize, }: {
driver: Driver;
idleTimeout?: number;
poolSize?: number;
idleTimeout: number;
maximumPoolSize: number;
minimumPoolSize: number;
}) => ConnectionPool;
export {};
//# sourceMappingURL=createConnectionPool.d.ts.map

@@ -11,3 +11,3 @@ "use strict";

});
const createConnectionPool = ({ driver, poolSize = 1, }) => {
const createConnectionPool = ({ driver, maximumPoolSize, minimumPoolSize, }) => {
// See test "waits for all connections to be established before attempting to terminate the pool"

@@ -53,8 +53,3 @@ // for explanation of why `pendingConnections` is needed.

}
const idleConnection = connections.find((connection) => connection.state() === 'IDLE');
if (idleConnection) {
idleConnection.acquire();
return idleConnection;
}
if (pendingConnections.length + connections.length < poolSize) {
const addConnection = async () => {
const pendingConnection = driver.createClient();

@@ -83,2 +78,6 @@ pendingConnections.push(pendingConnection);

const waitingClient = waitingClients.shift();
if (!isEnding && !isEnded && connections.length < minimumPoolSize) {
addConnection();
return;
}
if (!waitingClient) {

@@ -91,28 +90,36 @@ return;

connection.on('destroy', onDestroy);
connection.acquire();
connections.push(connection);
pendingConnections.splice(pendingConnections.indexOf(pendingConnection), 1);
return connection;
};
const idleConnection = connections.find((connection) => connection.state() === 'IDLE');
if (idleConnection) {
idleConnection.acquire();
return idleConnection;
}
else {
const deferred = (0, utilities_1.defer)();
waitingClients.push({
deferred,
});
const queuedAt = process.hrtime.bigint();
logger.warn({
connections: connections.length,
pendingConnections: pendingConnections.length,
poolSize,
waitingClients: waitingClients.length,
}, `connection pool full; client has been queued`);
// eslint-disable-next-line promise/prefer-await-to-then
return deferred.promise.then((connection) => {
logger.debug({
connectionId: connection.id(),
duration: Number(process.hrtime.bigint() - queuedAt) / 1e6,
}, 'connection has been acquired from the queue');
return connection;
});
if (pendingConnections.length + connections.length < maximumPoolSize) {
const newConnection = await addConnection();
newConnection.acquire();
return newConnection;
}
const deferred = (0, utilities_1.defer)();
waitingClients.push({
deferred,
});
const queuedAt = process.hrtime.bigint();
logger.warn({
connections: connections.length,
maximumPoolSize,
minimumPoolSize,
pendingConnections: pendingConnections.length,
waitingClients: waitingClients.length,
}, `connection pool full; client has been queued`);
// eslint-disable-next-line promise/prefer-await-to-then
return deferred.promise.then((connection) => {
logger.debug({
connectionId: connection.id(),
duration: Number(process.hrtime.bigint() - queuedAt) / 1e6,
}, 'connection has been acquired from the queue');
return connection;
});
};

@@ -119,0 +126,0 @@ return {

import { type ClientConfiguration } from '../types';
type PoolConfiguration = {
idleTimeout?: number;
poolSize?: number;
idleTimeout: number;
maximumPoolSize: number;
minimumPoolSize: number;
};

@@ -6,0 +7,0 @@ export declare const createPoolConfiguration: (clientConfiguration: ClientConfiguration) => PoolConfiguration;

@@ -9,3 +9,4 @@ "use strict";

idleTimeout: 10000,
poolSize: 10,
maximumPoolSize: 10,
minimumPoolSize: 0,
};

@@ -22,4 +23,7 @@ if (clientConfiguration.idleTimeout !== 'DISABLE_TIMEOUT') {

if (clientConfiguration.maximumPoolSize) {
poolConfiguration.poolSize = clientConfiguration.maximumPoolSize;
poolConfiguration.maximumPoolSize = clientConfiguration.maximumPoolSize;
}
if (clientConfiguration.minimumPoolSize) {
poolConfiguration.minimumPoolSize = clientConfiguration.minimumPoolSize;
}
return poolConfiguration;

@@ -26,0 +30,0 @@ };

@@ -1459,2 +1459,73 @@ "use strict";

});
test('removes connections from the pool after the idle timeout', async (t) => {
const pool = await (0, __1.createPool)(t.context.dsn, {
driverFactory,
idleTimeout: 100,
});
t.deepEqual(pool.state(), {
acquiredConnections: 0,
idleConnections: 0,
pendingDestroyConnections: 0,
pendingReleaseConnections: 0,
state: 'ACTIVE',
waitingClients: 0,
}, 'initial state');
await pool.query(__1.sql.unsafe `
SELECT 1
`);
t.deepEqual(pool.state(), {
acquiredConnections: 0,
idleConnections: 1,
pendingDestroyConnections: 0,
pendingReleaseConnections: 0,
state: 'ACTIVE',
waitingClients: 0,
}, 'shows idle clients');
await (0, promises_1.setTimeout)(100);
t.deepEqual(pool.state(), {
acquiredConnections: 0,
idleConnections: 0,
pendingDestroyConnections: 0,
pendingReleaseConnections: 0,
state: 'ACTIVE',
waitingClients: 0,
}, 'shows no idle clients');
});
test('retains a minimum number of connections in the pool', async (t) => {
const pool = await (0, __1.createPool)(t.context.dsn, {
driverFactory,
idleTimeout: 100,
minimumPoolSize: 1,
});
t.deepEqual(pool.state(), {
acquiredConnections: 0,
// TODO we might want to add an option to warm up the pool, in which case this value should be 1
idleConnections: 0,
pendingDestroyConnections: 0,
pendingReleaseConnections: 0,
state: 'ACTIVE',
waitingClients: 0,
}, 'initial state');
await pool.query(__1.sql.unsafe `
SELECT 1
`);
t.deepEqual(pool.state(), {
acquiredConnections: 0,
idleConnections: 1,
pendingDestroyConnections: 0,
pendingReleaseConnections: 0,
state: 'ACTIVE',
waitingClients: 0,
}, 'shows idle clients');
await (0, promises_1.setTimeout)(150);
t.deepEqual(pool.state(), {
acquiredConnections: 0,
idleConnections: 1,
pendingDestroyConnections: 0,
pendingReleaseConnections: 0,
state: 'ACTIVE',
waitingClients: 0,
}, 'shows idle clients because minimum pool size is 1');
await pool.end();
});
test('retains explicit transaction beyond the idle timeout', async (t) => {

@@ -1461,0 +1532,0 @@ const pool = await (0, __1.createPool)(t.context.dsn, {

@@ -87,6 +87,10 @@ import { type ConnectionPoolClient } from './factories/createConnectionPool';

/**
* Do not allow more than this many connections. Use 'DISABLE_TIMEOUT' constant to disable the timeout. (Default: 10)
* Do not allow more than this many connections. (Default: 10)
*/
readonly maximumPoolSize: number;
readonly maximumPoolSize?: number;
/**
* Ensure that at least this many connections are available in the pool. (Default: 0)
*/
readonly minimumPoolSize?: number;
/**
* Number of times a query failing with Transaction Rollback class error, that doesn't belong to a transaction, is retried. (Default: 5)

@@ -93,0 +97,0 @@ */

@@ -8,7 +8,7 @@ {

"dependencies": {
"@slonik/driver": "^46.0.1",
"@slonik/errors": "^46.0.1",
"@slonik/pg-driver": "^46.0.1",
"@slonik/sql-tag": "^46.0.1",
"@slonik/utilities": "^46.0.1",
"@slonik/driver": "^46.1.0",
"@slonik/errors": "^46.1.0",
"@slonik/pg-driver": "^46.1.0",
"@slonik/sql-tag": "^46.1.0",
"@slonik/utilities": "^46.1.0",
"get-stack-trace": "^3.1.1",

@@ -79,3 +79,3 @@ "iso8601-duration": "^1.3.0",

"types": "./dist/index.d.ts",
"version": "46.0.1",
"version": "46.1.0",
"scripts": {

@@ -82,0 +82,0 @@ "build": "rm -fr ./dist && tsc --project ./tsconfig.json",

@@ -26,2 +26,3 @@ import {

maximumPoolSize: 10,
minimumPoolSize: 0,
queryRetryLimit: 5,

@@ -43,2 +44,14 @@ resetConnection: ({ query }) => {

if (configuration.minimumPoolSize < 0) {
throw new InvalidConfigurationError(
'minimumPoolSize must be equal to or greater than 0.',
);
}
if (configuration.maximumPoolSize < configuration.minimumPoolSize) {
throw new InvalidConfigurationError(
'maximumPoolSize must be equal to or greater than minimumPoolSize.',
);
}
if (!configuration.typeParsers || configuration.typeParsers === typeParsers) {

@@ -45,0 +58,0 @@ configuration.typeParsers = createTypeParserPreset();

@@ -61,7 +61,9 @@ import { Logger } from '../Logger';

driver,
poolSize = 1,
maximumPoolSize,
minimumPoolSize,
}: {
driver: Driver;
idleTimeout?: number;
poolSize?: number;
idleTimeout: number;
maximumPoolSize: number;
minimumPoolSize: number;
}): ConnectionPool => {

@@ -128,13 +130,3 @@ // See test "waits for all connections to be established before attempting to terminate the pool"

const idleConnection = connections.find(
(connection) => connection.state() === 'IDLE',
);
if (idleConnection) {
idleConnection.acquire();
return idleConnection;
}
if (pendingConnections.length + connections.length < poolSize) {
const addConnection = async () => {
const pendingConnection = driver.createClient();

@@ -146,2 +138,3 @@

pendingConnections.pop();
throw error;

@@ -176,2 +169,8 @@ });

if (!isEnding && !isEnded && connections.length < minimumPoolSize) {
addConnection();
return;
}
if (!waitingClient) {

@@ -190,4 +189,2 @@ return;

connection.acquire();
connections.push(connection);

@@ -201,34 +198,53 @@

return connection;
} else {
const deferred = defer<ConnectionPoolClient>();
};
waitingClients.push({
deferred,
});
const idleConnection = connections.find(
(connection) => connection.state() === 'IDLE',
);
const queuedAt = process.hrtime.bigint();
if (idleConnection) {
idleConnection.acquire();
logger.warn(
return idleConnection;
}
if (pendingConnections.length + connections.length < maximumPoolSize) {
const newConnection = await addConnection();
newConnection.acquire();
return newConnection;
}
const deferred = defer<ConnectionPoolClient>();
waitingClients.push({
deferred,
});
const queuedAt = process.hrtime.bigint();
logger.warn(
{
connections: connections.length,
maximumPoolSize,
minimumPoolSize,
pendingConnections: pendingConnections.length,
waitingClients: waitingClients.length,
},
`connection pool full; client has been queued`,
);
// eslint-disable-next-line promise/prefer-await-to-then
return deferred.promise.then((connection) => {
logger.debug(
{
connections: connections.length,
pendingConnections: pendingConnections.length,
poolSize,
waitingClients: waitingClients.length,
connectionId: connection.id(),
duration: Number(process.hrtime.bigint() - queuedAt) / 1e6,
},
`connection pool full; client has been queued`,
'connection has been acquired from the queue',
);
// eslint-disable-next-line promise/prefer-await-to-then
return deferred.promise.then((connection) => {
logger.debug(
{
connectionId: connection.id(),
duration: Number(process.hrtime.bigint() - queuedAt) / 1e6,
},
'connection has been acquired from the queue',
);
return connection;
});
}
return connection;
});
};

@@ -235,0 +251,0 @@

@@ -7,4 +7,5 @@ /* eslint-disable canonical/id-match */

type PoolConfiguration = {
idleTimeout?: number;
poolSize?: number;
idleTimeout: number;
maximumPoolSize: number;
minimumPoolSize: number;
};

@@ -17,3 +18,4 @@

idleTimeout: 10_000,
poolSize: 10,
maximumPoolSize: 10,
minimumPoolSize: 0,
};

@@ -34,6 +36,10 @@

if (clientConfiguration.maximumPoolSize) {
poolConfiguration.poolSize = clientConfiguration.maximumPoolSize;
poolConfiguration.maximumPoolSize = clientConfiguration.maximumPoolSize;
}
if (clientConfiguration.minimumPoolSize) {
poolConfiguration.minimumPoolSize = clientConfiguration.minimumPoolSize;
}
return poolConfiguration;
};

@@ -1945,2 +1945,110 @@ /* eslint-disable id-length */

test('removes connections from the pool after the idle timeout', async (t) => {
const pool = await createPool(t.context.dsn, {
driverFactory,
idleTimeout: 100,
});
t.deepEqual(
pool.state(),
{
acquiredConnections: 0,
idleConnections: 0,
pendingDestroyConnections: 0,
pendingReleaseConnections: 0,
state: 'ACTIVE',
waitingClients: 0,
},
'initial state',
);
await pool.query(sql.unsafe`
SELECT 1
`);
t.deepEqual(
pool.state(),
{
acquiredConnections: 0,
idleConnections: 1,
pendingDestroyConnections: 0,
pendingReleaseConnections: 0,
state: 'ACTIVE',
waitingClients: 0,
},
'shows idle clients',
);
await delay(100);
t.deepEqual(
pool.state(),
{
acquiredConnections: 0,
idleConnections: 0,
pendingDestroyConnections: 0,
pendingReleaseConnections: 0,
state: 'ACTIVE',
waitingClients: 0,
},
'shows no idle clients',
);
});
test('retains a minimum number of connections in the pool', async (t) => {
const pool = await createPool(t.context.dsn, {
driverFactory,
idleTimeout: 100,
minimumPoolSize: 1,
});
t.deepEqual(
pool.state(),
{
acquiredConnections: 0,
// TODO we might want to add an option to warm up the pool, in which case this value should be 1
idleConnections: 0,
pendingDestroyConnections: 0,
pendingReleaseConnections: 0,
state: 'ACTIVE',
waitingClients: 0,
},
'initial state',
);
await pool.query(sql.unsafe`
SELECT 1
`);
t.deepEqual(
pool.state(),
{
acquiredConnections: 0,
idleConnections: 1,
pendingDestroyConnections: 0,
pendingReleaseConnections: 0,
state: 'ACTIVE',
waitingClients: 0,
},
'shows idle clients',
);
await delay(150);
t.deepEqual(
pool.state(),
{
acquiredConnections: 0,
idleConnections: 1,
pendingDestroyConnections: 0,
pendingReleaseConnections: 0,
state: 'ACTIVE',
waitingClients: 0,
},
'shows idle clients because minimum pool size is 1',
);
await pool.end();
});
test('retains explicit transaction beyond the idle timeout', async (t) => {

@@ -1947,0 +2055,0 @@ const pool = await createPool(t.context.dsn, {

@@ -118,6 +118,10 @@ import { type ConnectionPoolClient } from './factories/createConnectionPool';

/**
* Do not allow more than this many connections. Use 'DISABLE_TIMEOUT' constant to disable the timeout. (Default: 10)
* Do not allow more than this many connections. (Default: 10)
*/
readonly maximumPoolSize: number;
readonly maximumPoolSize?: number;
/**
* Ensure that at least this many connections are available in the pool. (Default: 0)
*/
readonly minimumPoolSize?: number;
/**
* Number of times a query failing with Transaction Rollback class error, that doesn't belong to a transaction, is retried. (Default: 5)

@@ -124,0 +128,0 @@ */

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc