MySQLサーバーから接続を切られた時は、errorイベントが発火する。一方で接続できなかった時はcallback関数の引き数にerrorオブジェクトが格納される。従って以下のように実装してみた。
var mysql = require('mysql'); var dbh = mysql.createConnection({ "host" : CONF['mysql']['host'], "user" : CONF['mysql']['user'], "password" : CONF['mysql']['pass'], "database" : CONF['mysql']['db'] }); var handleDisconnect = function(dbh){ dbh.on('error', function(err) { if (!err.fatal) { return; } if (err.code !== 'PROTOCOL_CONNECTION_LOST') { throw err; } console.log('Re-connecting lost connection: ' + err.stack); util.puts('mysql::connect'); dbh = mysql.createConnection(dbh.config); handleDisconnect(dbh); dbh.connect(dbhConnectHandler); }); } var dbhConnectHandler = function(err){ if (err) { util.puts('mysql::failed to connect[' + err.code + ']'); setTimeout( function(){ util.puts('mysql::connect'); dbh = mysql.createConnection(dbh.config); handleDisconnect(dbh); dbh.connect(dbhConnectHandler); }, 1000 * 30// 30 seconds ); } else { util.puts('mysql::connected'); } }; util.puts('mysql::connect'); handleDisconnect(dbh); dbh.connect(dbhConnectHandler);
PHPとかでMySQLに繋ぐのに慣れてると発想の転換が必要になる。
他のファイルのスクリプトと接続を共有する
expressを使っているとapp.jsでの接続をroutes/index.jsでも使いたい事がある。他にも方法はあると思うが以下のようにしてオブジェクトを共有している。
app.js
require('./share').dbh = dbh;
routes/index.js
var dbh = require('./share').dbh;
その場合は以下のようにして再接続後の接続を共有オブジェクトにセットする必要がある。
var mysql = require('mysql'); var dbh = mysql.createConnection({ "host" : CONF['mysql']['host'], "user" : CONF['mysql']['user'], "password" : CONF['mysql']['pass'], "database" : CONF['mysql']['db'] }); var handleDisconnect = function(dbh){ dbh.on('error', function(err) { if (!err.fatal) { return; } if (err.code !== 'PROTOCOL_CONNECTION_LOST') { throw err; } console.log('Re-connecting lost connection: ' + err.stack); util.puts('mysql::connect'); dbh = mysql.createConnection(dbh.config); handleDisconnect(dbh); dbh.connect(dbhConnectHandler); require('./share').dbh = dbh;// ...(a) }); } var dbhConnectHandler = function(err){ if (err) { util.puts('mysql::failed to connect[' + err.code + ']'); setTimeout( function(){ util.puts('mysql::connect'); dbh = mysql.createConnection(dbh.config); handleDisconnect(dbh); dbh.connect(dbhConnectHandler); require('./share').dbh = dbh;// ...(b) }, 1000 * 30// 30 seconds ); } else { util.puts('mysql::connected'); } }; util.puts('mysql::connect'); handleDisconnect(dbh); dbh.connect(dbhConnectHandler); require('./share').dbh = dbh;
仮に(a)と(b)が存在しない場合、以下の様なroutes/index.js内では古い接続に対してクエリを発行する事になる。
dbh.query("something query", null, function (err) { if (err) {/*err*/} else {/*success*/} });
この場合、厄介な事にcallbackが実行されず原因究明が困難となる。