Socket
Socket
Sign inDemoInstall

memcached

Package Overview
Dependencies
Maintainers
1
Versions
33
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

memcached - npm Package Compare versions

Comparing version 0.1.0 to 0.1.1

CHANGELOG

66

lib/connection.js

@@ -7,3 +7,2 @@ "use strict";

exports.Manager = ConnectionManager; // connection pooling
exports.IssueLog = IssueLog; // connection issue handling

@@ -108,66 +107,1 @@ exports.Available = ping; // connection availablity

};
function ConnectionManager (name, limit, constructor) {
this.name = name;
this.total = limit;
this.factory = constructor;
this.connections = [];
}
var Manager = ConnectionManager.prototype;
Manager.allocate = function allocate (callback) {
var total, i
, Manager = this;
i = total = this.connections.length;
// check for available
while (i--){
if (this.isAvailable(this.connections[i])) {
return callback(false, this.connections[i]);
}
}
// create new
if (total < this.total) {
return this.connections.push(this.factory.apply(this, arguments));
}
// give up and don't saturate the node.js process by retying #43
var full = new Error("All the connections in the memcached pool are busy");
full.connectionPool = true;
callback(full);
};
Manager.isAvailable = function isAvailable (connection) {
var readyState = connection.readyState;
return (readyState === 'open' || readyState === 'writeOnly')
&& !(connection._writeQueue && connection._writeQueue.length)
&& !(connection._handle && connection._handle.writeQueueSize);
};
Manager.remove = function remove (connection) {
var position = this.connections.indexOf(connection);
if (position !== -1) this.connections.splice(position, 1);
if (connection.readyState && connection.readyState !== 'closed' && connection.end) {
connection.end();
}
};
Manager.free = function freemymemories (keep) {
var save = 0
, connection;
while (this.connections.length) {
connection = this.connections.shift();
if (save < keep && this.isAvailable(this.connection[0])) {
save++;
continue;
}
this.remove(connection);
}
};

187

lib/memcached.js

@@ -6,3 +6,2 @@ "use strict";

*/
var EventEmitter = require('events').EventEmitter

@@ -15,7 +14,6 @@ , Stream = require('net').Stream

*/
var HashRing = require('hashring')
, Connection = require('./connection')
, Jackpot = require('jackpot')
, Utils = require('./utils')
, Manager = Connection.Manager
, IssueLog = Connection.IssueLog;

@@ -26,3 +24,2 @@

*/
var curry = Utils.curry;

@@ -38,3 +35,2 @@

