-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
Reproduction du bug
Contexte :
- Parking créé en base
- Aucun équipement initialisé (Pas de get ni de set effectué)
- Controller qui se connecte
- Event loop en marche et alimentée
- On reçoit énormément d'évènements (dépilage)
- Pool mysql initialisée à la valeur par défaut (10) (Bug aussi constaté avec d'autres valeurs)
Description :
On observe le controller se connecter au serveur et commencer à dépiler les évènements très rapidement. Toutes les requêtes sont en erreur (erreur logique du "type pas de capteur en base", non pas erreur sql, c'est différent), ce qui déclenche le reject des promises.
Après une durée variable, le serveur plante sur une erreur fatale au niveau de la gestion de la pool de connections :
"stack": ["Error: Connection already released",
" at Pool.releaseConnection (/var/www/p022/com/node_modules/mysql/lib/Pool.js:129:13)",
" at PoolConnection.release (/var/www/p022/com/node_modules/mysql/lib/PoolConnection.js:30:15)",
" at Query.<anonymous> (/var/www/p022/com/src/utils/mysql_helper.js:62:28)",
" at Query.emit (events.js:129:20)",
" at Query.Sequence.end (/var/www/p022/com/node_modules/mysql/lib/protocol/sequences/Sequence.js:99:12)",
" at Query.ErrorPacket (/var/www/p022/com/node_modules/mysql/lib/protocol/sequences/Query.js:94:8)",
" at Protocol._parsePacket (/var/www/p022/com/node_modules/mysql/lib/protocol/Protocol.js:274:23)",
" at Parser.write (/var/www/p022/com/node_modules/mysql/lib/protocol/Parser.js:77:12)",
" at Protocol.write (/var/www/p022/com/node_modules/mysql/lib/protocol/Protocol.js:39:16)",
" at Socket.<anonymous> (/var/www/p022/com/node_modules/mysql/lib/Connection.js:96:28)"
],
"level": "error",
"message": "uncaughtException: Connection already released"
Analyse du bug
Observations techniques
L'exception est levée par la méthode releaseConnection() de la lib node_mysql, dans les lignes suivantes:
if (this._freeConnections.indexOf(connection) !== -1) {
// connection already in free connection pool
// this won't catch all double-release cases
throw new Error('Connection already released');
}Cette exception fait suite à l'exécution de notre code "générique" de helper mysql.
Quand une requête est finie, on libère explicitement la connexion :
var query = connection.query(sql, params, callback);
query.on('error', function (err) {
logger.log('error', 'Mysql query error: ' + err);
//logger.log('error', 'Mysql query error RANDOM: ' + rand);
callback(err, true);
connection.release();
});
query.on('result', function (rows) {
callback(false, rows);
});
query.on('end', function () {
//logger.log('info', 'Mysql query end RANDOM: ' + rand);
connection.release();
});Concrètement, la connexion qu'on libère dans l'évènement end à déjà été libérée.
Interprétation des faits
- Premièrement on lit dans la doc, section https://github.com/felixge/node-mysql#streaming-query-rows on lit ça:
You MUST NOT provide a callback to the query() method when streaming rows. - Deuxièmement, dans le code de la lib, on trouve une libération automatique de la connexion quand une requête exécutée dans une pool est terminée:
// Release connection based off event
query.once('end', function() {
conn.release();
});- CEPENDANT, si on ne fait pas notre release, le serveur se bloque, semblerait-il quand on a utilisé toutes les connexions de la pool.
Pistes:
- Utiliser direction
pool.queryau lieu de faire un getConnexion - Ne pas utiliser le principe de streaming-query-rows (supprimer les callbacks et faire un release connexion à la fin)
- Réfléchir encore plus.