New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

goldfish

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

goldfish - npm Package Compare versions

Comparing version 0.0.8 to 0.1.0

Gruntfile.coffee

236

index.js

@@ -1,235 +0,1 @@

/*!
* goldfish
* Copyright(c) 2012 Ian Hansen <ian@supershabam.com>
* MIT Licensed
*/
"use strict";
var util = require('util')
, events = require('events')
, NULL
, EVICT_REASONS
;
// @TODO get rid of NULL, no longer needed
// @TODO allow keys to be more than just strings. Objects 'n' such
EVICT_REASONS = {
CAPACITY: 'capacity',
EXPIRED: 'expired',
MANUAL: 'manual'
};
/**
* options:
* + populate - function to run when getting a value that doesn't exist in the cache
* + expires - time in miliseconds that a key can stay in the cache (null for no expiration)
* + capacity - maximum number of items in the cache, older items will be evicted to make space (null for no max)
* + cleanup - time in miliseconds between running the cleanup function to expire old items
*/
function Goldfish(options) {
options = options || {};
this._populate = options.populate || null;
this._expires = options.expires || null;
this._capacity = options.capacity || null;
this._cleanupPeriod = options.cleanup || 60000;
this._cache = {};
this._newest = NULL;
this._oldest = NULL;
this._size = 0;
this._cleanupInterval = null;
this._fetching = {};
// magical thisness
this._cleanup = this._cleanup.bind(this);
}
util.inherits(Goldfish, events.EventEmitter);
/**
* key - hashable value to fetch from cache or run populate function with
* options:
* + populate - override the populate function provided
* + refresh - boolean whether or not to touch the key value so that it doesn't expire or get evicted for space (default: true)
*/
Goldfish.prototype.get = function(key, cb, options) {
options = options || {};
var populate = options.populate || this._populate
, refresh = options.refresh ? true : false
, expiresTime = this._expires ? this._expires + (new Date().getTime()) : -Infinity
;
// before reading from local cache, expire this key if it's too old
if (this._cache.hasOwnProperty(key) && this._cache[key].refreshed < expiresTime) {
this._evict(key, EVICT_REASONS.expired);
}
// comence cache retreival
if (this._cache.hasOwnProperty(key)) {
if (refresh) this._refresh(key);
// do callback on next cpu event (allow caller to operate truely asynchronously)
process.nextTick(cb.bind({}, null, this._cache[key].value));
} else {
this._fetch(populate, key, cb);
}
};
/**
* force the eviction of a key
* key - hashable value to evict from local cache
*/
Goldfish.prototype.evict = function(key, silent) {
if (this._cache.hasOwnProperty(key)) {
this._evict(key, EVICT_REASONS.MANUAL, silent);
}
};
Goldfish.prototype._fetch = function(populate, key, cb) {
var self = this;
if (this._fetching.hasOwnProperty(key)) {
this._fetching[key].push(cb);
} else {
this._fetching[key] = [cb];
populate(key, function handlePopulateResponse(err, value) {
var i;
// add to cache if we got a value
if (!err) self._insert(key, value);
// notify everybody waiting on this result (error or value)
for(i=0; i < self._fetching[key].length; ++i) {
self._fetching[key][i](err, value);
}
// clear fetchers
delete self._fetching[key];
});
}
};
Goldfish.prototype._insert = function(key, value) {
var entry
, capacity = this._capacity ? this._capacity : Infinity
;
entry = {
key: key,
value: value,
refreshed: new Date().getTime()
};
this._pushEntry(entry);
this._cache[key] = entry;
++this._size;
// evict oldest if we are now over capacity
if (this._size > capacity) {
this._evict(this._oldest.key, EVICT_REASONS.CAPACITY);
}
// start the cleanup thread if not already running
// @TODO only run if evict time is set
if(!this._cleanupInterval) {
this._cleanupInterval = setInterval(this._cleanup, this._cleanupPeriod);
}
};
Goldfish.prototype._evict = function(key, reason, silent) {
var entry = this._cache[key]
, silent = silent ? true : false
, env
;
if(!entry) return;
this._pullEntry(entry);
delete this._cache[key];
--this._size;
env = {
reason: reason,
key: key,
value: entry.value,
refreshed: entry.refreshed
};
// let people know about this eviction
if(!silent) {
this.emit('evict', env);
this.emit('evict:' + env.reason, env);
}
// stop cleanup thread if we are now empty
if(this._size === 0) {
clearInterval(this._cleanupInterval);
this._cleanupInterval = null;
}
};
Goldfish.prototype._pullEntry = function(entry) {
// remove from middle
if (entry.older !== NULL && entry.newer !== NULL) {
entry.older.newer = entry.newer;
entry.newer.older = entry.older;
}
// remove single entry
if (this._oldest === entry && this._newest === entry) {
this._oldest = NULL;
this._newest = NULL;
}
// remove oldest in a series
if (this._oldest === entry) {
this._oldest = entry.newer;
entry.newer.older = NULL;
}
// remove newest in a series
if (this._newest === entry) {
this._newest = entry.older;
entry.older.newer = NULL;
}
};
Goldfish.prototype._pushEntry = function(entry) {
// first entry if there is no newest
if (this._newest === NULL) {
this._newest = entry;
this._oldest = entry;
entry.newer = NULL;
entry.older = NULL;
}
// adding to the front
else {
this._newest.newer = entry;
entry.older = this._newest;
entry.newer = NULL;
this._newest = entry;
}
};
Goldfish.prototype._refresh = function(key) {
var entry = this._cache[key];
this._pullEntry(entry);
this._pushEntry(entry);
entry.refreshed = new Date().getTime();
};
// starting from the oldest, remove while timestamp is expired
Goldfish.prototype._cleanup = function() {
var maxElapsed = this._expires ? this._expires : Infinity
, now = new Date().getTime()
;
while (this._oldest && (now - this._oldest.refreshed) > maxElapsed) {
this._evict(this._oldest.key, EVICT_REASONS.EXPIRED);
}
};
module.exports = Goldfish;
module.exports = require('./lib/goldfish.js');

