Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

cache-helpers

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cache-helpers - npm Package Compare versions

Comparing version 1.3.0 to 1.4.0

.jshintrc

220

index.js

@@ -0,95 +1,157 @@

"use strict";
exports.once = function(func) {
var cache = undefined,
callbacks = null
var f, handler;
return function(callback) {
if(cache !== undefined)
return callback(null, cache)
handler = function(callback) {
var list;
if(callbacks) {
callbacks.push(callback)
return
}
list = [callback];
callbacks = [callback]
f = function(callback) {
list.push(callback);
};
return func(function(err, data) {
if(!err)
cache = data
func(function(err, result) {
var i;
while(callbacks.length)
callbacks.pop()(err, data)
f = err?
handler:
function(callback) {
process.nextTick(function() {
callback(err, result);
});
};
callbacks = null
})
}
}
for(i = 0; i < list.length; i++) {
list[i](err, result);
}
});
};
/* FIXME: why have an inProgress field? just set callbacks to null initially
* have it be an array only when we're in progress... */
f = handler;
return function(callback) {
f(callback);
};
};
exports.timeBasedWithGrace = function(func, soft, hard) {
var cache = undefined,
softLimit = 0,
hardLimit = 0,
inProgress = false,
callbacks = []
var f, handler;
return function(now, callback) {
/* If we're before the hardlimit, just call the callback immediately with
* cached data. Otherwise, if we're after it, we'll have to defer the
* callback until later on. */
if(now < hardLimit)
callback(null, cache)
/* "Hard" handler. */
handler = function(time, callback) {
var list;
else
callbacks.push(callback)
list = [callback];
/* If there's nothing more to do (because we're before the soft limit or
* because somebody else is already doing it), check out. */
if(now < softLimit || inProgress)
return
f = function(time, callback) {
list.push(callback);
};
/* Okay, so no we have to update the cache. Mark that we're doing something
* so that nobody else tries to. */
inProgress = true
func(function(err, result) {
var hard_time, i, sandler, soft_time;
/* Call the backing function. */
return func(function(err, data) {
/* If nothing went wrong, update the cache and timeouts. */
if(!err) {
cache = data
softLimit = now + soft
hardLimit = now + hard
if(err) {
f = handler;
}
/* Call each of the callbacks that we buffered up. (We just pass `err` to
* them because if there was no error, it's just going to be null anyway.
* Vice-versa applies as well.) */
while(callbacks.length)
callbacks.pop()(err, data)
else {
soft_time = time + soft;
hard_time = time + hard;
/* Finally, the last thing we do is mark that we're no longer in
* progress, since we just finished. */
inProgress = false
})
sandler = function(time, callback) {
var list;
if(time >= hard_time) {
handler(time, callback);
}
else {
process.nextTick(function() {
callback(err, result);
});
if(time >= soft_time) {
list = null;
f = function(time, callback) {
if(time >= hard_time) {
if(!list) {
list = [];
}
list.push(callback);
}
else {
process.nextTick(function() {
callback(err, result);
});
}
};
func(function(new_err, new_result) {
var i;
if(!new_err) {
err = new_err;
result = new_result;
soft_time = time + soft;
hard_time = time + hard;
}
f = sandler;
if(list) {
for(i = 0; i < list.length; i++) {
list[i](err, result);
}
}
});
}
}
};
f = sandler;
}
for(i = 0; i < list.length; i++) {
list[i](err, result);
}
});
};
f = handler;
return function(time, callback) {
f(time, callback);
};
};
exports.sizeBasedKeyValue = function(func, size) {
if(process.env["NODE_ENV"] !== "test") {
console.warn(
"cacheHelpers.sizeBasedKeyValue is DEPRECATED and will be removed"
);
}
}
exports.sizeBasedKeyValue = function(func, size) {
var cache = [],
callbacks = {}
callbacks = {};
size += size
size += size;
return function(key, callback) {
/* Look up in the cache. */
var i
var i;
for(i = 0; i !== cache.length; i += 2)
for(i = 0; i !== cache.length; i += 2) {
if(cache[i] === key) {
if(i !== 0)
Array.prototype.unshift.apply(cache, cache.splice(i, 2))
if(i !== 0) {
Array.prototype.unshift.apply(cache, cache.splice(i, 2));
}
return callback(null, cache[1])
return callback(null, cache[1]);
}
}

@@ -99,7 +161,7 @@ /* Somebody else is already polling the backend. Get notified when they're

if(callbacks[key]) {
callbacks[key].push(callback)
return
callbacks[key].push(callback);
return;
}
callbacks[key] = [callback]
callbacks[key] = [callback];

@@ -110,15 +172,17 @@ /* Call the backing store. */

if(!err) {
if(cache.length === size)
cache.length -= 2
if(cache.length === size) {
cache.length -= 2;
}
cache.unshift(key, value)
cache.unshift(key, value);
}
/* Notify all the saved callbacks, and then clean up. */
while(callbacks[key].length)
callbacks[key].pop()(err, value)
while(callbacks[key].length) {
callbacks[key].pop()(err, value);
}
delete callbacks[key]
})
}
}
delete callbacks[key];
});
};
};
{
"name": "cache-helpers",
"version": "1.3.0",
"version": "1.4.0",
"description": "caching convenience functions",

@@ -19,5 +19,8 @@ "keywords": [

"devDependencies": {
"mocha": "1.6.x",
"chai": "1.3.x"
"mocha": "*",
"jshint": "*"
},
"scripts": {
"test": "./node_modules/.bin/jshint *.js && NODE_ENV=test ./node_modules/.bin/mocha test"
}
}

@@ -54,1 +54,10 @@ cache-helpers

concrete use case. Checking out the tests may help.
License
-------
To the extend possible by law, The Dark Sky Company, LLC has [waived all
copyright and related or neighboring rights][cc0] to this library.
[cc0]: http://creativecommons.org/publicdomain/zero/1.0/

@@ -1,128 +0,252 @@

var assert = require("chai").assert,
cache = require("./")
"use strict";
var assert, cache;
assert = require("assert");
cache = require("./");
describe("cache", function() {
describe("time-based", function() {
var n
var inc, n;
function inc(callback) {
return callback(null, n++)
}
inc = function(callback) {
process.nextTick(function() {
callback(null, n++);
});
};
beforeEach(function() {
n = 0
})
beforeEach(function() {
n = 0;
});
describe("once", function() {
it("should only call the backing cache function once", function() {
var cinc = cache.once(inc)
describe("once", function() {
it("should only call the backing cache function once", function(done) {
var cinc = cache.once(inc);
cinc(function(err, n) {
assert.ifError(err);
assert.equal(n, 0);
cinc(function(err, n) {
assert.equal(n, 0)
})
assert.ifError(err);
assert.equal(n, 0);
cinc(function(err, n) {
assert.ifError(err);
assert.equal(n, 0);
done(null);
});
});
});
});
cinc(function(err, n) {
assert.equal(n, 0)
})
it("should call the backing cache function once even if simultaneous " +
"calls are made", function(done) {
var cinc = cache.once(inc),
m = 0;
cinc(function(err, n) {
assert.equal(n, 0)
})
})
cinc(function(err, n) {
assert.ifError(err);
assert.equal(n, 0);
if(++m === 3) {
done(null);
}
});
/* FIXME: Ensure that calling the function a bajillion times causes each
* callback to get called. */
})
cinc(function(err, n) {
assert.ifError(err);
assert.equal(n, 0);
if(++m === 3) {
done(null);
}
});
describe("timeBasedWithGrace", function() {
it("should only update the cache as appropriate", function() {
var cinc = cache.timeBasedWithGrace(inc, 100, 1000)
cinc(function(err, n) {
assert.ifError(err);
assert.equal(n, 0);
if(++m === 3) {
done(null);
}
});
});
});
/* First datapoint. */
cinc(0, function(err, n) {
assert.deepEqual(n, 0)
})
describe("timeBasedWithGrace", function() {
it("should only update the cache as appropriate", function(done) {
var cinc = cache.timeBasedWithGrace(inc, 100, 1000);
/* First datapoint. */
cinc(0, function(err, n) {
assert.ifError(err);
assert.deepEqual(n, 0);
/* Read cached. */
cinc(50, function(err, n) {
assert.deepEqual(n, 0)
})
assert.ifError(err);
assert.deepEqual(n, 0);
/* Soft timeout: return cached but update in the background. */
/* Soft timeout: return cached but update in the background. */
cinc(200, function(err, n) {
assert.ifError(err);
assert.deepEqual(n, 0);
/* Read cached. */
cinc(210, function(err, n) {
assert.ifError(err);
assert.deepEqual(n, 1);
/* Hard timeout: update n before returning. */
cinc(2500, function(err, n) {
assert.ifError(err);
assert.deepEqual(n, 2);
done(null);
});
});
});
});
});
});
it("should only call the callback once if called multiple times " +
"simultaneously", function(done) {
var cinc, m;
cinc = cache.timeBasedWithGrace(inc, 100, 1000);
m = 0;
cinc(0, function(err, n) {
assert.ifError(err);
assert.strictEqual(n, 0);
if(++m === 3) {
done(null);
}
});
cinc(0, function(err, n) {
assert.ifError(err);
assert.strictEqual(n, 0);
if(++m === 3) {
done(null);
}
});
cinc(0, function(err, n) {
assert.ifError(err);
assert.strictEqual(n, 0);
if(++m === 3) {
done(null);
}
});
});
it("should only call the callback once if called multiple times " +
"simultaneously in soft timeout state", function(done) {
var cinc;
cinc = cache.timeBasedWithGrace(inc, 100, 1000);
cinc(0, function(err, n) {
var m;
assert.ifError(err);
assert.strictEqual(n, 0);
m = 0;
cinc(200, function(err, n) {
assert.deepEqual(n, 0)
})
assert.ifError(err);
assert.strictEqual(n, 0);
if(++m === 3) {
done(null);
}
});
/* Read cached. */
cinc(250, function(err, n) {
assert.deepEqual(n, 1)
})
/* We assume that by the time this gets executed, the background update
* succeeded... */
cinc(200, function(err, n) {
assert.ifError(err);
assert.strictEqual(n, 1);
if(++m === 3) {
done(null);
}
});
/* Hard timeout: update n before returning. */
cinc(2500, function(err, n) {
assert.deepEqual(n, 2)
})
})
cinc(200, function(err, n) {
assert.ifError(err);
assert.strictEqual(n, 1);
if(++m === 3) {
done(null);
}
});
});
});
/* FIXME: Ensure that calling the function a bajillion times causes each
* callback to get called. */
})
})
/* FIXME: Ensure that calling the function a bajillion times causes each
* callback to get called. */
});
describe("key-value", function() {
var n
describe("sizeBasedKeyValue", function() {
var inc, n;
function inc(key, callback) {
return callback(null, key ^ n++)
}
inc = function(key, callback) {
process.nextTick(function() {
callback(null, key ^ n++);
});
};
beforeEach(function() {
n = 0
})
n = 0;
});
describe("sizeBasedKeyValue", function() {
it("should cache for each key, until you fill the space", function() {
var f = cache.sizeBasedKeyValue(inc, 2)
it("should cache for each key, until you fill the space", function(done) {
var f = cache.sizeBasedKeyValue(inc, 2);
f(20, function(err, value) {
assert.equal(value, 20)
})
f(20, function(err, value) {
assert.ifError(err);
assert.equal(value, 20);
f(20, function(err, value) {
assert.equal(value, 20)
})
assert.ifError(err);
assert.equal(value, 20);
f(40, function(err, value) {
assert.equal(value, 41)
})
f(40, function(err, value) {
assert.ifError(err);
assert.equal(value, 41);
f(20, function(err, value) {
assert.equal(value, 20)
})
f(20, function(err, value) {
assert.ifError(err);
assert.equal(value, 20);
f(40, function(err, value) {
assert.equal(value, 41)
})
f(40, function(err, value) {
assert.ifError(err);
assert.equal(value, 41);
f(30, function(err, value) {
assert.equal(value, 28)
})
f(30, function(err, value) {
assert.ifError(err);
assert.equal(value, 28);
f(40, function(err, value) {
assert.equal(value, 41)
})
f(40, function(err, value) {
assert.ifError(err);
assert.equal(value, 41);
f(20, function(err, value) {
assert.equal(value, 23)
})
f(20, function(err, value) {
assert.ifError(err);
assert.equal(value, 23);
f(40, function(err, value) {
assert.equal(value, 41)
})
})
f(40, function(err, value) {
assert.ifError(err);
assert.equal(value, 41);
/* FIXME: Ensure that calling the function a bajillion times causes each
* callback to get called. */
})
})
})
done(null);
});
});
});
});
});
});
});
});
});
});
/* FIXME: Ensure that calling the function a bajillion times causes each
* callback to get called. */
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc