-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathscripto.js
163 lines (120 loc) · 4.3 KB
/
scripto.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
var fs = require('fs');
var path = require('path');
var debug = require('debug')('scripto');
var luamin = require('luamin');
function Scripto (redisClient) {
var scripts = {};
var scriptShas = this._scriptShas = {};
this.load = function load(scriptObject) {
Object.keys(scriptObject).forEach(key => {
scriptObject[key] = luamin.minify(scriptObject[key]);
});
mergeObjects(scripts, scriptObject);
loadScriptsIntoRedis(redisClient, scriptObject, afterShasLoaded);
};
this.loadFromFile = function loadFromFile(name, filepath) {
var loadedScripts = {};
loadedScripts[name] = fs.readFileSync(filepath, 'utf8');
this.load(loadedScripts);
};
this.loadFromDir = function loadFromDir(scriptsDir) {
var loadedScripts = loadScriptsFromDir(scriptsDir);
this.load(loadedScripts);
};
this.run = function run(scriptName, keys, args, callback) {
if(scripts[scriptName]) {
if(scriptShas[scriptName]) {
var sha = scriptShas[scriptName];
evalShaScript(redisClient, sha, keys, args, callback);
} else {
var script = scripts[scriptName];
evalScript(redisClient, script, keys, args, callback);
}
} else {
callback(new Error('NO_SUCH_SCRIPT'));
}
};
this.eval = function eval(scriptName, keys, args, callback) {
if(scripts[scriptName]) {
var script = scripts[scriptName];
evalScript(redisClient, script, keys, args, callback);
} else {
callback(new Error('NO_SUCH_SCRIPT'));
}
};
this.evalSha = function evalSha(scriptName, keys, args, callback) {
if(scriptShas[scriptName]) {
var sha = scriptShas[scriptName];
evalShaScript(redisClient, sha, keys, args, callback);
} else {
callback(new Error('NO_SUCH_SCRIPT_SHA'));
}
};
//load scripts into redis in every time it connects to it
redisClient.on('connect', function() {
debug('loading scripts into redis again, aftet-reconnect');
loadScriptsIntoRedis(redisClient, scripts, afterShasLoaded);
});
//reset shas after error occured
redisClient.on('error', function(err) {
var errorMessage = (err)? err.toString() : "";
debug('resetting scriptShas due to redis connection error: ' + errorMessage);
scriptShas = {};
});
function afterShasLoaded(err, shas) {
if(err) {
debug('scripts loading failed due to redis command error: ' + err.toString());
} else {
debug('loaded scriptShas');
mergeObjects(scriptShas, shas);
}
}
function mergeObjects (obj1, obj2) {
for(var key in obj2) {
obj1[key] = obj2[key];
}
}
}
module.exports = Scripto;
function loadScriptsFromDir(scriptsDir) {
var names = fs.readdirSync(scriptsDir);
var scripts = {};
names.forEach(function(name) {
var filename = path.resolve(scriptsDir, name);
var key = name.replace('.lua', '');
scripts[key] = fs.readFileSync(filename, 'utf8');
});
return scripts;
}
function loadScriptsIntoRedis (redisClient, scripts, callback) {
var cnt = 0;
var keys = Object.keys(scripts);
var shas = {};
(function doLoad() {
if(cnt < keys.length) {
var key = keys[cnt++];
redisClient.send_command('script', ['load', scripts[key]], function(err, sha) {
if(err) {
callback(err);
} else {
shas[key] = sha;
doLoad();
}
});
} else {
callback(null, shas);
}
})();
}
function evalScript(redisClient, script, keys, args, callback) {
var keysLength= keys.length || 0;
var arguments = [keysLength].concat(keys, args);
arguments.unshift(script);
redisClient.send_command('eval', arguments, callback);
}
function evalShaScript(redisClient, sha, keys, args, callback) {
var keysLength= keys.length || 0;
var arguments = [keysLength].concat(keys, args);
arguments.unshift(sha);
redisClient.send_command('evalsha', arguments, callback);
}