Skip to content
Browse files

0.0.1

  • Loading branch information...
1 parent 960c29e commit 67934b52b73a94e07e8cd8beb71dc93bb0e00e50 @thefosk committed
Showing with 230 additions and 0 deletions.
  1. +2 −0 .gitignore
  2. +104 −0 lib/cache.js
  3. +26 −0 package.json
  4. +5 −0 test.js
  5. +93 −0 test/memcached-test.js
View
2 .gitignore
@@ -0,0 +1,2 @@
+node_modules
+.DS_Store
View
104 lib/cache.js
@@ -0,0 +1,104 @@
+var data = {};
+
+exports.get = function(id, property) {
+ property = typeof property !== 'undefined' ? property : "this";
+
+ var element = data[id];
+ if (!element || !element[property]) return null;
+
+ if (element[property].expiration > 0 && getNewReferenceDate(element[property].referenceDate, element[property].expiration) != element[property].referenceDate) {
+ // Expired
+ return (element[property].counter) ? 0 : null;
+ } else {
+ return element[property].value
+ }
+}
+
+exports.populate = function(d) {
+ data = d;
+}
+
+exports.getAll = function() {
+ return data;
+}
+
+exports.increment = function(id, property, amount, expiration) {
+ exports.set(id, property, amount, expiration, true);
+}
+
+exports.set = function(id, property, value, expiration, counter) {
+ counter = typeof counter !== 'undefined' ? counter : false;
+
+ var element = data[id];
+ if (element && element[property]) {
+ if (expiration) {
+ // update expiration date if set
+ if (expiration < 0) expiration = 0;
+ element[property].expiration = expiration;
+ }
+
+ // Item exists
+ if (element[property].expiration > 0) {
+ var newReferenceDate = getNewReferenceDate(element[property].referenceDate, element[property].expiration);
+ if (element[property].referenceDate != newReferenceDate) {
+ // Expired
+ element[property].value = value;
+ element[property].referenceDate = newReferenceDate;
+ return;
+ }
+ }
+
+ // Not expired
+ if (counter) {
+ element[property].value = element[property].value + parseInt(value);
+ } else {
+ element[property].value = value;
+ }
+ } else {
+ createItem(id, property, {
+ value: (counter) ? parseInt(value) : value,
+ counter: counter,
+ expiration: (expiration) ? ((expiration < 0) ? 0 : expiration) : 0, // Do not allow negative expiration dates
+ referenceDate:new Date().getTime()
+ });
+ }
+}
+
+function getNewReferenceDate(oldReferenceDate, expiration) {
+ var now = new Date().getTime();
+
+ // NEW_REF_DATE = OLD_REF_DATE + (FLOOR((NOW - OLD_REF_DATE) / EXP) * EXP)
+ // If new reference date != referenceDate, is expired.
+
+ // Reference date is the date taken as reference when calculating the expiration of an item.
+
+ var newReferenceDate = oldReferenceDate + (Math.floor((now - oldReferenceDate) / expiration) * expiration);
+ return newReferenceDate;
+}
+
+exports.delete = function(id, property) {
+ if (!property) {
+ delete data[id];
+ } else {
+ var element = data[id];
+ delete element[property];
+ var keys = Object.keys(element);
+ if (keys.length == 1 && element[keys[0]] == null) {
+ // If this was the only key in the item, remove the whole item from memory
+ delete data[id];
+ }
+ }
+}
+
+function createItem(id, property, options) {
+ var element = data[id];
+ if (!element) element = {};
+ element[property] = {
+ value: options.value,
+ counter: options.counter,
+ expiration: (options.expiration) ? parseInt(options.expiration) : 0,
+ referenceDate:new Date().getTime()
+ }
+
+ data[id] = element;
+}
View
26 package.json
@@ -0,0 +1,26 @@
+{
+ "name": "node-mem-cache",
+ "version": "0.0.1",
+ "description": "An in-memory cache module.",
+ "author": "Mashape <support@mashape.com>",
+ "homepage":"http://www.mashape.com",
+ "dependencies": {
+ },
+ "private": true,
+ "engines": {
+ "node": ">= 0.8.11"
+ },
+ "devDependencies": {
+ "vows": "0.6.3"
+ },
+ "bin" : { "zencounter" : "bin/main.js" },
+ "license" : "GNU AFFERO GENERAL PUBLIC LICENSE",
+ "repository" : {
+ "type" : "git",
+ "url" : "https://github.com/thefosk/node-mem-cache"
+ },
+ "bugs" : {
+ "url" : "https://github.com/thefosk/node-mem-cache/issues",
+ "email" : "support@mashape.com"
+ }
+}
View
5 test.js
@@ -0,0 +1,5 @@
+cache = require('./lib/cache');
+
+cache.set("item", "this", "ciao");
+
+console.log(cache.get("item","this"));
View
93 test/memcached-test.js
@@ -0,0 +1,93 @@
+var vows = require('vows'),
+ assert = require('assert'),
+ cache = require('./../lib/cache');
+
+function sleep(ms) {
+ var now = new Date().getTime();
+ while(new Date().getTime() - now < ms) {
+ // Do nothing
+ }
+}
+
+vows.describe('cache test').addBatch({
+ 'Items' : {
+ 'set an item': {
+ operation: function() {cache.set("item", "this", "simple value")},
+ 'get the item': function () {
+ assert.equal ("simple value", cache.get("item", "this"));
+ },
+ 'get the wrong item':function() {
+ assert.equal (null, cache.get("asd", "this"));
+ },
+ 'get the wrong property':function() {
+ assert.equal (null, cache.get("item", "asd"));
+ }
+ },
+ 'set an item': {
+ operation: function() {cache.set("item", "this", "simple value")},
+ 'get the item': function () {
+ assert.equal ("simple value", cache.get("item", "this"));
+ },
+ 'reset item':function() {
+ cache.set("item", "this", "simple updated value");
+ assert.equal ("simple updated value", cache.get("item", "this"));
+ },
+ 'set another property':function() {
+ cache.set("item", "nickname", "thefosk");
+ assert.equal ("simple updated value", cache.get("item", "this"));
+ assert.equal ("thefosk", cache.get("item", "nickname"));
+ assert.isFalse(cache.getAll().item.nickname.counter);
+ assert.equal(0, cache.getAll().item.nickname.expiration);
+ }
+ }
+ },
+ 'Counters' : {
+ 'set a counter': {
+ operation: function() {cache.increment("item", "age", 10)},
+ 'get the item': function () {
+ assert.equal (10, cache.get("item", "age"));
+ assert.isTrue(cache.getAll().item.age.counter);
+ }
+ },
+ 'update a counter': {
+ operation: function() {cache.increment("item", "age", 4)},
+ 'get the item': function () {
+ assert.equal (14, cache.get("item", "age"));
+ assert.isTrue(cache.getAll().item.age.counter);
+ assert.equal(0, cache.getAll().item.nickname.expiration);
+ }
+ }
+ },
+ 'Expiration' : {
+ 'set an item with expiration': {
+ operation: function() {cache.set("item", "name", "Marco", 2000)},
+ 'get the item': function () {
+ assert.equal ("Marco", cache.get("item", "name"));
+ assert.isFalse(cache.getAll().item.name.counter);
+ var referenceDate = cache.getAll().item.name.referenceDate;
+ assert.equal(2000, cache.getAll().item.name.expiration);
+
+ sleep(2000);
+
+ assert.equal(null, cache.get("item", "name"));
+ assert.equal(cache.getAll().item.name.referenceDate, referenceDate);
+
+ cache.set("item", "name", "Luke");
+ assert.equal ("Luke", cache.get("item", "name"));
+ assert.isFalse(cache.getAll().item.name.counter);
+ assert.equal(2000, cache.getAll().item.name.expiration);
+ assert.notEqual(cache.getAll().item.name.referenceDate, referenceDate);
+ assert.equal(cache.getAll().item.name.referenceDate, referenceDate + 2000);
+
+ sleep(3000);
+
+ cache.set("item", "name", "Pippo");
+ assert.equal ("Pippo", cache.get("item", "name"));
+ assert.isFalse(cache.getAll().item.name.counter);
+ assert.equal(2000, cache.getAll().item.name.expiration);
+ assert.notEqual(cache.getAll().item.name.referenceDate, referenceDate);
+ assert.equal(cache.getAll().item.name.referenceDate, referenceDate + 4000);
+ }
+ }
+ }
+}).export(module);

0 comments on commit 67934b5

Please sign in to comment.
Something went wrong with that request. Please try again.