API Docs for: 1.0.0
Show:

File: src/gallery-expiration-cache/js/ExpirationCache.js

/**
 * @module gallery-expiration-cache
 */

/**
 * <p>Cache which drops items based on a user-defined expiration criterion,
 * e.g., age.  By default, expired items are only removed when they are
 * requested.  If you want to "stop the world" and clean out the cache,
 * call clean().</p>
 * 
 * @main gallery-expiration-cache
 * @class ExpirationCache
 * @constructor
 * @param config {Object}
 * @param [config.store] {Object} Data store which implements get,put,remove,clear,keys.  If not specified, a new instance of `Y.InstanceManager` is created.
 * @param [config.meta] {Function} Attaches meta data to an item when it is added to the cache.  It receives the value as an argument.  If not specified, the default is to timestamp the item.
 * @param config.expire {Function} Returns true if the item has expired.  It receives the meta data and the value as arguments.  If a number is specified, it is assumed to be a duration in milliseconds.
 * @param [config.stats] {Boolean} Pass true if you want to collect basic statistics.  Pass a function if you want to control what information is stored for each key.  The function receives the key, the value, and the stat object.
 */
function ExpirationCache(config)
{
	this._store  = config.store || new Y.InstanceManager();
	this._meta   = config.meta  || timestamp;
	this._expire = Y.Lang.isNumber(config.expire) ? Y.rbind(expire, null, config.expire) : config.expire;
	this._stats  = config.stats ? initStats() : null;

	if (Y.Lang.isFunction(config.stats))
	{
		this._stats_key_meta = config.stats;
	}
}

function timestamp()
{
	return new Date().getTime();
}

function expire(timestamp, value, delta)
{
	var elapsed = new Date().getTime() - timestamp;
	return (elapsed > delta);
}

function initStats()
{
	return { gets: 0, keys: {} };
}

function initKeyStats(keys, key)
{
	if (!keys[key])
	{
		keys[key] = { puts: 0, gets: 0 };
	}
}

ExpirationCache.prototype =
{
	/**
	 * Retrieve a value.
	 * 
	 * @method get
	 * @param key {String} the key of the object to retrieve
	 * @return {Mixed} the stored object, or undefined if the slot is empty
	 */
	get: function(
		/* string */	key)
	{
		var obj = this._store.get(key);
		if (obj && this._expire(obj.meta, obj.data))
		{
			this._store.remove(key);
		}
		else if (obj)
		{
			if (this._stats)
			{
				this._stats.gets++;

				initKeyStats(this._stats.keys, key);
				this._stats.keys[key].gets++;
			}

			return obj.data;
		}
	},

	/**
	 * Store a value.
	 * 
	 * @method put
	 * @param key {String} the key of the value
	 * @param value {Object} the value to store
	 * @return {boolean} false if the key has already been used
	 */
	put: function(
		/* string */	key,
		/* obj/fn */	value)
	{
		var obj =
		{
			data: value,
			meta: this._meta(value)
		};

		if (!this._store.put(key, obj))
		{
			return false;
		}

		if (this._stats)
		{
			initKeyStats(this._stats.keys, key);
			this._stats.keys[key].puts++;

			if (this._stats_key_meta)
			{
				this._stats_key_meta(key, value, this._stats.keys[key]);
			}
		}
		return true;
	},

	/**
	 * Store a value.
	 * 
	 * @method replace
	 * @param key {String} the key of the value
	 * @param value {Object} the value to store
	 * @return {Mixed} the original value that was in the slot, or undefined if the slot is empty
	 */
	replace: function(
		/* string */	key,
		/* obj/fn */	value)
	{
		var orig = this.remove(key);
		this.put(key, value);
		return orig;
	},

	/**
	 * Remove an value.
	 * 
	 * @method remove
	 * @param key {String} the key of the value
	 * @return {mixed} the value that was removed, or undefined if the slot was empty
	 */
	remove: function(
		/* string */	key)
	{
		var orig = this._store.remove(key);
		if (orig)
		{
			return orig.data;
		}
	},

	/**
	 * Remove all values.
	 * 
	 * @method clear
	 */
	clear: function()
	{
		this._store.clear();
	},

	/**
	 * Remove all expired values.
	 * 
	 * @method clean
	 */
	clean: function()
	{
		Y.each(this._store.keys(), this.get, this);
	},

	/**
	 * This resets all the values.
	 *
	 * @method dumpStats
	 * @return {Object} the current stats
	 */
	dumpStats: function()
	{
		var stats   = this._stats;
		this._stats = initStats();
		return stats;
	}
};

Y.ExpirationCache = ExpirationCache;