*/
function Client (args, options) {

@@ -79,17 +75,17 @@ var servers = []

Client.config = {
maxKeySize: 251 // max key size allowed by Memcached
, maxExpiration: 2592000 // max expiration duration allowed by Memcached
, maxValue: 1048576 // max length of value allowed by Memcached
maxKeySize: 251 // max key size allowed by Memcached
, maxExpiration: 2592000 // max expiration duration allowed by Memcached
, maxValue: 1048576 // max length of value allowed by Memcached
, algorithm: 'crc32' // hashing algorithm that is used for key mapping
, algorithm: 'crc32' // hashing algorithm that is used for key mapping
, poolSize: 10 // maximal parallel connections
, reconnect: 18000000 // if dead, attempt reconnect each xx ms
, timeout: 5000 // after x ms the server should send a timeout if we can't connect
, retries: 5 // amount of retries before server is dead
, retry: 30000 // timeout between retries, all call will be marked as cache miss
, remove: false // remove server if dead if false, we will attempt to reconnect
, redundancy: false // allows you do re-distribute the keys over a x amount of servers
, keyCompression: true // compress keys if they are to large (md5)
, debug: false // Output the commands and responses
, poolSize: 10 // maximal parallel connections
, reconnect: 18000000 // if dead, attempt reconnect each xx ms
, timeout: 5000 // after x ms the server should send a timeout if we can't connect
, retries: 5 // amount of retries before server is dead
, retry: 30000 // timeout between retries, all call will be marked as cache miss
, remove: false // remove server if dead if false, we will attempt to reconnect
, redundancy: false // allows you do re-distribute the keys over a x amount of servers
, keyCompression: true // compress keys if they are to large (md5)
, debug: false // Output the commands and responses
};

@@ -114,3 +110,3 @@

// will receive the connection if the operation was successful
memcached.connect = function connect (server, callback) {
memcached.connect = function connect(server, callback) {
// server is dead, bail out

@@ -123,3 +119,3 @@ if (server in this.issues && this.issues[server].failed) {

if (server in this.connections) {
return this.connections[server].allocate(callback);
return this.connections[server].pull(callback);
}

@@ -143,3 +139,4 @@

manager = new Manager(server, this.poolSize, function factory (callback) {
manager = new Jackpot(this.poolSize);
manager.factory(function factory() {
var S = Array.isArray(serverTokens)

@@ -164,13 +161,10 @@ ? new Stream

Utils.fuse(S, {
connect: function streamConnect () {
callback(false, this);
}
, close: function streamClose () {
close: function streamClose() {
Manager.remove(this);
}
, error: function streamError (err) {
, error: function streamError(err) {
memcached.connectionIssue(err, S, callback);
}
, data: curry(memcached, privates.buffer, S)
, timeout: function streamTimeout () {
, timeout: function streamTimeout() {
Manager.remove(this);

@@ -190,3 +184,3 @@ }

// connection
this.connections[server].allocate(callback);
this.connections[server].pull(callback);
};

@@ -196,3 +190,3 @@

// servers.
memcached.multi = function memcachedMulti (keys, callback) {
memcached.multi = function memcachedMulti(keys, callback) {
var map = {}

@@ -206,3 +200,3 @@ , memcached = this

if (keys) {
keys.forEach(function fetchMultipleServers (key) {
keys.forEach(function fetchMultipleServers(key) {
var server = memcached.servers.length === 1

@@ -234,3 +228,3 @@ ? memcached.servers[0]

// use the query.key to get the server from the HashRing
memcached.command = function memcachedCommand (queryCompiler, server) {
memcached.command = function memcachedCommand(queryCompiler, server) {
// generate a regular query,

@@ -266,5 +260,5 @@ var query = queryCompiler()

this.connect(server, function allocateMemcachedConnection (error, S) {
this.connect(server, function allocateMemcachedConnection(error, S) {
if (memcached.debug) {
query.command.split(LINEBREAK).forEach(function errors (line) {
query.command.split(LINEBREAK).forEach(function errors(line) {
console.log(S.streamID + ' << ' + line);

@@ -297,6 +291,6 @@ });

redundancy.forEach(function each (server) {
redundancy.forEach(function each(server) {
if (server in memcached.issues && memcached.issues[server].failed) return;
memcached.connect(server, function allocateMemcachedConnection (error, S) {
memcached.connect(server, function allocateMemcachedConnection(error, S) {
if (!S || error || S.readyState !== 'open') return;

@@ -311,3 +305,3 @@ S.write(queryRedundancy.command + LINEBREAK);

// cache misses.
memcached.connectionIssue = function connectionIssue (error, S, callback) {
memcached.connectionIssue = function connectionIssue(error, S, callback) {
// end connection and mark callback as cache miss

@@ -336,15 +330,15 @@ if (S && S.end) S.end();

Utils.fuse(issues, {
issue: function issue (details) {
issue: function issue(details) {
memcached.emit('issue', details);
}
, failure: function failure (details) {
, failure: function failure(details) {
memcached.emit('failure', details);
}
, reconnecting: function reconnect (details) {
, reconnecting: function reconnect(details) {
memcached.emit('reconnecting', details);
}
, reconnected: function reconnected (details) {
, reconnected: function reconnected(details) {
memcached.emit('reconnect', details);
}
, remove: function remove (details) {
, remove: function remove(details) {
// emit event and remove servers

@@ -368,6 +362,6 @@ memcached.emit('remove', details);

// Kills all active connections
memcached.end = function endMemcached () {
memcached.end = function endMemcached() {
var memcached = this;
Object.keys(this.connections).forEach(function closeConnection (key) {
Object.keys(this.connections).forEach(function closeConnection(key) {
memcached.connections[key].free(0);

@@ -381,17 +375,21 @@ });

// handle error responses
'NOT_FOUND': function notfound (tokens, dataSet, err) {
'NOT_FOUND': function notfound(tokens, dataSet, err) {
return [CONTINUE, false];
}
, 'NOT_STORED': function notstored (tokens, dataSet, err) {
, 'NOT_STORED': function notstored(tokens, dataSet, err) {
return [CONTINUE, false];
}
, 'ERROR': function error (tokens, dataSet, err) {
, 'ERROR': function error(tokens, dataSet, err) {
err.push('Received an ERROR response');
return [FLUSH, false];
}
, 'CLIENT_ERROR': function clienterror (tokens, dataSet, err) {
, 'CLIENT_ERROR': function clienterror(tokens, dataSet, err) {
err.push(tokens.splice(1).join(' '));
return [CONTINUE, false];
}
, 'SERVER_ERROR': function servererror (tokens, dataSet, err, queue, S, memcached) {
, 'SERVER_ERROR': function servererror(tokens, dataSet, err, queue, S, memcached) {
(memcached || this.memcached).connectionIssue(tokens.splice(1).join(' '), S);

@@ -402,15 +400,19 @@ return [CONTINUE, false];

// keyword based responses
, 'STORED': function stored (tokens, dataSet) {
, 'STORED': function stored(tokens, dataSet) {
return [CONTINUE, true];
}
, 'DELETED': function deleted (tokens, dataSet) {
, 'DELETED': function deleted(tokens, dataSet) {
return [CONTINUE, true];
}
, 'OK': function ok (tokens, dataSet) {
, 'OK': function ok(tokens, dataSet) {
return [CONTINUE, true];
}
, 'EXISTS': function exists (tokens, dataSet) {
, 'EXISTS': function exists(tokens, dataSet) {
return [CONTINUE, false];
}
, 'END': function end (tokens, dataSet, err, queue) {
, 'END': function end(tokens, dataSet, err, queue) {
if (!queue.length) queue.push(false);

@@ -421,3 +423,3 @@ return [FLUSH, true];

// value parsing:
, 'VALUE': function value (tokens, dataSet, err, queue) {
, 'VALUE': function value(tokens, dataSet, err, queue) {
var key = tokens[1]

@@ -458,10 +460,12 @@ , flag = +tokens[2]

, 'INCRDECR': function incrdecr (tokens) {
, 'INCRDECR': function incrdecr(tokens) {
return [CONTINUE, +tokens[1]];
}
, 'STAT': function stat (tokens, dataSet, err, queue) {
, 'STAT': function stat(tokens, dataSet, err, queue) {
queue.push([tokens[1], /^\d+$/.test(tokens[2]) ? +tokens[2] : tokens[2]]);
return [BUFFER, true];
}
, 'VERSION': function version (tokens, dataSet) {
, 'VERSION': function version(tokens, dataSet) {
var versionTokens = /(\d+)(?:\.)(\d+)(?:\.)(\d+)$/.exec(tokens.pop());

@@ -477,3 +481,4 @@

}
, 'ITEM': function item (tokens, dataSet, err, queue) {
, 'ITEM': function item(tokens, dataSet, err, queue) {
queue.push({

@@ -489,3 +494,3 @@ key: tokens[1]

function resultSetIsEmpty (resultSet) {
function resultSetIsEmpty(resultSet) {
return !resultSet || (resultSet.length === 1 && !resultSet[0]);

@@ -496,3 +501,3 @@ }

// combines the stats array, in to an object
'stats': function stats (resultSet) {
'stats': function stats(resultSet) {
var response = {};

@@ -505,3 +510,3 @@ if (resultSetIsEmpty(resultSet)) return response;

// Fill the object
resultSet.forEach(function each (statSet) {
resultSet.forEach(function each(statSet) {
if (statSet) response[statSet[0]] = statSet[1];

@@ -514,7 +519,8 @@ });

// the settings uses the same parse format as the regular stats
, 'stats settings': function settings () {
, 'stats settings': function settings() {
return privates.resultParsers.stats.apply(this, arguments);
}
// Group slabs by slab id
, 'stats slabs': function slabs (resultSet) {
, 'stats slabs': function slabs(resultSet) {
var response = {};

@@ -527,3 +533,3 @@ if (resultSetIsEmpty(resultSet)) return response;

// Fill the object
resultSet.forEach(function each (statSet) {
resultSet.forEach(function each(statSet) {
if (statSet) {

@@ -539,3 +545,4 @@ var identifier = statSet[0].split(':');

}
, 'stats items': function items (resultSet) {
, 'stats items': function items(resultSet) {
var response = {};

@@ -548,3 +555,3 @@ if (resultSetIsEmpty(resultSet)) return response;

// Fill the object
resultSet.forEach(function each (statSet) {
resultSet.forEach(function each(statSet) {
if (statSet) {

@@ -575,3 +582,3 @@ var identifier = statSet[0].split(':');

// all responds end with them.
privates.buffer = function BufferBuffer (S, BufferStream) {
privates.buffer = function BufferBuffer(S, BufferStream) {
S.responseBuffer += BufferStream;

@@ -585,3 +592,3 @@

if (this.debug) {
chunks.forEach(function each (line) {
chunks.forEach(function each(line) {
console.log(S.streamID + ' >> ' + line);

@@ -600,3 +607,3 @@ });

// format, deciding if we should queue it up, or send it to a callback fn.
memcached.rawDataReceived = function rawDataReceived (S) {
memcached.rawDataReceived = function rawDataReceived(S) {
var queue = []

@@ -696,3 +703,3 @@ , token

// Small wrapper function that only executes errors when we have a callback
privates.errorResponse = function errorResponse (error, callback) {
privates.errorResponse = function errorResponse(error, callback) {
if (typeof callback === 'function') callback(error, false);

@@ -707,3 +714,3 @@

this.command(function getCommand (noreply) {
this.command(function getCommand(noreply) {
return {

@@ -741,3 +748,3 @@ key: key

// handle multiple responses and cache them untill we receive all.
function handle (err, results) {
function handle(err, results) {
if (err) {

@@ -748,3 +755,3 @@ errors.push(err);

// add all responses to the array
(Array.isArray(results) ? results : [results]).forEach(function each (value) {
(Array.isArray(results) ? results : [results]).forEach(function each(value) {
Utils.merge(responses, value);

@@ -756,6 +763,6 @@ });

this.multi(keys, function multi (server, key, index, totals) {
this.multi(keys, function multi(server, key, index, totals) {
if (!calls) calls = totals;
memcached.command(function getMultiCommand (noreply) {
memcached.command(function getMultiCommand(noreply) {
return {

@@ -776,3 +783,3 @@ callback: handle

// enough to ignore those.
privates.setters = function setters (type, validate, key, value, lifetime, callback, cas) {
privates.setters = function setters(type, validate, key, value, lifetime, callback, cas) {
var flag = 0

@@ -798,3 +805,3 @@ , valuetype = typeof value

this.command(function settersCommand (noreply) {
this.command(function settersCommand(noreply) {
return {

@@ -848,3 +855,3 @@ key: key

memcached.cas = function checkandset (key, value, cas, lifetime, callback) {
memcached.cas = function checkandset(key, value, cas, lifetime, callback) {
privates.setters.call(this

@@ -866,3 +873,3 @@ , 'cas'

memcached.append = function append (key, value, callback) {
memcached.append = function append(key, value, callback) {
privates.setters.call(this

@@ -883,3 +890,3 @@ , 'append'

memcached.prepend = function prepend (key, value, callback) {
memcached.prepend = function prepend(key, value, callback) {
privates.setters.call(this

@@ -901,4 +908,4 @@ , 'prepend'

// Small handler for incr and decr's
privates.incrdecr = function incrdecr (type, key, value, callback) {
this.command(function incredecrCommand (noreply) {
privates.incrdecr = function incrdecr(type, key, value, callback) {
this.command(function incredecrCommand(noreply) {
return {

@@ -926,4 +933,4 @@ key: key

// Deletes the keys from the servers
memcached.del = function del (key, callback){
this.command(function deleteCommand (noreply) {
memcached.del = function del(key, callback){
this.command(function deleteCommand(noreply) {
return {

@@ -946,3 +953,3 @@ key: key

// Small wrapper that handle single keyword commands such as FLUSH ALL, VERSION and STAT
privates.singles = function singles (type, callback) {
privates.singles = function singles(type, callback) {
var memcached = this

@@ -954,3 +961,3 @@ , responses = []

// handle multiple servers
function handle (err, results) {
function handle(err, results) {
if (err) {

@@ -966,6 +973,6 @@ errors = errors || [];

this.multi(false, function multi (server, keys, index, totals) {
this.multi(false, function multi(server, keys, index, totals) {
if (!calls) calls = totals;
memcached.command(function singlesCommand (noreply) {
memcached.command(function singlesCommand(noreply) {
return {

@@ -997,4 +1004,4 @@ callback: handle

// see simple_cachedump.js for an example
memcached.cachedump = function cachedump (server, slabid, number, callback) {
this.command(function cachedumpCommand (noreply) {
memcached.cachedump = function cachedump(server, slabid, number, callback) {
this.command(function cachedumpCommand(noreply) {
return {

@@ -1001,0 +1008,0 @@ callback: callback

{
"name": "memcached"
, "version": "0.1.0"
, "version": "0.1.1"
, "author": "Arnout Kazemier"

@@ -37,3 +37,4 @@ , "description": "A fully featured Memcached API client, supporting both single and clustered Memcached servers through consistent hashing and failover/failure. Memcached is rewrite of nMemcached, which will be deprecated in the near future."

, "dependencies": {
"hashring": "*"
"hashring": "0.0.x"
, "jackpot": "0.0.x"
}

@@ -40,0 +41,0 @@ , "devDependencies": {

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