1 | var _ = require("underscore");
|
2 | var DataLayer = require("./DataLayer");
|
3 | var helpers = require("../helpers");
|
4 |
|
5 | module.exports = DataLayer.extend("RedisLayer", {
|
6 |
|
7 |
|
8 | parseArguments: function(args){
|
9 | switch(args.length){
|
10 | case 0: return false;
|
11 | case 1:
|
12 | if(typeof args[0] !== "function") return false;
|
13 | else return [undefined,{},args[0]];
|
14 | case 2:
|
15 | if(typeof args[1] !== "function") return false;
|
16 | else return [args[0],{}, args[1]];
|
17 | case 3:
|
18 | if(typeof args[2] !== "function") return false;
|
19 | else return [args[0],args[1], args[2]];
|
20 | default: return false;
|
21 | }
|
22 | },
|
23 |
|
24 | parseResults: function(pattern, options, cb){
|
25 | var self = this;
|
26 | return function(err, results){
|
27 |
|
28 | if(typeof pattern === "number"){
|
29 | if(results[0]) return cb(null, _.extend(JSON.parse(results[0]), _.object([[self.primaryKey, parseInt(pattern)]])));
|
30 | else return cb(null, null);
|
31 | }
|
32 | else if(Array.isArray(pattern)){
|
33 | return cb(null, pattern.map(function(id, index){
|
34 | if(!results[index]) return null;
|
35 | var object = JSON.parse(results[index]);
|
36 | _.extend(object, _.object([[self.primaryKey, parseInt(id)]]));
|
37 | if(options.fields) object = _.pick(object, options.fields);
|
38 | return object;
|
39 | }));
|
40 | }
|
41 | else{
|
42 | var objects = [];
|
43 | for(var key in results){
|
44 | var object = JSON.parse(results[key]);
|
45 | _.extend(object, _.object([[self.primaryKey, parseInt(key)]]))
|
46 | objects.push(options.fields? _.pick(object, options.fields) : object);
|
47 | }
|
48 | cb(null, objects);
|
49 | }
|
50 | };
|
51 | },
|
52 |
|
53 | create: function(obj, options, cb){
|
54 | var data = _.omit(_.pick(obj, _.keys(this.fields)), [this.primaryKey]);
|
55 | var primaryKey = primaryKey = ++this.pk;
|
56 | this.redis.hmset(this.hashName, primaryKey, JSON.stringify(data), function(err){
|
57 | if(err) return cb(err);
|
58 | data.primaryKey = primaryKey;
|
59 | cb(null, data)
|
60 | });
|
61 | },
|
62 |
|
63 | find: function(pattern, options, cb){
|
64 | if(!pattern) return this.redis.hgetall(this.hashName, this.parseResults(pattern, options, cb));
|
65 | this.redis.hmget(this.hashName, pattern, this.parseResults(pattern, options, cb));
|
66 | },
|
67 |
|
68 | findOne: function(pattern, options, cb){
|
69 |
|
70 | },
|
71 |
|
72 | update: function(pattern, options, cb){
|
73 | var self = this;
|
74 | if(Array.isArray(pattern)){
|
75 | pattern = pattern.filter(function(obj){
|
76 | return obj.hasOwnProperty(self.primaryKey);
|
77 | });
|
78 | var objIndex = _.indexBy(pattern, this.primaryKey);
|
79 | this.find(_.pluck(pattern, this.primaryKey), options, function(err, results){
|
80 | if(err) return cb(err);
|
81 | var updates = [];
|
82 | results.forEach(function(result){
|
83 | if(result) {
|
84 | var id = result[self.primaryKey];
|
85 | _.extend(result, objIndex[id])
|
86 | var data = JSON.stringify(_.omit( _.pick(result, self.publicFields || _.keys(self.fields)), [self.primaryKey]));
|
87 | updates.push([id, data]);
|
88 | }
|
89 | });
|
90 | updates.push();
|
91 | self.redis.hmset.call(self.redis, self.hashName, _.object(updates), function(err){
|
92 | if(err) return cb(err);
|
93 | cb(null, results);
|
94 | });
|
95 |
|
96 | });
|
97 | }
|
98 | else{
|
99 | if(!_.has(pattern, this.primaryKey)) return cb("Can't find primary key for update");
|
100 | this.find(pattern[this.primaryKey], {}, function(err, object){
|
101 | if(err) return cb(err);
|
102 | if(!object) return cb("Can't find object");
|
103 | _.extend(object, _.pick(pattern, self.publicFields || _.keys(self.fields)));
|
104 | var data = JSON.stringify(_.omit(object, [self.primaryKey] ) );
|
105 |
|
106 | self.redis.hmset(self.hashName, _.object([[pattern[this.primaryKey], data]]), function(err){
|
107 | if(err) return cb(err);
|
108 | return cb(null, object);
|
109 | });
|
110 | });
|
111 | }
|
112 | },
|
113 |
|
114 | delete: function(pattern, options, cb){
|
115 | if(typeof pattern === "number"){
|
116 | this.redis.hdel(this.hashName, pattern, cb);
|
117 | }
|
118 | else if(Array.isArray(pattern)){
|
119 | var self = this;
|
120 | helpers.amap(pattern, function(id, cb){
|
121 | self.redis.hdel(self.hashName, id, cb);
|
122 | }, cb);
|
123 | }
|
124 | else if(pattern === null){
|
125 | self.redis.hdel(self.hashName, cb);
|
126 | }
|
127 |
|
128 | },
|
129 |
|
130 |
|
131 | }, {
|
132 |
|
133 | setupDatabase: function(self, env, name){
|
134 | var Prototype = this;
|
135 | self.setupNode = function(cb){ Prototype.setupStore(self, env, function(err){
|
136 | if(err) return cb(err);
|
137 | env.i.do("log.sys", "DataLayer:redis", name);
|
138 | cb();
|
139 | }); }
|
140 | },
|
141 |
|
142 | setupStore: function(instance, env, cb){
|
143 | instance.redis = env.engines.redis;
|
144 |
|
145 | instance.redis.hgetall(instance.hashName, function(err, obj){
|
146 | if(err) return cb(err);
|
147 | if(!obj) {
|
148 | instance.pk = 0;
|
149 | return cb();
|
150 | }
|
151 |
|
152 | var keys = _.keys(obj).sort();
|
153 | var length = keys.length;
|
154 | var last = parseInt(keys.pop());
|
155 | instance.pk = last
|
156 | cb();
|
157 | });
|
158 |
|
159 | },
|
160 |
|
161 | extend: function(name, props, statics){
|
162 | this.setMethods(this.prototype, props);
|
163 | return DataLayer.extend.apply(this, arguments);
|
164 | }
|
165 | });
|