Connection.connect callback may never be executed
See original GitHub issueI’ve found a subtle inconsistency between mysql and mysql2…
mysql separates the creation of a Connection object and the establishment of a database connection, i.e.
var mysql = require('mysql');
// Create the connection object
var connection = mysql.createConnection({
host : 'example.org',
user : 'bob',
password : 'secret'
});
// Actually establish a database connection
connection.connect(function(err) {
if (err) {
console.error('error connecting: ' + err.stack);
return;
}
console.log('connected as id ' + connection.threadId);
});
However mysql2 both creates the Connection object and establishes the database connection in the Connection constructor, emitting a connect event when successful.
mysql2 attempts to maintain compatibility with mysql by adding a connect function, which listens for the connect event and executes the callback, however this creates a potential race condition where if the connect event is emitted before connection.connect(cb)
is called, the callback will never be executed. The following code demonstrates the problem…
const mysql = require('mysql2');
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
});
connection.on('connect', () => {
console.log('Connection established');
connection.connect(() => {
console.log('Connect callback executed'); // <------ NEVER REACHED
});
})
setTimeout(() => {
console.log('Timeout');
process.exit(1);
}, 5000);
$ node index.js
Connection established
Timeout
I discovered this problem while trying to switch marv-mysql-driver to mysql2. I can easily rewrite my code to not go async between initiating the connection and calling connect, but thought it was worth mentioning, as it could affect other applications, and could be fixed by executing the callback immediately if the connection was currently active, or with an error if the connection had already been closed.
Issue Analytics
- State:
- Created 3 years ago
- Comments:8 (5 by maintainers)
One way of doing this is to create “MITM” stream and use it as custom transport via “stream” option - https://github.com/sidorares/node-mysql2/blob/master/documentation/Extras.md#connecting-using-custom-stream That way you don’t need to control real server to kill the connection
Alternatively use
createServer()
and actually kill connection from server side, in that case both client and server live in the same node processWill do