Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
luin committed Feb 11, 2013
0 parents commit 56e49f8
Show file tree
Hide file tree
Showing 8 changed files with 345 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
@@ -0,0 +1,2 @@
.DS_Store
node_modules
10 changes: 10 additions & 0 deletions Makefile
@@ -0,0 +1,10 @@
TESTS = $(shell find test/ -name '*.test.js')

run-tests:
@./node_modules/.bin/mocha --timeout 3000 $(TESTS)

test:
@$(MAKE) NODE_PATH=lib TESTS="$(ALL_TESTS)" run-tests

.PHONY: test

18 changes: 18 additions & 0 deletions index.js
@@ -0,0 +1,18 @@
var redis = require('redis');

exports.createClient = function (port, host, prefix) {
if (typeof port === 'object') {
exports.redisClient = port;
prefix = host;
} else {
exports.redisClient = redis.createClient(port, host);
}
exports.prefix = prefix || 'Ranaly:';

return {
Amount: require('./type/amount')(exports),
Realtime: require('./type/realtime')(exports),
DataList: require('./type/data_list')(exports)
};
};

23 changes: 23 additions & 0 deletions package.json
@@ -0,0 +1,23 @@
{
"name": "ranaly",
"version": "0.1.0",
"description": "Ranaly client library",
"keywords": ["ranaly"],
"author": "Zihua Li <i@zihua.li> (http://zihua.li)",
"main": "./index.js",
"repository": {
"type": "git",
"url": "https://github.com/luin/node_ranaly.git"
},
"scripts": {
"test": "mocha"
},
"dependencies": {
"redis": "0.8.2",
"moment": "2.0.0"
},
"devDependencies": {
"redis-mock": "0.1.4",
"mocha": "*"
}
}
91 changes: 91 additions & 0 deletions test/index.js
@@ -0,0 +1,91 @@
/*jshint undef:false */
var assert = require('assert');
var redis = require('redis-mock').createClient();
var ranaly = require('../index');
var client = ranaly.createClient(redis);

var Amount = client.Amount;

var aDay = 24 * 3600000;
describe('Amount', function () {
var amount = new ranaly.Amount('demo');
var hour;
before(function (done) {
amount._get(function (err, data) {
hour = data;
done();
});
});

describe('incr', function () {
it('should have default increment and unixTime', function (done) {
amount.incr();
hour += 1;
amount._get(function (err, data) {
assert.equal(hour, data);
done();
});
});

it('should accept custom increment', function (done) {
amount.incr(2);
hour += 2;
amount._get(function (err, data) {
assert.equal(hour, data);
done();
});
});

it('should accept custom date', function (done) {
var yesterday = new Date(Date.now() - aDay);
var yesterdayData;
amount._get(yesterday, function (err, data) {
yesterdayData = data;
amount.incr(null, yesterday);
amount.incr(10, yesterday);
amount._get(yesterday, function (err, data) {
assert.equal(yesterdayData + 11, data);
done();
});
});
});

});

});

describe('Realtime', function () {
var realtime = new ranaly.Realtime('demo');
describe('set', function () {
it('should set the value successfully', function (done) {
realtime.set(10, function () {
realtime.get(function (err, result) {
assert.equal(10, result);
done(err);
});
});
});

});

describe('incr', function () {
it('should increase the value successfully', function (done) {
realtime.incr(function () {
realtime.get(function (err, result) {
assert.equal(11, result);
done(err);
});
});
});

it('should accept a custom increment', function (done) {
realtime.incr(10, function () {
realtime.get(function (err, result) {
assert.equal(21, result);
done(err);
});
});
});

});
});
114 changes: 114 additions & 0 deletions type/amount.js
@@ -0,0 +1,114 @@
var moment = require('moment');
var ZMSCORE = ' \
local result = {} \
local length = #ARGV \
for i = 1, length do \
local score = 0 \
if #ARGV[i] == 8 then \
for j = 0, 23 do \
local k = tostring(j) \
if #k == 1 then \
k = "0" .. k \
end \
local r = redis.call("zscore", KEYS[1], ARGV[i] .. k) \
if r then \
score = score + r \
end \
end \
else \
score = redis.call("zscore", KEYS[1], ARGV[i]) \
if not score then \
score = 0 \
else \
score = tonumber(score) \
end \
end \
result[i] = score \
end \
return result \
';

