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

zcache

Package Overview
Dependencies
Maintainers
8
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

zcache - npm Package Compare versions

Comparing version 0.3.6 to 0.4.0-alpha

.jshintignore

2

index.js

@@ -14,3 +14,3 @@ module.exports = {

PartialResultError: require('./lib/PartialResultError'),
MultiWriteCacheGroup: require('./lib/MultiWriteCacheGroup')
CachePair: require('./lib/CachePair')
}

@@ -143,2 +143,7 @@ // Copyright 2014 The Obvious Corporation.

/** @override */
CacheCluster.prototype.getUrisByKey = function (key) {
return [this._hashRing.get(key)]
}
/** @override */
CacheCluster.prototype.get = function (key) {

@@ -276,5 +281,5 @@ var cacheInstance = this._servers[this._hashRing.get(key)]

*
* @param {Promise} origPromise The promise to wrap.
* @param {Q.Promise} origPromise The promise to wrap.
* @param {string} opName The name of the cache operation, e.g., 'get', 'set', etc.
* @return {Promise} A promise that behaves the same as the 'origPromise' with its latency
* @return {Q.Promise} A promise that behaves the same as the 'origPromise' with its latency
* measured.

@@ -343,3 +348,3 @@ */

* @param {Array.<string>} values The values that have been fetched
* @return {Promise.<Array.<string>>} The passed in "values", for easy chaining.
* @return {Q.Promise.<Array.<string>>} The passed in "values", for easy chaining.
*/

@@ -356,3 +361,3 @@ function setValues(valueMap, keys, values) {

*
* @param {Object.<string, string>} map The key-value map of fetched cache entries.
* @param {Object} errorMap The key-value map of fetched cache entries.
* @param {Array.<string>} keys The keys that have been fetched

@@ -369,2 +374,2 @@ * @param {Object} err The error object

module.exports = CacheCluster
module.exports = CacheCluster

@@ -10,10 +10,9 @@ // Copyright 2014 The Obvious Corporation.

var metrics = require('metrics')
var util = require('util')
var Q = require('kew')
/**
* Default timeout for cache request. Notice, not the timeout for connection.
* @const
* @type {number}
*/
* Default timeout for cache request. Notice, not the timeout for connection.
* @const
* @type {number}
*/
var DEFAULT_REQ_TIMEOUT_MS = 50

@@ -24,5 +23,6 @@

*
* @param {Object=} options Additional options for this connection.
* @param {{requestTimeoutMs: (number|undefined)}=} options Additional options for this connection.
* 'requestTimeoutMs' specifies the timeout of a Redis request.
* @constructor
* @extends {events.EventEmitter}
*/

@@ -72,3 +72,3 @@ function CacheInstance(options) {

* @param {Array.<string>} keys A list of keys
* @return {Promise.<Array.<string>>} The fetched values. For keys that do not exist,
* @return {Q.Promise.<Array.<string>>} The fetched values. For keys that do not exist,
* returns 'undefined's.

@@ -83,8 +83,9 @@ */

*
* @param {Array.<{key: string, value: string}} items Key-value pairs to set.
* @param {number=} maxAgeMs The living time of keys, in milliseconds.
* @return {Promise}
* @param {Array.<{key: string, value: string}>} items Key-value pairs to set.
* @param {number} maxAgeMs The living time of keys, in milliseconds.
* @param {boolean=} setWhenNotExist Only set the keys that do not exist yet.
* @return {Q.Promise}
*/
CacheInstance.prototype.mset = function (items, maxAgeMs) {
throw new Error("mget() must be implemented by any class extending CacheInstance")
CacheInstance.prototype.mset = function (items, maxAgeMs, setWhenNotExist) {
throw new Error("mset() must be implemented by any class extending CacheInstance")
}

@@ -96,3 +97,3 @@

* @param {string} key The key to get value of.
* @return {Promise.<string>} The fetched value. Returns 'undefined' if the doesn't exist.
* @return {Q.Promise.<string>} The fetched value. Returns 'undefined' if the doesn't exist.
*/

@@ -106,8 +107,9 @@ CacheInstance.prototype.get = function (key) {

*
* @param {string} key
* @param {string} value
* @param {number=} maxAgeMs The living time of this key, in milliseconds.
* @return {Promise}
* @param {string} key The key to set
* @param {string} val The value to set
* @param {number} maxAgeMs The living time of this key, in milliseconds.
* @param {boolean=} setWhenNotExist Only set the key when it doesn't exist.
* @return {Q.Promise}
*/
CacheInstance.prototype.set = function (key, val, maxAgeMs) {
CacheInstance.prototype.set = function (key, val, maxAgeMs, setWhenNotExist) {
throw new Error("set() must be implemented by any class extending CacheInstance")

@@ -120,3 +122,3 @@ }

* @param {string} key
* @param {Promise}
* @return {Q.Promise}
*/

@@ -128,2 +130,12 @@ CacheInstance.prototype.del = function (key) {

/**
* Get the uri of the cache server(s) that is in charge of the given key.
*
* @param {string} key
* @return {Array.<string>}
*/
CacheInstance.prototype.getUrisByKey = function (key) {
return ['UnknownUri']
}
/**
* Get the number of cache accesses.

@@ -148,4 +160,2 @@ *

* Reset the access count and hit count to get counts during time intervals.
*
* @return {number}
*/

@@ -161,3 +171,3 @@ CacheInstance.prototype.resetCount = function () {

* @param {string} key
* @param {Promise.<ServerInfo>} A promise that returns the server information. Returns
* @return {Q.Promise.<ServerInfo>} A promise that returns the server information. Returns
* null if the server info is not available.

@@ -172,7 +182,6 @@ */

*
* @param {Array.<Object>|Object} data The data fetched by get or mget.
* @return {Function} A function that updates the counts and returns the parameter
* that is passed into it. It is handy to chain to a promise.
*/
CacheInstance.prototype.updateCount = function() {
CacheInstance.prototype.getCountUpdater = function() {
var self = this

@@ -237,4 +246,5 @@ return function (data) {

/**
* Gets a map of cacheInstance uri and the requestCounts
* @return {Object}
* Gets a map of cacheInstance uri and the requestCounts.
*
* @return {Array.<Object>}
*/

@@ -241,0 +251,0 @@ CacheInstance.prototype.getPendingRequestsCount = function () {

@@ -9,5 +9,5 @@ // Copyright 2014 A Medium Corporation.

* Merges pending requests count for a list of cache instances to a list
* @param {Object} requestCounts map of cacheInstance uri and requests count
* @param {Array<Object>} cacheInstances
* @return {Array<Object>}
*
* @param {Array.<Object>} cacheInstances
* @return {Array.<Object>} A list of pending requests count objects
*/

@@ -14,0 +14,0 @@ function mergePendingRequestCounts(cacheInstances) {

@@ -7,2 +7,6 @@ var poolModule = require('generic-pool')

/**
* @constructor
* @extends {CacheInstance}
*/
function ConnectionPool(opts) {

@@ -120,3 +124,3 @@ CacheInstance.call(this)

* @param {Object} context the query context
* @return {Promise.<Array.<string>>} the cached response
* @return {Q.Promise.<Array.<string>>} the cached response
*/

@@ -142,3 +146,3 @@ function callMget(client, context) {

* @param {Object} context the query context
* @return {Promise.<string>} the cached response
* @return {Q.Promise.<string>} the cached response
*/

@@ -164,3 +168,3 @@ function callGet(client, context) {

* @param {Object} context the query context
* @return {Promise.<string>} the cached response
* @return {Q.Promise.<string>} the cached response
*/

@@ -186,3 +190,3 @@ function callSet(client, context) {

* @param {Object} context the query context
* @return {Promise.<string>} the cached response
* @return {Q.Promise.<string>} the cached response
*/

@@ -194,2 +198,2 @@ function callDel(client, context) {

module.exports = ConnectionPool
module.exports = ConnectionPool

@@ -5,2 +5,6 @@ var util = require('util')

/**
* @constructor
* @extends {CacheInstance}
*/
function ConnectionWrapper(cacheInstance, opts) {

@@ -40,3 +44,3 @@ CacheInstance.call(this)

this._state.shouldConnect = true
this._connectDelayed(0)
this._connectDelayed()
}

@@ -85,2 +89,2 @@

module.exports = ConnectionWrapper
module.exports = ConnectionWrapper

@@ -14,2 +14,5 @@ // Copyright 2014 The Obvious Corporation.

/** @typedef {{fine: !Function}} */
var Logger
/**

@@ -19,4 +22,5 @@ * @constructor

* @param {Logger} logger A logger for logging debug information.
* @param {string=} optUri Give an URI to this fake cache instance
*/
function FakeCache(logger) {
function FakeCache(logger, optUri) {
CacheInstance.call(this)

@@ -29,6 +33,7 @@

this._nextFailure = null
this._uri = optUri || 'FakeCache'
}
util.inherits(FakeCache, CacheInstance)
/** @inheritDoc */
/** @override */
FakeCache.prototype.mget = function (keys) {

@@ -47,3 +52,3 @@ if (this._failureCount > 0) return this._fakeFail('mget')

/** @inheritDoc */
/** @override */
FakeCache.prototype.get = function (key) {

@@ -63,3 +68,3 @@ if (this._failureCount > 0) return this._fakeFail('get')

/** @inheritDoc */
/** @override */
FakeCache.prototype.del = function (key) {

@@ -75,8 +80,7 @@ if (this._failureCount > 0) return this._fakeFail('del')

delete self._data[key]
return Q.resolve()
})
}
/** @inheritDoc */
FakeCache.prototype.set = function (key, value) {
/** @override */
FakeCache.prototype.set = function (key, value, maxAgeMs, setWhenNotExist) {
if (this._failureCount > 0) return this._fakeFail('set')

@@ -90,9 +94,8 @@ this._logger.fine('FakeCache - set', key, value)

self._requestCounts.set += 1
self._data[key] = value
return Q.resolve()
if (!setWhenNotExist || !(key in self._data)) self._data[key] = value
})
}
/** @inheritDoc */
FakeCache.prototype.mset = function (items) {
/** @override */
FakeCache.prototype.mset = function (items, maxAgeMs, setWhenNotExist) {
if (this._failureCount > 0) return this._fakeFail('mset')

@@ -105,10 +108,15 @@

self._requestCounts.mset += 1
self._requestCounts.msetItemCount.push(items.length)
for (var i = 0; i < items.length; i++) {
var item = items[i]
self._data[item.key] = item.value
if (!setWhenNotExist || !(item.key in self._data)) self._data[item.key] = item.value
}
return Q.resolve()
})
}
/** @override */
FakeCache.prototype.getUrisByKey = function (key) {
return [this._uri]
}
/**

@@ -204,2 +212,3 @@ * A sync version of the mget().

mget: 0,
mset: 0,
get: 0,

@@ -209,2 +218,3 @@ set: 0,

mgetItemCount: [],
msetItemCount: [],
hitCount: 0,

@@ -211,0 +221,0 @@ missCount: 0,

@@ -73,3 +73,3 @@ // Copyright 2013 The Obvious Corporation.

/** @inheritDoc */
/** @override */
InMemoryCache.prototype.isAvailable = function () {

@@ -79,3 +79,3 @@ return this._isAvailable

/** @inheritDoc */
/** @override */
InMemoryCache.prototype.connect = function () {

@@ -88,3 +88,3 @@ this._isAvailable = true

/** @inheritDoc */
/** @override */
InMemoryCache.prototype.disconnect = function () {

@@ -96,3 +96,3 @@ this._destroyReaper()

/** @inheritDoc */
/** @override */
InMemoryCache.prototype.destroy = function () {

@@ -106,3 +106,3 @@ this._destroyReaper()

/** @inheritDoc */
/** @override */
InMemoryCache.prototype.get = function (key) {

@@ -114,3 +114,3 @@ return this.mget([key]).then(function (data) {

/** @inheritDoc */
/** @override */
InMemoryCache.prototype.mget = function (keys) {

@@ -130,26 +130,47 @@ var ret = []

/** @inheritDoc */
InMemoryCache.prototype.set = function (key, val, maxAgeMs) {
if ((maxAgeMs === undefined || maxAgeMs <= 0) && !this._maxAgeOverride) throw new Error('maxAge must either be positive or overriden with a positive overrideMaxAgeMs')
this._expireAt[key] = Date.now() + (this._maxAgeOverride || maxAgeMs )
return this._data[key] = val
/** @override */
InMemoryCache.prototype.set = function (key, val, maxAgeMs, setWhenNotExist) {
if ((maxAgeMs === undefined || maxAgeMs <= 0) && !this._maxAgeOverride) {
return Q.reject(new Error('maxAgeMs must either be positive or overriden with a positive overrideMaxAgeMs'))
}
this._setInternal(key, val, maxAgeMs, setWhenNotExist)
return Q.resolve(null)
}
/** @inheritDoc */
InMemoryCache.prototype.mset = function (items, maxAgeMs) {
/** @override */
InMemoryCache.prototype.mset = function (items, maxAgeMs, setWhenNotExist) {
if ((maxAgeMs === undefined || maxAgeMs <= 0) && !this._maxAgeOverride) {
return Q.reject(new Error('maxAgeMs must either be positive or overriden with a positive overrideMaxAgeMs'))
}
for (var i = 0; i < items.length; i++) {
this.set(items[i].key, items[i].value, maxAgeMs)
this._setInternal(items[i].key, items[i].value, maxAgeMs, setWhenNotExist)
}
return Q.resolve(null)
}
/** @inheritDoc */
/**
* A helper function that sets an individual value.
*/
InMemoryCache.prototype._setInternal = function (key, val, maxAgeMs, setWhenNotExist) {
if (setWhenNotExist && (key in this._data)) {
return
}
this._expireAt[key] = Date.now() + (this._maxAgeOverride || maxAgeMs )
this._data[key] = val
}
/** @override */
InMemoryCache.prototype.del = function (key) {
;delete this._data[key]
;delete this._expireAt[key]
return true
return Q.resolve(null)
}
/** @inheritDoc */
CacheInstance.prototype.getPendingRequestsCount = function () {
/** @override */
InMemoryCache.prototype.getUrisByKey = function (key) {
return ['InMemoryCache']
}
/** @override */
InMemoryCache.prototype.getPendingRequestsCount = function () {
var requestCounts = {}

@@ -156,0 +177,0 @@ requestCounts['count'] = 0

@@ -7,2 +7,6 @@ var memc = require('node-memcache-parser-obvfork').client

/**
* @constructor
* @extends {CacheInstance}
*/
function MemcacheConnection(host, port, encoding) {

@@ -125,2 +129,2 @@ CacheInstance.call(this)

module.exports = MemcacheConnection
module.exports = MemcacheConnection

@@ -47,2 +47,3 @@ // Copyright 2014 A Medium Corporation

* @constructor
* @extends {CacheInstance}
*/

@@ -61,3 +62,3 @@ function MultiplexingCache(delegate) {

* number of promises when doing mgets.
* @type {Object.<Promise.<Object.<*>>}
* @type {Object.<Q.Promise.<Object.<*>>>}
*/

@@ -119,8 +120,2 @@ this._pendingGets = {}

/** @override */
MultiplexingCache.prototype.updateCount = function() {
return this._delegate.updateCount()
}
/** @override */
MultiplexingCache.prototype.getStats = function (op) {

@@ -150,11 +145,18 @@ return this._delegate.getStats(op)

/** @override */
MultiplexingCache.prototype.mset = function (items, maxAgeMs) {
MultiplexingCache.prototype.getUrisByKey = function (key) {
return this._delegate.getUrisByKey(key)
}
/** @override */
MultiplexingCache.prototype.mset = function (items, maxAgeMs, setWhenNotExist) {
this._invalidateKeys(items)
return this._delegate.mset(items, maxAgeMs)
return this._delegate.mset(items, maxAgeMs, setWhenNotExist)
}
MultiplexingCache.prototype.set = function (key, val, maxAgeMs) {
/** @override */
MultiplexingCache.prototype.set = function (key, val, maxAgeMs, setWhenNotExist) {
this._invalidateKeys([key])
return this._delegate.set(key, val, maxAgeMs)
return this._delegate.set(key, val, maxAgeMs, setWhenNotExist)
}

@@ -169,3 +171,2 @@

/** @override */

@@ -228,3 +229,2 @@ MultiplexingCache.prototype.get = function (key) {

/**

@@ -246,3 +246,3 @@ * Deletes the promise for a set of keys or objects.

* @param {Array.<string>} keys
* @return {Promise.<Object>}
* @return {Q.Promise.<Object>}
* @private

@@ -269,2 +269,3 @@ */

* @private
* @template T
*/

@@ -280,3 +281,5 @@ MultiplexingCache.prototype._convertToMap = function (keys) {

}
/** @inheritDoc */
/** @override */
MultiplexingCache.prototype.getPendingRequestsCount = function () {

@@ -283,0 +286,0 @@ return this._delegate.getPendingRequestsCount()

@@ -15,2 +15,3 @@ // Copyright 2014 The Obvious Corporation.

* @constructor
* @extends {Error}
*/

@@ -35,3 +36,3 @@ function PartialResultError(data, err) {

/**
* @param {Object.<string, *>} err The keys that failed to process.
* @return {Object.<string, *>} The keys that failed to process.
* The values in this object are the errors.

@@ -38,0 +39,0 @@ */

@@ -14,4 +14,4 @@ var redis = require('redis')

* @param {string} host The host that runs the redis-server
* @param {string} port The port that the redis-server listens to
* @param {Object=} options Additional options for this connection.
* @param {number} port The port that the redis-server listens to
* @param {{requestTimeoutMs: (number|undefined)}=} options Additional options for this connection.
* 'requestTimeoutMs' specifies the timeout of a Redis request.

@@ -27,2 +27,3 @@ * @extends CacheInstance

this._port = port || null
this._uri = this._host + ':' + this._port
this._bound_onConnect = this._onConnect.bind(this)

@@ -34,3 +35,3 @@ this._bound_onError = this._onError.bind(this)

/** @inheritDoc */
/** @override */
RedisConnection.prototype.isAvailable = function () {

@@ -40,23 +41,34 @@ return this._isAvailable

/** @inheritDoc */
RedisConnection.prototype.set = function (key, val, maxAgeMs) {
/** @override */
RedisConnection.prototype.set = function (key, val, maxAgeMs, setWhenNotExist) {
var deferred = Q.defer()
this._client.setex(key, Math.floor(maxAgeMs / 1000), val,
this._makeNodeResolverWithTimeout(deferred, 'set', 'Redis [set] key: ' + key))
var params = [key, val, 'PX', maxAgeMs]
if (setWhenNotExist) params.push('NX')
this._client.set(params, this._makeNodeResolverWithTimeout(deferred, 'set', 'Redis [set] key: ' + key))
return deferred.promise
}
/** @inheritDoc */
RedisConnection.prototype.mset = function (items, maxAgeMs) {
if (!items || !items.length) return Q.resolve()
/** @override */
RedisConnection.prototype.mset = function (items, maxAgeMs, setWhenNotExist) {
if (!items || !items.length) return Q.resolve(undefined)
var deferred = Q.defer()
var msetCommand = ["MSET"]
var commands = [msetCommand]
for (var i = 0, l = items.length; i < l; i++) {
var key = items[i].key
// Append key value arguments to the set command.
msetCommand.push(key, items[i].value)
// Append an expire command.
commands.push(["EXPIRE", key, Math.floor(maxAgeMs / 1000)])
var commands = []
var i, l
if (setWhenNotExist) {
// Use "SET" to set each key with a "NX" flag.
for (i = 0, l = items.length; i < l; i++) {
commands.push(['set', items[i].key, items[i].value, 'PX', maxAgeMs, 'NX'])
}
} else {
// Use "MSET" to set all the keys and "EXPIRE" to set TTL for each key
var msetCommand = ['MSET']
commands.push(msetCommand)
for (i = 0, l = items.length; i < l; i++) {
var key = items[i].key
// Append key value arguments to the set command.
msetCommand.push(key, items[i].value)
// Append an expire command.
commands.push(['EXPIRE', key, Math.floor(maxAgeMs / 1000)])
}
}

@@ -70,3 +82,3 @@ this._client.multi(commands).exec(

/** @inheritDoc */
/** @override */
RedisConnection.prototype.del = function (key) {

@@ -79,3 +91,3 @@ var deferred = Q.defer()

/** @inheritDoc */
/** @override */
RedisConnection.prototype.get = function (key) {

@@ -86,3 +98,3 @@ return this.mget([key])

/** @inheritDoc */
/** @override */
RedisConnection.prototype.mget = function (keys) {

@@ -107,6 +119,6 @@ if (!keys || !keys.length) return Q.resolve([])

})
.then(this.updateCount())
.then(this.getCountUpdater())
}
/** @inheritDoc */
/** @override */
RedisConnection.prototype.getServerInfo = function () {

@@ -122,3 +134,3 @@ var deferred = Q.defer()

.map(function(item) {items[item[0]] = item[1]})
var serverInfo = new ServerInfo
var serverInfo = new ServerInfo()
try {

@@ -132,3 +144,3 @@ serverInfo.memoryBytes = parseInt(items['used_memory'], 10)

} catch (e) {
Q.reject('Malformatted output from the "INFO" command of Redis')
Q.reject(new Error('Malformatted output from the "INFO" command of Redis'))
}

@@ -139,3 +151,3 @@ return Q.resolve(serverInfo)

/** @inheritDoc */
/** @override */
RedisConnection.prototype.disconnect = function () {

@@ -147,3 +159,3 @@ this._isAvailable = false

/** @inheritDoc */
/** @override */
RedisConnection.prototype.destroy = function () {

@@ -155,3 +167,3 @@ this.disconnect()

/** @inheritDoc */
/** @override */
RedisConnection.prototype.connect = function () {

@@ -172,17 +184,22 @@ if (this._isAvailable) return

/** @override */
RedisConnection.prototype.getUrisByKey = function (key) {
return [this._uri]
}
/**
* Gets the uri of the server
* @return {string}
* Return the URI of this Redis server.
*
* @return {string} The URI of this Redis server.
*/
RedisConnection.prototype.getUri = function () {
return this._host + ':' + this._port
return this._uri
}
/** @inheritDoc */
/** @override */
RedisConnection.prototype.getPendingRequestsCount = function () {
var requestCounts = {
'uri': this.getUri(),
return [{
'uri': this._uri,
'count': this._client.command_queue.length
}
return [requestCounts]
}]
}

@@ -208,3 +225,3 @@

*
* @param {Promise} deferred A deferred promise.
* @param {Q.Promise} deferred A deferred promise.
* @param {string} opName The name of the operation. It should be one of these: 'get',

@@ -211,0 +228,0 @@ * 'mget', 'set', 'mset' and 'del'.

@@ -7,2 +7,6 @@ var util = require('util')

/**
* @constructor
* @extends {CacheInstance}
*/
function RedundantCacheGroup() {

@@ -55,3 +59,3 @@ CacheInstance.call(this)

RedundantCacheGroup.prototype.isAvailable = function () {
return !!this._getAvailableInstance()
return !!this._getAvailableInstance(0)
}

@@ -82,2 +86,6 @@

/**
* @param {number=} start
* @override
*/
RedundantCacheGroup.prototype.mget = function (keys, start) {

@@ -114,2 +122,6 @@ var instanceIndex = this._getIndexOfFirstAvailableInstance(start || 0)

/**
* @param {number=} start
* @override
*/
RedundantCacheGroup.prototype.get = function (key, start) {

@@ -128,3 +140,3 @@ var instanceIndex = this._getIndexOfFirstAvailableInstance(start || 0)

RedundantCacheGroup.prototype.mset = function (items, maxAgeMs) {
RedundantCacheGroup.prototype.mset = function (items, maxAgeMs, setWhenNotExist) {
var instances = this._getAllInstances()

@@ -134,3 +146,3 @@ var promises = []

for (var i = 0; i < instances.length; i++) {
promises.push(instances[i].mset(items, maxAgeMs))
promises.push(instances[i].mset(items, maxAgeMs, setWhenNotExist))
}

@@ -142,3 +154,4 @@

RedundantCacheGroup.prototype.set = function (key, val, maxAgeMs) {
/** @override */
RedundantCacheGroup.prototype.set = function (key, val, maxAgeMs, setWhenNotExist) {
var instances = this._getAllInstances()

@@ -148,3 +161,3 @@ var promises = []

for (var i = 0; i < instances.length; i++) {
promises.push(instances[i].set(key, val, maxAgeMs))
promises.push(instances[i].set(key, val, maxAgeMs, setWhenNotExist))
}

@@ -169,4 +182,17 @@

/** @override */
RedundantCacheGroup.prototype.getUrisByKey = function (key) {
var uris = []
this._getAllInstances().forEach(function (instance) {
instance.getUrisByKey(key).forEach(function (uri) {
if (uris.indexOf(uri) < 0) uris.push(uri)
})
})
return uris
}
/** @override */
RedundantCacheGroup.prototype.getPendingRequestsCount = function () {
return cacheUtils.mergePendingRequestCounts(cacheInstnaces.map(function (obj) { return obj.instance }))
return cacheUtils.mergePendingRequestCounts(this._getAllInstances())
}

@@ -173,0 +199,0 @@

@@ -7,2 +7,3 @@ // Copyright 2013 The Obvious Corporation.

* @constructor
* @extends {Error}
*/

@@ -9,0 +10,0 @@ function TimeoutError(msg) {

{
"name": "zcache",
"description": "AWS zone-aware multi-layer cache",
"version": "0.3.6",
"homepage": "https://github.com/Obvious/zcache",
"version": "0.4.0-alpha",
"homepage": "https://github.com/Medium/zcache",
"authors": [

@@ -12,6 +12,6 @@ "Jeremy Stanley <github@azulus.com> (https://github.com/azulus)",

"keywords": ["zcache", "cache", "redis"],
"main": "lib/zcache.js",
"main": "index.js",
"repository": {
"type": "git",
"url": "https://github.com/Obvious/zcache.git"
"url": "https://github.com/Medium/zcache.git"
},

@@ -21,3 +21,3 @@ "dependencies": {

"generic-pool": "2.0.3",
"kew": "0.3.3",
"kew": "0.4.0",
"redis": "0.8.2",

@@ -31,7 +31,16 @@ "hiredis": "0.1.16",

"nodeunitq": "0.0.3",
"logg": "0.2.2"
"logg": "0.2.2",
"closure-npc": "0.1.3"
},
"externDependencies": {
"redis": "./externs/redis.js",
"xxhash": "./externs/xxhash.js",
"hashring": "./externs/hashring.js",
"node-memcache-parser-obvfork": "./externs/node-memcache-parser-obvfork.js",
"generic-pool": "./externs/generic-pool.js",
"metrics": "./externs/metrics.js"
},
"scripts": {
"test": "./node_modules/nodeunit/bin/nodeunit test"
"test": "./node_modules/.bin/closure-npc --jscomp_error=checkTypes && ./node_modules/nodeunit/bin/nodeunit test"
}
}

@@ -233,2 +233,14 @@ // Copyright 2014 The Obvious Corporation.

builder.add(function testGetUri(test) {
var cluster = new zcache.CacheCluster()
cluster.addNode('FakeCache1', new zcache.FakeCache(logger), 1, 0)
cluster.addNode('FakeCache2', new zcache.FakeCache(logger), 1, 0)
cluster.addNode('FakeCache3', new zcache.FakeCache(logger), 1, 0)
cluster.connect()
test.equal('FakeCache2', cluster.getUrisByKey('foo'), 'Key "foo" should be on cache 2')
test.equal('FakeCache1', cluster.getUrisByKey('bar'), 'Key "foo" should be on cache 1')
test.done()
})
builder.add(function testCornerCaseWithOnlyOneNode(test) {

@@ -235,0 +247,0 @@ var cluster = new zcache.CacheCluster()

var zcache = require('../index')
var Q = require('kew')
// TODO: these test cases should be using nodeunitq
exports.setUp = function (callback) {

@@ -23,18 +25,39 @@ this.cI = new zcache.InMemoryCache()

exports.testCacheSet = function (test) {
var self = this
test.equal(0, this.cI.getKeyCount(), 'There is no key in cache')
this.cI.set('foo', 'bar', 10000)
test.equal(this.cI._data['foo'], 'bar', 'bar should be returned')
test.equal(1, this.cI.getKeyCount(), 'There is 1 key in cache')
test.done()
.then(function() {
test.equal(self.cI._data['foo'], 'bar', 'bar should be returned')
test.equal(1, self.cI.getKeyCount(), 'There is 1 key in cache')
test.done()
})
}
exports.testCacheSetImproperMaxAge = function (test) {
var client = this
test.throws(function () {
client.cI.set('foo', 'bar')
})
exports.testCacheMset = function (test) {
var self = this
var items = [
{key: 'key1', value: 'value1'},
{key: 'key2', value: 'value2'}
]
test.done()
test.equal(0, this.cI.getKeyCount(), 'There is no key in cache')
this.cI.mset(items, 10000)
.then(function() {
test.equal('value1', self.cI._data['key1'], '"key1" should be set')
test.equal('value2', self.cI._data['key2'], '"key2" should be set')
test.equal(2, self.cI.getKeyCount(), 'There should be two keys in cache')
test.done()
})
}
exports.testCacheSetImproperMaxAge = function (test) {
this.cI.set('foo', 'bar')
.then(function () {
test.fail('Invalide max age parameter should fail the test')
})
.fail(function () {
test.done()
})
}
exports.testCacheOverrideMaxAgeMs = function (test) {

@@ -114,23 +137,13 @@ this.cI.overrideMaxAgeMs(1) // super short

exports.testCacheDel = function (test) {
this.cI.set('foo', 1, 1000)
this.cI.del('foo')
test.deepEqual(this.cI._data['foo'], undefined, 'foo should have been deleted')
test.done()
var self = this
self.cI.set('foo', 1, 1000)
.then(function () {
return self.cI.del('foo')
})
.then(function () {
test.deepEqual(self.cI._data['foo'], undefined, 'foo should have been deleted')
test.done()
})
}
exports.testCacheMset = function (test) {
var sampleKeys = [
{key: 'a', value: 1},
{key: 'b', value: 2},
{key: 'c', value: 3}
]
this.cI.mset(sampleKeys, 1000)
test.equal(this.cI._data['a'], 1, 'a should be 1')
test.equal(this.cI._data['b'], 2, 'b should be 2')
test.equal(this.cI._data['c'], 3, 'c should be 3')
test.equal(3, this.cI.getKeyCount(), 'There are 3 keys in cache')
test.done()
}
exports.testCacheMget = function (test) {

@@ -192,1 +205,37 @@ this.cI.mset([{key: 'a', value: 1}, {key: 'b', value: 2}, {key: 'c', value: 3}], 1000)

}
exports.testSetNotExist = function (test) {
var cacheInstance = this.cI
cacheInstance.set('abc', '123', 30000)
cacheInstance.set('abc', '456', 30000, true)
cacheInstance.get('abc')
.then(function (val) {
test.equals('123', val, 'The value should still be "123"')
test.done()
})
}
exports.testMsetNotExist = function (test) {
var cacheInstance = this.cI
var items = [
{key: 'key1', value: 'value1'},
{key: 'key3', value: 'value3'}
]
cacheInstance.mset(items, 30000)
items = [
{key: 'key1', value: 'value1_new'},
{key: 'key2', value: 'value2'},
{key: 'key3', value: 'value3_new'},
{key: 'key4', value: 'value4'}
]
cacheInstance.mset(items, 30000, true)
cacheInstance.mget(['key1', 'key2', 'key3', 'key4'])
.then(function (values) {
test.deepEqual(['value1', 'value2', 'value3', 'value4'], values, 'key2 and key4 should be set')
test.done()
})
}

@@ -106,1 +106,215 @@ var zcache = require('../index')

}
exports.testSetNotExist = function (test) {
var cacheInstance = new zcache.RedisConnection('localhost', 6379)
cacheInstance.on('connect', function () {
cacheInstance.removeAllListeners('connect')
test.equal(cacheInstance.isAvailable(), true, 'Connection should be available')
cacheInstance.set('abc', '123', 300000)
.then(function () {
return cacheInstance.set('abc', '456', 300000, true)
})
.then(function (val) {
return cacheInstance.get('abc')
})
.then(function (val) {
test.equal(val, '123')
cacheInstance.destroy()
})
.fail(function (e) {
console.error(e)
test.fail(e.message)
test.done()
})
})
cacheInstance.on('destroy', function () {
test.done()
})
cacheInstance.connect()
}
exports.testMsetNotExist = function (test) {
var cacheInstance = new zcache.RedisConnection('localhost', 6379)
cacheInstance.on('connect', function () {
cacheInstance.removeAllListeners('connect')
test.equal(cacheInstance.isAvailable(), true, 'Connection should be available')
var items = [
{key: 'key1', value: 'value1'},
{key: 'key3', value: 'value3'}
]
Q.all([cacheInstance.del('key1'), cacheInstance.del('key2'), cacheInstance.del('key3'), cacheInstance.del('key4')])
.then(function () {
cacheInstance.mset(items, 300000)
})
.then(function () {
var items = [
{key: 'key1', value: 'value1_new'},
{key: 'key2', value: 'value2'},
{key: 'key3', value: 'value3_new'},
{key: 'key4', value: 'value4'}
]
return cacheInstance.mset(items, 300000, true)
})
.then(function (val) {
return cacheInstance.mget(['key1', 'key2', 'key3', 'key4'])
})
.then(function (vals) {
test.deepEqual(['value1', 'value2', 'value3', 'value4'], vals)
cacheInstance.destroy()
})
.fail(function (e) {
console.error(e)
test.fail(e.message)
test.done()
})
})
cacheInstance.on('destroy', function () {
test.done()
})
cacheInstance.connect()
}
// Test .set() with TTL
// (1) set a key with 1 sec TTL
// (2) wait for 1.05 sec
// (3) get the key, and it should return 'undefined'.
exports.testSetTimeout = function (test) {
var cacheInstance = new zcache.RedisConnection('localhost', 6379)
cacheInstance.on('connect', function () {
cacheInstance.removeAllListeners('connect')
test.equal(cacheInstance.isAvailable(), true, 'Connection should be available')
cacheInstance.set('abc', '123', 1000)
.then(function () {
return Q.delay(1050)
})
.then(function (val) {
return cacheInstance.get('abc')
})
.then(function (val) {
test.deepEqual(undefined, val, 'The "abc" key should have been expired after 1.05 sec')
cacheInstance.destroy()
})
.fail(function (e) {
console.error(e)
test.fail(e.message)
test.done()
})
})
cacheInstance.on('destroy', function () {
test.done()
})
cacheInstance.connect()
}
// Test .mset() with 'setWhenNotExist' set and TTL
// (1) set two keys with a long TTL
// (2) set two existing keys plus two more new keys with 'setWhenNotExist' set and with 1 sec TTL
// (3) wait for 1.05 sec.
// (4) the two new keys should have expired and the two old keys should still exist and have the old value
exports.testMsetNotExistTimeout = function (test) {
var cacheInstance = new zcache.RedisConnection('localhost', 6379)
cacheInstance.on('connect', function () {
cacheInstance.removeAllListeners('connect')
test.equal(cacheInstance.isAvailable(), true, 'Connection should be available')
var items = [
{key: 'key1', value: 'value1'},
{key: 'key3', value: 'value3'}
]
Q.all([cacheInstance.del('key1'), cacheInstance.del('key2'), cacheInstance.del('key3'), cacheInstance.del('key4')])
.then(function () {
cacheInstance.mset(items, 300000)
})
.then(function () {
var items = [
{key: 'key1', value: 'value1_new'},
{key: 'key2', value: 'value2'},
{key: 'key3', value: 'value3_new'},
{key: 'key4', value: 'value4'}
]
return cacheInstance.mset(items, 1000, true)
})
.then(function (val) {
return Q.delay(1050)
})
.then(function (val) {
return cacheInstance.mget(['key1', 'key2', 'key3', 'key4'])
})
.then(function (vals) {
test.deepEqual(['value1', undefined, 'value3', undefined], vals, '"key2" and "key4" should have been expired at this moment')
cacheInstance.destroy()
})
.fail(function (e) {
console.error(e)
test.fail(e.message)
test.done()
})
})
cacheInstance.on('destroy', function () {
test.done()
})
cacheInstance.connect()
}
exports.testCounts = function (test) {
var cacheInstance = new zcache.RedisConnection('localhost', 6379)
cacheInstance.on('connect', function () {
cacheInstance.removeAllListeners('connect')
test.equal(cacheInstance.isAvailable(), true, 'Connection should be available')
var items = [
{key: 'key1', value: 'value1'},
{key: 'key3', value: 'value3'}
]
Q.all([cacheInstance.del('key1'), cacheInstance.del('key2'), cacheInstance.del('key3'), cacheInstance.del('key4')])
.then(function () {
cacheInstance.mset(items, 300000)
})
.then(function () {
return cacheInstance.mget(['key1', 'key2', 'key3', 'key4'])
})
.then(function (vals) {
test.deepEqual(['value1', undefined, 'value3', undefined], vals, '"key2" and "key4" should have been expired at this moment')
test.equals(4, cacheInstance.getAccessCount())
test.equals(2, cacheInstance.getHitCount())
cacheInstance.destroy()
})
.fail(function (e) {
console.error(e)
test.fail(e.message)
test.done()
})
})
cacheInstance.on('destroy', function () {
test.done()
})
cacheInstance.connect()
}
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