import {MysqlDB,MysqlUtil} from '../extra/mysqldb'; // const RedisBridge = require(Core.Path.ExtraLib + '/redisdb.js'); import MongoDB from 'mongodb'; import MemcacheDB from 'memcached'; import * as RedisDB from 'redis'; (global as any).MysqlUtil = MysqlUtil; //默认配置 const DatabaseOption:any = { mysql : '{"host":"localhost","port":3306,"user":"root","password":"","database":"","prefix":"","connectionLimit":10}', mongodb : '{"host":"localhost","port":27017,"user":null,"password":"","database":"","prefix":""}', memcache : '{"host":"localhost","port":11211}', redis : '{"host":"localhost","port":6379,"prefix":null}' } class Database { /** * @param {String} DatabaseType 数据库类型 * @param {Object} option 数据库配置 * @param {String} GlobalName 自动全局命名 * @param {Function} callback 回调函数 */ public static async create(DatabaseType:string,option:DBOption,GlobalName?:string){ DatabaseType = DatabaseType.toLowerCase(); switch(DatabaseType){ case 'mysql': return await Creater._createMysqlConnection(option,GlobalName); case 'mongodb': return await Creater._createMongoConnection(option,GlobalName); case 'memcache': return await Creater._createMemcacheConnection(option,GlobalName); case 'redis': return await Creater._createRedisConnection(option,GlobalName); default: return {err:new Error('Wrong database type!')}; } } //生成默认配置 public static getOption(type:string){ type = type.toLowerCase(); if(DatabaseOption[type]!=undefined){ return JSON.parse(DatabaseOption[type]); }else{ return null; } } } //连接控制器 class Creater{ static _createMysqlConnection (option:DBOption,GlobalName?:string){ return new Promise((resolve,reject)=>{ const _MysqlDB = new MysqlDB(option); // if(!callback || typeof(callback)!='function') callback = ()=>{return} //连接测试 _MysqlDB.query('SELECT VERSION() as version',(err,result,fields?:any)=>{ if(err){ LOGGER.error('Mysql Connect error,please recheck your config'); if(err.stack) LOGGER.error(err.stack); return resolve({err}) }else{ LOGGER.info('Mysql Connect success'); LOGGER.info(`Mysql Version: ${result[0]['version']} | User: ${option.user} | Database: ${option.database} | GlobalName: ${GlobalName}`); if(GlobalName){ if((global as any)[GlobalName]){ LOGGER.error(`Create global name fail with "${GlobalName}"`); return resolve({err:new Error('Duplicate global name')}) }else{ (global as any)[GlobalName] = _MysqlDB; } } resolve({err:null,client:_MysqlDB}) } }); }) } static _createMongoConnection(option:DBOption,GlobalName?:string){ return new Promise((resolve,rejects)=>{ const verify = option.user?option.user+':'+option.password+'@':''; const mongoConnect = 'mongodb://' + verify + option.host+':'+option.port+'/'+option.database; // if(!callback) callback = ()=>{return} MongoDB.MongoClient.connect(mongoConnect,(err?:Error,db?:any)=>{ if(err) { LOGGER.error('MongoDB connect error!'); if(err.stack) LOGGER.error(err.stack); return resolve({err}) }else{ LOGGER.info(`Mongodb Connect success | GlobalName: ${GlobalName}`); const _mongoClient = { db:db, c:(collection:any)=>{ return db.collection(option.prefix+collection); } }; if(GlobalName){ if((global as any)[GlobalName]){ LOGGER.error(`Create global name fail with "${GlobalName}"`); return resolve({err:new Error('Duplicate global name')}) } (global as any)[GlobalName] = _mongoClient; } resolve({err:null,client:_mongoClient}) } }); }) } static _createMemcacheConnection(option:DBOption,GlobalName?:string){ return new Promise(async (resolve,reject)=>{ const _Memcache = new MemcacheDB(option.host+':'+option.port); _Memcache.version(function(err,data){ if(err){ LOGGER.error('Memcache Connect error,please recheck your config'); LOGGER.error(err); resolve({err}); }else{ LOGGER.info('Memcache Connect success'); LOGGER.info(`Memcache Version: ${data[0]['version']} | GlobalName: ${GlobalName}`); if(GlobalName){ if((global as any)[GlobalName]){ LOGGER.error(`Create global name fail with "${GlobalName}"`); resolve({err:new Error('Duplicate global name')}); return; }else{ (global as any)[GlobalName] = _Memcache; } } resolve({err:null,client:_Memcache}); } }); }); } static async _createRedisConnection(option:DBOption,GlobalName?:string){ return new Promise(async (resolve,reject)=>{ let _redisConnStr = `${option.host}:${option.port}`; _redisConnStr = `redis://${option.user||''}:${option.password||''}@${_redisConnStr}`; const _redisClient = RedisDB.createClient({url:_redisConnStr,socket:{keepAlive:30000}}); _redisClient.on('error',(err:Error)=>{ if(err instanceof RedisDB.SocketClosedUnexpectedlyError){ LOGGER.error(`Redis [${option.host}:${option.port}] connect has been refused,please recheck your config,and make sure redis server is running!`); resolve({err:err}); } }) _redisClient.on('ready',async ()=>{ LOGGER.info(`Redis Connect [${option.user||''}@${option.host}:${option.port}] success [${GlobalName||'UNKNOW'}]`); const infoStr = await _redisClient.info(); const infoLine = infoStr.split('\n'); const info:any = {}; for(const line of infoLine){ const lineArr = line.split(':'); if(lineArr.length>1) info[lineArr[0]] = lineArr[1]; } if(info.redis_version) LOGGER.info(`GlobalName: ${GlobalName||'UNKNOW'} | Server Version: ${info.redis_version}`); // _redisClient.stream.setKeepAlive(true,30 * 1000); if(GlobalName){ if((global as any)[GlobalName]){ LOGGER.error(`Create global name fail with "${GlobalName}"`); return resolve({err:new Error('Duplicate global name')}); }else{ (global as any)[GlobalName] = _redisClient; } } resolve({err:null,client:_redisClient}); }); _redisClient.on('reconnecting',function(e:any){ LOGGER.warn('Redis lost connect,reconnecting!'); }); await _redisClient.connect(); }) // {port:option.port,host:option.host,socket_keepalive:true,socket_initialdelay:30000,retry_strategy: function (retryData) { // if (retryData.error && retryData.error.code === 'ECONNREFUSED') { // } // if (retryData.total_retry_time > 1000 * 10) { // LOGGER.error('Redis retry connect time exhausted'); // } // if (retryData.attempt > 10) { // LOGGER.error('Redis unknow error'); // } // // reconnect after // return Math.min(retryData.attempt * 100, 3000); // },prefix:option.prefix}); // if(!callback || typeof(callback)!='function') callback = ()=>{} } } // (global as any).DBManager = Database; module.exports = Database;