var ZSUMSCORE = ' \
local length = #ARGV \
local score = 0 \
if #ARGV >= 1 then \
for i = 1, length do \
if #ARGV[i] == 8 then \
for j = 0, 23 do \
local k = tostring(j) \
if #k == 1 then \
k = "0" .. k \
end \
local result = redis.call("zscore", KEYS[1], ARGV[i] .. k) \
if result then \
score = score + result \
end \
end \
else \
local result = redis.call("zscore", KEYS[1], ARGV[i]) \
if result then \
score = score + result \
end \
end \
end \
else \
local result = redis.call("get", KEYS[1] .. ":TOTAL") \
if result then \
score = tonumber(result) \
end \
end \
return score \
';
module.exports = function (ranaly) {
var db = ranaly.redisClient;

var Amount = function (bucket) {
this.bucket = bucket;
this.key = ranaly.prefix + 'AMOUNT' + ':' + this.bucket;
};

Amount.prototype.incr = function (increment, when, callback) {
if (typeof increment === 'function') {
callback = increment;
increment = void 0;
} else if (typeof when === 'function') {
callback = when;
when = void 0;
}
if (typeof increment !== 'number') {
increment = 1;
}
when = moment(when);
db.multi()
.incrby(this.key + ':TOTAL', increment)
.zincrby(this.key, increment,when.format('YYYYMMDDHH'))
.exec(function (err, result) {
if (typeof callback === 'function') {
callback(err, Array.isArray(result) ? result[0] : result);
}
});
};

Amount.prototype.get = function (timeList, callback) {
var next = function (err, result) {
callback(err, result);
};
db['eval'].apply(db, [ZMSCORE].concat(1).concat(this.key).concat(timeList).concat(next));
};

Amount.prototype.sum = function (timeList, callback) {
var next = function (err, result) {
callback(err, result);
};
var tl = [ZSUMSCORE].concat(1).concat(this.key);
if (Array.isArray(timeList) && timeList.length > 0) {
tl = tl.concat(timeList).concat(next);
} else {
tl = tl.concat(next);
}
db['eval'].apply(db, tl);
};

return Amount;
};

45 changes: 45 additions & 0 deletions type/data_list.js
@@ -0,0 +1,45 @@
module.exports = function (ranaly) {
var db = ranaly.redisClient;

var DataList = function (bucket) {
this.bucket = bucket;
this.key = ranaly.prefix + 'DATALIST' + ':' + this.bucket;
};

DataList.prototype.push = function (data, trim, callback) {
if (typeof trim === 'function') {
callback = trim;
trim = void 0;
}
if (typeof increment !== 'number') {
trim = 100;
}

db.multi()
.lpush(this.key, JSON.stringify(data))
.ltrim(this.key, 0, trim - 1)
.exec(function (err, result) {
if (typeof callback === 'function') {
if (!err) result = result[0];
callback(err, result);
}
});
};

DataList.prototype.range = function (start, stop, callback) {
db.lrange(this.key, start, stop, function (err, result) {
if (!err && Array.isArray(result)) {
result = result.map(function (r) {
return JSON.parse(r);
});
}
callback(err, result);
});
};

DataList.prototype.len = function (callback) {
db.llen(this.key, callback);
};

return DataList;
};
42 changes: 42 additions & 0 deletions type/realtime.js
@@ -0,0 +1,42 @@
module.exports = function (ranaly) {
var db = ranaly.redisClient;

var Realtime = function (bucket) {
this.bucket = bucket;
this.key = ranaly.prefix + 'REALTIME' + ':' + this.bucket;
};

Realtime.prototype.incr = function (increment, callback) {
if (typeof increment === 'function') {
callback = increment;
increment = void 0;
}
if (typeof increment !== 'number') {
increment = 1;
}

db.incrby(this.key, increment, function (err, result) {
if (!err) {
db.publish(this.key, result);
}
if (typeof callback === 'function') {
callback(err, result);
}
});
};

Realtime.prototype.get = function (callback) {
db.get(this.key, function (err, result) {
callback(err, parseInt(result, 10) || 0);
});
};

Realtime.prototype.set = function (value, callback) {
value = parseInt(value, 10) || 0;
db.set(this.key, value, callback);
console.log('Publish To: ' + this.key);
db.publish(this.key, value);
};

return Realtime;
};

0 comments on commit 56e49f8

Please sign in to comment.