@@ -5,3 +5,3 @@ {

"description": "Evented in-memory cache",
"version": "0.0.8",
"version": "0.1.0",
"repository": {

@@ -12,10 +12,20 @@ "type": "git",

"dependencies": {
"jsosort": "0.0.0",
"moment": "~2.0.0"
},
"devDependencies": {
"mocha": "~1.4.0"
"mocha": "~1.8.2",
"grunt": "~0.4.0",
"grunt-contrib-coffee": "~0.6.0",
"grunt-contrib-clean": "~0.4.0",
"chai": "~1.5.0",
"sinon-chai": "~2.3.1",
"sinon": "~1.6.0",
"coffee-script": "~1.6.1",
"async": "~0.2.6"
},
"optionalDependencies": {},
"scripts": {
"test": "./node_modules/.bin/mocha"
"test": "grunt test"
}
}

@@ -1,8 +0,33 @@

goldfish
Goldfish
========
[![Build Status](https://secure.travis-ci.org/SuperShabam/goldfish.png?branch=master)](http://travis-ci.org/SuperShabam/goldfish)
Goldfish - the forgetful in-memory cache
Evented JavaScript in-memory cache
```javascript
// _, _,
// .' ( .-' /
// _/..._'. .' /
// .-'` ` '-./ _.'
// ( o) ;= <_
// '-.,\\__ __.-;`\ '.
// \) |`\ \) '. \
// \_/ jgs '-._\
// `
```
[![Build Status](https://secure.travis-ci.org/supershabam/goldfish.png?branch=master)](http://travis-ci.org/supershabam/goldfish)
[![endorse](http://api.coderwall.com/supershabam/endorsecount.png)](http://coderwall.com/supershabam)
Options
=======
```javascript
Goldfish({
populate: // fn(arg1, arg2, ..., cb)
expires: // (optional) Integer - miliseconds before a cache item is expired (default = Infinity)
remind: // (optional) Boolean - refresh expire time on fetch (default = false)
capacity: // (optional) Integer - max number of items to have in the cache (default = Infinity)
});
```
Example

@@ -35,14 +60,8 @@ =======

// listen for any evictions
cache.on('evict', function(evict) {
console.log(evict.key); // the key of the item being evicted
console.log(evict.value); // the value of key that is being removed from the cache
console.log(evict.reason); // the reason the eviction occured (manual, capacity, expired)
cache.on('evict', function(entry) {
console.log(entry.args); // Array - the args passed to populate resulting in this entry
console.log(evict.result); // Array - the results from populate
});
// can also listen for specific types of evictions
cache.on('evict:manual', function(evict) {
console.log(evict.key);
});
cache.evict('test');
// clear the cache
cache.clear();
```

@@ -54,4 +73,13 @@

**get#hit** O(1)
**get#miss** O(1) + O(populate)
**evict** O(1)
**expire** O(1)
**get#miss** O(1) + Populate()
**clear** O(n)
Changelog
=========
0.1.0
-----
Complete disregard for the previous api. Don't blindly update.
Smaller, simpler api.

Sorry, the diff of this file is not supported yet

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