Help Wanted: Increasing max pool prevents "TimeoutError: operation timed out for an unknown reason", am I doing something wrong?
See original GitHub issueI’ve been tracing a bug for several days, and finally just found a solution, but I’m not sure it’s correct or scalable. The solution was to increase the max pool size above the default value to prevent timeouts of my queries. Here is some context:
While in development, connecting to the dev SQL server running in a Docker container I never experienced any timeout issues, however when moving to production and setting up my application on a Windows web server (…I know) with a separate SQL server, I was experiencing the following error:
TimeoutError: operation timed out for an unknown reason at
app_path/node_modules/tarn/lib/PendingOperation.js:16:27
Only when I made requests in rapid succession (querying enum tables for a complex form, ~12 requests) would I see this issue. When making 1 or 2 requests quickly everything would be fine.
I was able to recreate this issue locally by setting up 2 Windows Server VMs and connecting between them. I assume that the additional network latency is what initiated the timeout errors, and increasing the connection pool size from the default 10 to 500 appears to have fixed the issue.
My issue with this solution is that it doesn’t seem scalable or the right answer and I’m worried that I’m not handling my connections correctly, or my connection pool is not being reused or something else.
Here is how my code is setup:
database/config.js
require('dotenv').config();
module.exports = {
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
server: process.env.DB_SERVER,
database: process.env.DB_DATABASE,
options: {
enableArithAbort: true,
},
pool: {
max: process.env.DB_MAX_POOL || 500,
min: 0,
},
};
database/db.js
const config = require('./config');
const sql = require('mssql');
module.exports = {
query: (query) => {
return sql.connect(config).then((pool) => {
return pool.request().query(query);
});
},
};
express route example
const router = require('express').Router();
const db = require('../database/db');
router.get('/some-enum', (req, res) => {
db.query('GetSomeEnumValuesStoredProcedure')
.then((results) => {
return res.json(results.recordset);
})
.catch((err) => {
console.error(err);
return res.status(500).json({
message: 'There was a server error. Please try again later.',
});
});
});
module.exports = router;
My application would make several requests to these enum routes while loading the data needed for the form, and a few of them would load correctly and then they would start failing. with the following error:
TimeoutError: operation timed out for an unknown reason at
app_path/node_modules/tarn/lib/PendingOperation.js:16:27
Is increasing the max connection pool the right answer here, or is something else wrong?
Thank you to anyone that can help me.
Software versions
- NodeJS:
v12.16.2
- node-mssql:
6.1.0
- SQL Server:
SQL Server 2016 SP2
Issue Analytics
- State:
- Created 3 years ago
- Comments:9
I know this is an old issue, I just want to share the way I solved it since this solution did not help me. I found some obscure timeout settings under “pool” which I increased to a ridiculous amount. I am not sure which one of these helped, but this solved my problem:
@dhensby Thank you so much for your help, alas there was indeed some logic I had different behavior based on the environment, the problem is that rather than checking if
NODE_ENV === "production"
I was checking forNODE_ENV === "development"
so it did not appear in my initial search.What my issue actually was: I had a middleware that was getting user data from the database and checking role-based authentication on every route, and in a particular case I had database transactions that were not being committed. I guess I just forgot to commit/rollback because I was only doing SELECTs rather than INSERTs. So if you create a transaction and don’t commit it, and make several more queries it eventually leads to the behavior described above. Now my app works even with 1 as the max database pool.
Again, thanks for the help.