I am using SvelteKit, Vite.js, and the mariadb
package with Node.js in my application. I have the following code in the db.js
file:
import mariadb from 'mariadb';
const databaseConnectionPoolConfig = {
...
};
let databaseConnectionPool = undefined;
export function createDatabaseConnectionPool() {
return databaseConnectionPool ??= mariadb.createPool(databaseConnectionPoolConfig);
}
Inside the hooks.server.js
file, I have the following code:
import { createDatabaseConnectionPool } from '$lib/db';
createDatabaseConnectionPool();
When a hot reload is performed, the databaseConnectionPool
is reset to undefined, but the connections in the pool are not closed, and new ones are created. I checked this by running the following query:
SHOW STATUS LIKE 'Threads_connected';
Which increases each time a hot reload is performed by the number of connections specified by the databaseConnectionPoolConfig.connectionLimit
property.
How can I prevent this from happening?
2
Answers
You would need to implement a mechanism to persist the database connection pool across hot reloads.
In the context of hot module reloading (HMR) with Vite.js, Node.js
global
variables are usually not preserved. That is because the server-side code gets re-executed, resetting the state of these variables.Hot module reloading replaces the modified modules without restarting the server, which means the global scope in each module would get reset. However, Node.js built-in modules and their state, like
require.cache
, may not necessarily be cleared upon HMR, and this behavior could potentially be leveraged to preserve certain data like a database connection pool.Modify your
db.js
to store the database connection pool inrequire.cache
if it does not already exist:Then:
SHOW STATUS LIKE 'Threads_connected';
again to check if the number of threads connected increases or not.By doing this, you should be able to maintain the same database connection pool even after multiple hot reloads, provided your development environment does not clear
require.cache
on a hot reload.In the code provided, each time the hot module replacement (HMR) is triggered, the module is re-evaluated. Based on that code this leads to a new pool of connections getting created without closing the existing pool of connections.
To prevent the above, the code can be modified to check for an existing pool, close it and then create a new pool.
Also, it would be wise to make the function use
await
before calling thedatabaseConnectionPool.end()
method since it is asynchronous and it needs to complete before proceeding, see amended function below:On the other hand it would be more efficient to actually reuse an existing data connection pool if it already exists, rather than wasting resources to recreate it each time. If that approach is more desirable, amend the function to the following:
With this approach, the connection pool is initialised only once. Subsequent calls to
createDatabaseConnectionPool
will simply return the existing connection pool without creating a new one. This ensures the connection pool is reused and prevents the creation of a new connection pool with each HMR.