newbeely-nodejs
Version:
简单易用的轻量级nodejs服务框架. 框架简单到只有组件逻辑,不同的组件提供不同的服务,使用外部的配置文件(只有一个配置文件)方便的组合成一个完整的服务框架. 整个服务使用bearcat(网易开源的nodejs面向切面编程的轻量级框架(AOP))管理,极大的解耦组件间的耦合.(关于代码热更新后续开放).
245 lines (223 loc) • 6.58 kB
JavaScript
/**
* 本组件代码是copy github 上 mongooseRedisCacheComponent模块的代码
* @filename mongooseRedisCacheComponent
*
* @module Component
*
* @author Gandalfull <orientcountry@gmail.com>
* @version 1
* @time 2016-02-19 10:03
*/
var FS = require('fs'),
Redis = require('redis'),
Logger = require('pomelo-logger').getLogger('newbeely', 'mongooseRedisCacheComponent'),
EventEmitter = require('events').EventEmitter,
Util = require('util'),
Mongoose = require('mongoose'),
Path = require('path'),
__ = require('underscore')
/**
* @event INITED
* @type {string}
*/
var INITED = "inited";
/**
* @event STARTING
* @type {string}
*/
var STARTING = "starting";
/**
* @event STARTED
* @type {string}
*/
var STARTED = "started";
/**
* @event STOPED
* @type {string}
*/
var STOPED = 'stoped';
/**
* mongoose + redis 结合的使用
*
* @class MongooseRedisCacheComponent
* @param sid {String} 组件id
* @param opts {*} 数据库参数配置
* @constructor
*/
function MongooseRedisCacheComponent(sid, opts) {
EventEmitter.call(this);
/**
* sid
*
* @property sid
* @type {String}
*/
this.sid = sid;
/**
* opts
*
* @property opts
* @type {Object}
*/
this.opts = opts;
/**
* App Instance
*
* @property app
* @type {Object}
*/
this.app = null;
/**
* Mongo Connection Pool
*
* @property connection
* @type {Object}
*/
this.connections = [];
Logger.info("MongooseComponent created.");
}
Util.inherits(MongooseRedisCacheComponent, EventEmitter);
/**
* 初始化组件
*
* @method init
* @async
* @for MongooseRedisCacheComponent
* @return null
*/
MongooseRedisCacheComponent.prototype.init = function () {
this.opts["path"] = Path.normalize(this.app.workedir + "/app/" + this.sid);
this.schemas = {};
/// 加载schema文件
try {
var schemas = FS.readdirSync(this.opts.path + "/schemas");
for (var i in schemas) {
if (!schemas.hasOwnProperty(i)) continue;
if (Path.extname(schemas[i]) === '.js') {
var schema = require(Path.normalize(this.opts.path + "/schemas/" + schemas[i]));
if (schema) {
this.schemas[schema.name] = schema.schema;
}
}
}
} catch (e) {
Logger.warn('Load mongoose schemas failed:' + JSON.stringify(e.stack));
}
var client = Mongoose.redisClient = Redis.createClient(this.opts.redis.port || 6379, this.opts.redis.host || "127.0.0.1", {});
this.app.set('redisClient', client);
if (this.opts.redis.pass && this.opts.redis.pass.length > 0) {
client.auth(this.opts.redis.pass, function (error) {
if (error) {
Logger.error("Redis auth failed:" + JSON.stringify(error.stack));
}
});
}
Mongoose.Query.prototype.execCache = function (callback) {
var _this = this;
var model = _this.model;
var query = _this._conditions;
var options = _this._optionsForExec(model);
var fields = __.clone(_this._fields);
var schemaOptions = model.schema.options;
var expires = schemaOptions.expires || 60;
if (!schemaOptions.redisCache && options.lean) {
Logger.warn("Unused redis cache by findByCache!");
return Mongoose.Query.prototype.exec().apply(_this, arguments);
}
var key = schemaOptions.redisCache + JSON.stringify(query) + JSON.stringify(options) + JSON.stringify(fields);
function redisCallback(err, result) {
var docs;
if (err) {
return callback(err);
}
if (!result) {
return Mongoose.Query.prototype.exec.call(_this, function (err, docs) {
if (err) {
return callback(err);
}
client.set(key, JSON.stringify(docs));
client.expire(key, expires);
return callback(null, docs);
});
} else {
docs = JSON.parse(result);
Logger.debug("Redis cache data ok:" + key);
return callback(null, docs);
}
};
client.get(key, redisCallback);
return _this;
}
this.emit(INITED);
}
/**
* 启动组件
*
* @method start
* @for MongooseRedisCacheComponent
* @async
* @return null
*/
MongooseRedisCacheComponent.prototype.start = function () {
var user = this.opts.user || "";
Logger.info("MongooseRedisCacheComponent " + this.sid + " is starting...");
this.emit(STARTING);
var url = "mongodb://" + ( user != "" ? (this.opts.user + ":" + this.opts.password + "@") : "") + this.opts.host + ":" + this.opts.port + "/" + this.opts.dbname;
var _this = this;
function create_connection() {
var connection = Mongoose.createConnection(url);
connection.on('error', function (error) {
Logger.error("Mongodb error:" + error);
});
connection.once('connected', function () {
Logger.info("Mongodb connected to :" + url);
for (var i in _this.schemas) {
connection.model(i, _this.schemas[i]);
}
_this.emit(STARTED);
});
connection.on('disconnected', function () {
Logger.warn("Mongodb disconnected from : " + url);
setTimeout(function () {
Logger.info('Mongoose reconnect to : ' + url);
connection.open(url);
}, 1000);
});
_this.connections.push(connection);
}
for (var i = 0; i < (this.opts.pool || 1); i++) {
create_connection();
}
Logger.info("MongooseRedisCacheComponent " + this.sid + " is started!");
}
/**
* 获取数据库连接
*
* @method getConnection
* @for MongooseComponent
*/
MongooseRedisCacheComponent.prototype.getConnection = function () {
return __.sample(this.connections);
};
/**
*
*
* @method stop
* @for MongooseRedisCacheComponent
*/
MongooseRedisCacheComponent.prototype.stop = function () {
this.emit(STOPED);
};
module.exports = {
id: "mongooseRedisCacheComponent",
func: MongooseRedisCacheComponent,
init: "init",
scope: "prototype",
args: [
{name: "sid", "type": "String"},
{name: "opts", type: "Object"}
],
"props": [
{name: "app", "ref": "application"}
]
};