dl
Version:
DreamLab Libs
211 lines (181 loc) • 6.29 kB
JavaScript
/**
* @overview MySQLCredentialPool
* @copyright Dreamlab Onet.pl sp. z. o o 2012
*/
var MySQLPool = require('core').client.MySQLPool;
var CredentialsManager = require('../credentials/Manager.js').CredentialsManager;
var mysql = require('mysql');
/**
* @class MySQLCredentialPool
* @classdesc MySQL connection pool.
* @param {String} credential credential key
* @param {String} identity credential identity
*/
var MySQLCredentialPool = function (credential, identity) {
var that = this;
MySQLPool.call(this);
this._credential = credential;
this._cm = CredentialsManager.factory(identity);
this._cm.addEventListener(CredentialsManager.Event.LOADED, credential, function (data) {
that._createSpareClients(data.data);
});
this._cm.addEventListener(CredentialsManager.Event.ERROR, credential, function (data) {
console.error('CREDENTIAL ERROR: ' + credential +
'. Error while receiving credential data for MySQLPool',
JSON.stringify(data.data));
setTimeout(function () {
console.info('CREDENTIAL INFO: getting credential -> ' +
credential);
that._cm.renewCredential(credential);
}, 500);
});
};
MySQLCredentialPool.prototype = Object.create(MySQLPool.prototype);
/**
* Create clients
* @method
*/
MySQLCredentialPool.prototype.connect = function () {
this._cm.getCredential(this._credential);
};
/**
* Create spare clients
* @method
* @param {Object} data
*/
MySQLCredentialPool.prototype._createSpareClients = function (data) {
console.info('MySQLCredentialPool>MySQL create connections: %s', JSON.stringify(data));
var randIndex = Math.round(Math.random() * (data.hosts.length - 1)),
host = data.hosts[randIndex].host,
port = data.hosts[randIndex].port,
max_connections = data.max_connections || 1;
console.info('MySQLCredentialPool>MySQL connecting to: %s:%d', host, port);
var create_connections = max_connections - this.getKnownLength();
console.info('MySQLCredentialPool>MySQL connections', (create_connections > 0 ? 'shortage' : 'overhead'), create_connections);
var connectionOptions = {
user: data.user,
password: data.pass,
host: host,
port: port,
database: data.db_name
};
if (create_connections > 0) {
this._createConnections(connectionOptions, create_connections);
} else if (create_connections < 0) {
/*
* zamieniam liczbe ujemna na dodatnia, np.:
* -5 = 5;
* oznacza ze usuwamy 5 połaczeń
*/
create_connections = -create_connections;
this._removeConnections(create_connections);
}
this._executeQueuedQueries();
};
/**
* Usuwanie nadmiarowych polaczen
*
* @param {Number} n ilosc nadmiarowych polaczeń
*/
MySQLCredentialPool.prototype._removeConnections = function (n) {
var that = this;
for (var i = 0; i < n; i++) {
if (this.getKnownLength() == 0) {
break;
}
this.get(function (client) {
that.markForDeletion(client);
that.release(client);
});
}
};
/**
* Tworzenie brakujacych polaczen
*
* @param {Object} connectionOptions - opcje dla polaczenia MySQL (host, port)
* @param {Number} n - ilosc połączeń do utworzenia
*/
MySQLCredentialPool.prototype._createConnections = function (connectionOptions, n) {
var toCount = n;
var that = this;
var isError = false;
var onConnection = function (err) {
if (err) {
isError = true;
}
/* semafór */
if (--toCount) return;
/* *** */
if (isError) {
that._scheduleRenewCredential();
}
};
for (var i = 0; i < n; i++) {
this._createConnection(connectionOptions, onConnection);
};
};
/**
* Towrzenie pojedynczego połączenia do MySQL
*
* @param {Object} connectionOptions - opcje dla polaczenia MySQL (host, port)
* @param {Function} callback - callback po zakonczeniu tworzenia połaczenia
*/
MySQLCredentialPool.prototype._createConnection = function (connectionOptions, callback) {
var that = this;
var client = mysql.createConnection(connectionOptions);
var onConnectionError = function (error) {
client.destroy();
callback(error);
};
/* timeout connectu do MySQL */
var connectTimeout = setTimeout(function () {
console.warn('MySQLCredentialPool>MySQL connection timeout');
that._removeClient(client);
onConnectionError(new Error('MySQL Connection error'));
}, 500);
client.connect(function (err) {
/* czyszcze timeout - udalo sie zakonczyc faze polączenia */
clearTimeout(connectTimeout);
if (err) {
console.warn('MySQLCredentialPool>MySQL connection error:', err);
onConnectionError(err);
} else {
console.warn('MySQLCredentialPool>MySQL connection established');
callback(null);
}
});
client.on('close', function (err) {
console.warn('MySQLCredentialPool>MySQL Close:', err);
that._removeClient(client);
});
client.on('error', function (err) {
console.warn('MySQLCredentialPool>MySQL Error', err);
});
client.query("SET NAMES utf8");
this.add(client);
};
/**
* Usuwanie klienta MySQL z puli.
* Triggeruje odświeżenie credentiali.
*
* @param {MySQLClient} client - klient mysqla
*/
MySQLCredentialPool.prototype._removeClient = function (client) {
this.markForDeletion(client);
this.release(client);
this._scheduleRenewCredential();
};
MySQLCredentialPool.prototype._scheduleRenewCredential = function () {
/* jesli timer jest juz ustawiony to wychodze */
if (this._credentialTimer) return;
var that = this;
this._credentialTimer = setTimeout(function () {
that._credentialTimer = null;
that._cm.renewCredential(that._credential);
}, 2500);
};
MySQLCredentialPool.prototype.destroy = function () {
this._cm.removeAllEventListeners(CredentialsManager.Event.LOADED);
this._cm.removeAllEventListeners(CredentialsManager.Event.ERROR);
};
exports.MySQLCredentialPool = MySQLCredentialPool;