Permalink
Browse files

Initial commit.

  • Loading branch information...
0 parents commit 56e49f8c9f7ccf2b080f9769a9c910d08278268e @luin committed Feb 11, 2013
Showing with 345 additions and 0 deletions.
  1. +2 −0 .gitignore
  2. +10 −0 Makefile
  3. +18 −0 index.js
  4. +23 −0 package.json
  5. +91 −0 test/index.js
  6. +114 −0 type/amount.js
  7. +45 −0 type/data_list.js
  8. +42 −0 type/realtime.js
@@ -0,0 +1,2 @@
+.DS_Store
+node_modules
@@ -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
+
@@ -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)
+ };
+};
+
@@ -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": "*"
+ }
+}
@@ -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);
+ });
+ });
+ });
+
+ });
+});
@@ -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;
+};
+
@@ -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;
+};
@@ -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.