-
Notifications
You must be signed in to change notification settings - Fork 468
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Over 2000 retries/second on connection loss #470
Comments
Okay, this happens in generic-pool in |
+1 |
I'm having the same issue during testing. Are there any workarounds for this? |
I backed off to the older version of |
+1 |
i am building a scheduled tasks runner that remote db offline is expected. This occurred to me during the test. It's good that the module would keep trying but blocking this process is not suitable in my case. Also, i think it would be better to follow 'let it break' in this case and let user handler the logic of retry. I am reverting back to tedious.js for now, which just has a pr for remote db goes to offline. It's pretty tedious to use that low-level library so i hope this can be improved soon. |
This is still happening for me. I'm trying to test reconnecting the pool (and retrying any pending queries). When I call function onConnectionError(err) {
connection.removeAllListeners('error');
connection.addListener('error', (e) => {
console.log('failed to close connection');
// every tick or so, a new ConnectionError appears
console.error(e);
});
connection.close((e) => {
// never reached if a connection disconnects
performReconnect();
});
} I can achieve this by running a query at an interval, waiting for it to timeout, having the error occur (caught by Some more info, if I don't add a listener for error before performing the close, an UnhandledPromiseRejection occurs. (and that took me a while to discover that's happening from within My method of testing is disabling the Ethernet/WiFi connection after a connection is made. It triggers a ENOTFOUND error, which returns immediately with no delay (since there's no network connection). It's possible that there's no timing buffer before retrying a connection. Regardless, any ConnectionPool that has |
@clshortfuse Thanks for your comprehensive update. Can you please confirm the node-mssql version you have installed? |
I'm using I can't tell exactly which Just to add, I believe it's related to some code (I forget where exactly) requesting a reconnect with |
Had a look for usage of Lines 268 to 279 in 691456d
Out of interest, what do you see when you perform this testing exercise with the |
The issue is still present in mssql 4.3.0. Once the pool has been created and the initial connection succeeds, any new connection issues result in an infinite loop. It's an issue with Pool._createResource when |
Perhaps it's time to revive #624? |
I decided to share a rewrite of the tedious connection pool I made. The original was a bit more complicated, (auto-deadlock handling, parameter mapping, and auto-connection retries) and it's being used in production. I trimmed it down for make it more modular. https://gist.github.com/clshortfuse/33447c2b731531ecf5a7a224f649e818 All you have to do is
|
Perhaps the recent patch to @clshortfuse care to test? PS: It may be better to resolve the bug in the underlying library rather than re-write your own pool for tedious specifically? Or add a custom evictor to the current library? |
@dhensby It's still broken in
I was just rewriting my connection pooler and remembered about this issue and figured I'd share my pool code for others. It's pretty clean without using any complicated timers or sequencing which avoids race conditions. It basically maintains a queue of JS Promises. The only thing I would think needs a bit of tweaking is the idle check interval. There's a more efficient way than checking every X seconds for idle connections. |
@clshortfuse thanks for this - I'll look into it |
@clshortfuse with the code your provided the behaviour is as follows:
|
well, to elaborate on this, this is actually because you are calling However, I think we can fix this by checking whether the global connection is connected or not... see #804 |
@dhensby I suggest you run the code. It has nothing to do with I was only using the |
You can use this
And it'll still cause the issue. If you don't use connection.addListener('error'), then an UnhandledPromiseRejectionWarning is emitted, as I said in the October comment above.
And as the warning states, in the future, NodeJS will exit the app when it encounters an unhandled promise rejections. This was the primary reason why I had to stop using the built-in connection pooling, |
I... did?? That's why I am able to provide my experience of what happens. I can remove |
@dhensby Sorry, I understood
When the issue happens regardless of me calling it. I'm not sure what "this" was in reference to. I assumed it's the infinite error loop. |
Actually, re-reading your comment, you said 'NEVER REACHED' is logged. This does not happen for me. The environments could be different. I used to run on this on a Linux container, but I'm able to reproduce it now on Mac OS X v14.10. Even if I do:
The process will never exit. |
Ah, no, that's just for the final point which, I agree, is inconsequential to your bug report However I am not getting an infinite loop. It stops at about 1000 errors (connection attempts) can you share the non-secret parts of your DB config? |
The config is pretty limited:
You say you get about 1000 errors. I've been letting it spit out errors for the last 2 minutes. It's 120,000 errors with no sign of stopping, which is about 2000/sec as the original topic states. This is the error it spits out:
That repeats infinitely. |
@clshortfuse to start, I'm testing on v5.0.0-beta.1 - what version are you currently using? I've modified your supplied code slightly just to keep the verbosity down: const mssql = require('mssql');
const sqlConfig = {
password: '********',
database: '********',
// connectionTimeout: undefined,
// requestTimeout: 30000,
stream: false,
options: { encrypt: true },
port: 1433,
user: '********',
server: 'localhost',
pool: {
acquireTimeoutMillis: 15000,
},
};
let errorCount = 0;
let pool = null;
/** @return {void} */
function reconnect() {
mssql.connect(sqlConfig).then((connection) => {
/**
* @param {Error} err
* @return {void}
*/
function onConnectionError(err) {
pool = null;
connection.removeAllListeners('error');
connection.addListener('error', (e) => {
errorCount++;
console.log('failed to close connection');
// Every tick or so, a new ConnectionError appears
// Gets stuck in infinite loop.
console.error('connection error', errorCount);
});
connection.close((e) => {
// Never reached if a connection disconnects
console.log('NEVER REACHED!');
// Retry in 10 seconds
setTimeout(reconnect, 10000);
});
}
connection.on('error', onConnectionError);
pool = connection;
}).catch((err) => {
errorCount++;
console.error('initial connection error', err);
clearInterval(interval);
});
}
/** @return {void} */
function getTime() {
if (!pool) {
console.log('no pool');
return;
}
pool.request().query('SELECT GETUTCDATE()').then((result) => {
console.log(result);
console.log('DISCONNECT NETWORK ADAPTER NOW!');
}).catch((err) => {
errorCount++;
console.error('error', errorCount);
clearInterval(interval);
});
}
const interval = setInterval(getTime, 5000);
reconnect(); From that I get this output:
and the process exits with exit code 0 |
@clshortfuse I think I'm getting a better understanding of this now. I'm going to close this as I've opened a new issue so that it's a bit less noisy (#805). I'd really appreciate your comment on it. |
@clshortfuse you're right, this is a complete excrement exhibit. I've made the changes I can to #805 to make this a bit more reasonable, but there's still an issue where the pool will still try to create connections even after close the pool (see coopernurse/node-pool#256) I've also opened #808, but this changes APIs so can't come out in v4 or v5... thought I don't suspect v6 is too far off given tedious are releasing new versions like it's going out of fashion |
When I start my application, then stop the DB server, and then try to execute a query on the server, mssql 4.0.1 tries to reconnect 2700 times per second on my laptop:
There should probably be a small delay after which mssql reconnects.
The text was updated successfully, but these errors were encountered: