const HEALTHY_CHECK_INTERVAL_MS = 10000; const MODULE_NAME = require('path').basename(__filename); const mysql = require('mysql'); const config = require('komodo-sdk/config'); const logger = require('tektrans-logger'); const connectionLimit = config.mysql && config.mysql.pool_connection_limit ? config.mysql.pool_connection_limit : 0; const ERROR_POOL_NOT_READY = new Error(`${MODULE_NAME}: pool is not ready`); exports.ERROR_POOL_NOT_READY = ERROR_POOL_NOT_READY; const pool = config.mysql ? mysql.createPool({ connectionLimit, host: config.mysql.host || 'localhost', database: config.mysql.database || 'komodo', user: config.mysql.user || 'komodo', password: config.mysql.password, timezone: config.mysql.timezone, }) : null; exports.pool = pool; exports.query = (query, values, cb) => { // pool.query.apply(null, arguments); if (!pool || !pool.query) { logger.warn(`${MODULE_NAME}: ${ERROR_POOL_NOT_READY.toString()}`); if (typeof cb === 'function') { cb(ERROR_POOL_NOT_READY); } return; } pool.query(query, values, cb); }; exports.format = (sql, values, cb) => new Promise((resolve, reject) => { if (!pool) { reject(ERROR_POOL_NOT_READY); if (typeof cb === 'function') cb(ERROR_POOL_NOT_READY); return; } pool.getConnection((err, connection) => { if (err) { reject(err); if (typeof cb === 'function') cb(err); return; } const formatted = connection.format(sql, values); connection.release(); resolve(formatted); if (typeof cb === 'function') cb(null, formatted); }); }); exports.beginConnection = (cb) => new Promise((resolve) => { pool.getConnection((errGetConnection, connection) => { if (errGetConnection) { resolve([errGetConnection]); if (typeof cb === 'function') cb(errGetConnection); return; } connection.beginTransaction((errBeginTransaction) => { if (errBeginTransaction) { resolve([errBeginTransaction]); if (typeof cb === 'function') cb(errBeginTransaction); return; } resolve([null, connection]); if (typeof cb === 'function') cb(null, connection); }); }); }); exports.getBy = (tableName, fieldName, value, cb) => new Promise((resolve) => { const query = 'SELECT * FROM ?? WHERE ?? = ? LIMIT 1'; const values = [tableName, fieldName, value]; pool.query(query, values, (err, results) => { const result = results && results[0]; resolve([err, result || null]); if (typeof cb === 'function') cb(err, result || null); }); }); function healthyCheck() { const query = 'SELECT 1'; const values = []; if (!pool) { logger.warn(`${MODULE_NAME}: Skip healthy check on undefined pool (ERR-EB9E5C08)`); return; } if (!pool.query) { logger.warn(`${MODULE_NAME}: Skip healthy check on undefined pool.query (ERR-D10F70F3)`); return; } pool.query(query, values, (err) => { if (err) { logger.warn(`${MODULE_NAME}: Error on healthy check (ERR-38EC9B78)`, { err }); } }); } setInterval(() => { const randomMs = Math.floor(Math.random() * HEALTHY_CHECK_INTERVAL_MS * 0.3); setTimeout(() => { try { healthyCheck(); } catch (err) { logger.warn(`${MODULE_NAME}: Exception on periodic healthy check (ERR-2D137502)`, { err }); } }, randomMs); }, HEALTHY_CHECK_INTERVAL_MS);