Note: This problem is mainly about singleton objects in node and not DB pools
I'm building an expressjs app using mysqljs node module for DB connections. I want to create a single pool object that can be reused throughout the app (for the different models etc). I want to know what is the correct way to use a single object instance throughout an express app
I've seen many examples where people create a db.js file or pool.js file like so and require it where they need it
// db.js
var mysql = require('mysql');
var pool;
module.exports = {
getPool: function () {
if (pool) return pool;
pool = mysql.createPool(dbConfig);
return pool;
}
};
// app.js
var pool = require('pool').getPool();
pool.query('SELECT * FROM users');
However I feel this is still not the correct approach as you are relying on the nodejs cache to return the same instance every time you require the object. If the node ended up loading the code twice you would end up with two pools, e.g.
const poolA = require('./pool').getPool();
const poolB = require('./POOL').getPool(); // resolves to same file but node will not get result from cache
console.log(poolA === poolB); // false
From most things I've read, it is generally not recommended to use singleton objects in your node applications because of this behaviour, but this seems like a common use case for express apps. So I was wondering how are people creating their single pool for the lifetime of their application?
Note: What I've currently been doing is instantiating the pool in the app root and then passing the instance as a constructor function parameter but I also am not fond of this
Short answer
I don't see any problem in your code.
Long Answer
This solution is assuming you don't actually have a file named POOL.js
with the same exact code.
The below require
is resolving to the same file as pool.js
because you're using a filesystem with case-insensitivity
enabled. For example NTFS
or APFS
.
const poolB = require('./POOL').getPool();
If you use case sensitive
file system like ext4
then you would get error.
Error: Cannot find module './POOL'
Internally node
caches files based on the file path name you provide. From source:
const relativeResolveCache = Object.create(null);
relResolveCacheIdentifier = `${parent.path}\x00${request}`;
const filename = relativeResolveCache[relResolveCacheIdentifier];
if (filename !== undefined)
...
Since JavaScript
is case-sensitive
, an object (the cache
, from above) with property (simplyfying) pool
and POOL
is going to be different and refer to entirely 2 different object reference.
Conclusion
Watch out for gotchas with file names or identifier names.