Comparing version 1.2.2 to 1.3.0
@@ -20,2 +20,5 @@ { | ||
}, | ||
"globals": { | ||
"Promise": "readonly" | ||
}, | ||
"env": { | ||
@@ -22,0 +25,0 @@ "node": true, |
@@ -5,2 +5,3 @@ // # MemJS Memcache Client | ||
var Server = require('./server').Server; | ||
var noopSerializer = require('./noop-serializer').noopSerializer; | ||
var makeRequestBuffer = require('./utils').makeRequestBuffer; | ||
@@ -19,2 +20,4 @@ var hashCode = require('./utils').hashCode; | ||
{failoverTime: 60, retries: 2, retry_delay: 0.2, expires: 0, logger: console}); | ||
this.serializer = this.options.serializer || noopSerializer; | ||
}; | ||
@@ -47,3 +50,17 @@ | ||
// Defaults to `console`. | ||
// * `serializer` - the object which will (de)serialize the data. It needs | ||
// two public methods: serialize and deserialize. It defaults to the | ||
// noopSerializer: | ||
// | ||
// ~~~~ | ||
// var noopSerializer = { | ||
// serialize: function (opcode, value, extras) { | ||
// return { value: value, extras: extras }; | ||
// }, | ||
// deserialize: function (opcode, value, extras) { | ||
// return { value: value, extras: extras }; | ||
// } | ||
// }; | ||
// ~~~~ | ||
// | ||
// Or options for the servers including: | ||
@@ -75,3 +92,4 @@ // * `username` and `password` for fallback SASL authentication credentials. | ||
// mechanisms | ||
var origIdx = hashCode(key) % this.servers.length; | ||
var total = this.servers.length; | ||
var origIdx = (total > 1) ? (hashCode(key) % total) : 0; | ||
var idx = origIdx; | ||
@@ -81,3 +99,3 @@ var serv = this.servers[idx]; | ||
serv.wakeupAt > Date.now()) { | ||
idx = (idx + 1) % this.servers.length; | ||
idx = (idx + 1) % total; | ||
if (idx === origIdx) { | ||
@@ -126,4 +144,4 @@ return null; | ||
Client.prototype.get = function(key, callback) { | ||
var self = this; | ||
if(callback === undefined) { | ||
var self = this; | ||
return promisify(function(callback) { | ||
@@ -136,3 +154,3 @@ self.get(key, function(err, value, flags) { | ||
var logger = this.options.logger; | ||
this.seq++; | ||
this.incrSeq(); | ||
var request = makeRequestBuffer(0, key, '', '', this.seq); | ||
@@ -146,3 +164,6 @@ this.perform(key, request, this.seq, function(err, response) { | ||
case 0: | ||
if (callback) { callback(null, response.val, response.extras); } | ||
if (callback) { | ||
var deserialized = self.serializer.deserialize(response.header.opcode, response.val, response.extras); | ||
callback(null, deserialized.value, deserialized.extras); | ||
} | ||
break; | ||
@@ -174,2 +195,3 @@ case 1: | ||
var self = this; | ||
if (!options) options = {}; | ||
return promisify(function(callback) { self.set(key, value, options, function(err, success) { callback(err, success); }); }); | ||
@@ -191,6 +213,9 @@ } | ||
// TODO: support flags, support version (CAS) | ||
this.seq++; | ||
this.incrSeq(); | ||
var expiration = makeExpiration(expires || this.options.expires); | ||
var extras = Buffer.concat([Buffer.from('00000000', 'hex'), expiration]); | ||
var request = makeRequestBuffer(1, key, extras, value, this.seq); | ||
var opcode = 1; | ||
var serialized = this.serializer.serialize(opcode, value, extras); | ||
var request = makeRequestBuffer(opcode, key, serialized.extras, serialized.value, this.seq); | ||
this.perform(key, request, this.seq, function(err, response) { | ||
@@ -228,2 +253,3 @@ if (err) { | ||
var self = this; | ||
if (!options) options = {}; | ||
return promisify(function(callback) { self.add(key, value, options, function(err, success) { callback(err, success); }); }); | ||
@@ -245,6 +271,9 @@ } | ||
// TODO: support flags, support version (CAS) | ||
this.seq++; | ||
this.incrSeq(); | ||
var expiration = makeExpiration(expires || this.options.expires); | ||
var extras = Buffer.concat([Buffer.from('00000000', 'hex'), expiration]); | ||
var request = makeRequestBuffer(2, key, extras, value, this.seq); | ||
var opcode = 2; | ||
var serialized = this.serializer.serialize(opcode, value, extras); | ||
var request = makeRequestBuffer(opcode, key, serialized.extras, serialized.value, this.seq); | ||
this.perform(key, request, this.seq, function(err, response) { | ||
@@ -285,2 +314,3 @@ if (err) { | ||
var self = this; | ||
if (!options) options = {}; | ||
return promisify(function(callback) { self.replace(key, value, options, function(err, success) { callback(err, success); }); }); | ||
@@ -302,6 +332,9 @@ } | ||
// TODO: support flags, support version (CAS) | ||
this.seq++; | ||
this.incrSeq(); | ||
var expiration = makeExpiration(expires || this.options.expires); | ||
var extras = Buffer.concat([Buffer.from('00000000', 'hex'), expiration]); | ||
var request = makeRequestBuffer(3, key, extras, value, this.seq); | ||
var opcode = 3; | ||
var serialized = this.serializer.serialize(opcode, value, extras); | ||
var request = makeRequestBuffer(opcode, key, serialized.extras, serialized.value, this.seq); | ||
this.perform(key, request, this.seq, function(err, response) { | ||
@@ -342,3 +375,3 @@ if (err) { | ||
var logger = this.options.logger; | ||
this.seq++; | ||
this.incrSeq(); | ||
var request = makeRequestBuffer(4, key, '', '', this.seq); | ||
@@ -381,2 +414,3 @@ this.perform(key, request, this.seq, function(err, response) { | ||
return promisify(function(callback) { | ||
if (!options) options = {}; | ||
self.increment(key, amount, options, function(err, success, value) { | ||
@@ -404,3 +438,3 @@ callback(err, {success: success, value: value}); | ||
// TODO: support version (CAS) | ||
this.seq++; | ||
this.incrSeq(); | ||
initial = initial || 0; | ||
@@ -467,3 +501,3 @@ expires = expires || this.options.expires; | ||
this.seq++; | ||
this.incrSeq(); | ||
initial = initial || 0; | ||
@@ -505,4 +539,6 @@ expires = expires || this.options.expires; | ||
var logger = this.options.logger; | ||
this.seq++; | ||
var request = makeRequestBuffer(0x0E, key, '', value, this.seq); | ||
this.incrSeq(); | ||
var opcode = 0x0E; | ||
var serialized = this.serializer.serialize(opcode, value, ''); | ||
var request = makeRequestBuffer(opcode, key, serialized.extras, serialized.value, this.seq); | ||
this.perform(key, request, this.seq, function(err, response) { | ||
@@ -542,4 +578,7 @@ if (err) { | ||
var logger = this.options.logger; | ||
this.seq++; | ||
var request = makeRequestBuffer(0x0E, key, '', value, this.seq); | ||
this.incrSeq(); | ||
var opcode = 0x0E; | ||
var serialized = this.serializer.serialize(opcode, value, ''); | ||
var request = makeRequestBuffer(opcode, key, serialized.extras, serialized.value, this.seq); | ||
this.perform(key, request, this.seq, function(err, response) { | ||
@@ -579,3 +618,3 @@ if (err) { | ||
var logger = this.options.logger; | ||
this.seq++; | ||
this.incrSeq(); | ||
var extras = makeExpiration(expires || this.options.expires); | ||
@@ -618,3 +657,3 @@ var request = makeRequestBuffer(0x1C, key, extras, '', this.seq); | ||
// TODO: support expiration | ||
this.seq++; | ||
this.incrSeq(); | ||
var request = makeRequestBuffer(0x08, '', '', '', this.seq); | ||
@@ -661,3 +700,3 @@ var count = this.servers.length; | ||
var logger = this.options.logger; | ||
this.seq++; | ||
this.incrSeq(); | ||
var request = makeRequestBuffer(0x10, key, '', '', this.seq); | ||
@@ -738,3 +777,3 @@ var i; | ||
Client.prototype.quit = function() { | ||
this.seq++; | ||
this.incrSeq(); | ||
// TODO: Nicer perhaps to do QUITQ (0x17) but need a new callback for when | ||
@@ -823,2 +862,10 @@ // write is done. | ||
// Increment the seq value | ||
Client.prototype.incrSeq = function() { | ||
this.seq++; | ||
// Wrap `this.seq` to 32-bits since the field we fit it into is only 32-bits. | ||
this.seq &= 0xffffffff; | ||
}; | ||
exports.Client = Client; | ||
@@ -825,0 +872,0 @@ exports.Server = Server; |
@@ -5,3 +5,3 @@ { | ||
"description": "A memcache client for node using the binary protocol and SASL authentication", | ||
"version": "1.2.2", | ||
"version": "1.3.0", | ||
"license": "MIT", | ||
@@ -35,6 +35,6 @@ "homepage": "http://github.com/memcachier/memjs", | ||
"docco": "^0.8.0", | ||
"eslint": "1.10.3", | ||
"microtime": "^2.1.7", | ||
"eslint": "4.18.2", | ||
"microtime": "^3.0.0", | ||
"tap": "4.0.*" | ||
} | ||
} |
@@ -112,3 +112,3 @@ MemJS | ||
The best way to contribut to the project is by reporting bugs and testing unpublished | ||
The best way to contribute to the project is by reporting bugs and testing unpublished | ||
versions. If you have a staging or development app, the easiest way to do this is | ||
@@ -115,0 +115,0 @@ using the git repository as your `memjs` package dependency---in `package.json`: |
@@ -56,2 +56,41 @@ var test = require('tap').test; | ||
test('GetSerializer', function(t) { | ||
var n = 0; | ||
var dn = 0; | ||
var dummyServer = new MemJS.Server(); | ||
dummyServer.write = function(requestBuf) { | ||
var request = MemJS.Utils.parseMessage(requestBuf); | ||
t.equal('hello', request.key.toString()); | ||
n += 1; | ||
dummyServer.respond( | ||
{header: {status: 0, opaque: request.header.opaque}, | ||
val: 'world', extras: 'flagshere'}); | ||
}; | ||
var client = new MemJS.Client([dummyServer], { | ||
serializer: { | ||
serialize: function(opcode, value, extras){ | ||
return { value: value, extras: extras }; | ||
}, | ||
deserialize: function (opcode, value, extras) { | ||
dn += 1; | ||
return { value: 'deserialized', extras: extras }; | ||
} | ||
} | ||
}); | ||
var assertor = function(err, val, flags) { | ||
t.equal('deserialized', val); | ||
t.equal('flagshere', flags); | ||
t.equal(null, err); | ||
t.equal(1, n, 'Ensure get is called'); | ||
t.equal(1, dn, 'Ensure deserialization is called once'); | ||
}; | ||
client.get('hello', assertor); | ||
n = 0; | ||
dn = 0; | ||
return client.get('hello').then(function(res) { | ||
assertor(null, res.value, res.flags); | ||
}); | ||
}); | ||
test('SetSuccessful', function(t) { | ||
@@ -101,2 +140,21 @@ var n = 0; | ||
test('SetPromiseWithoutOption', function(t) { | ||
var n = 0; | ||
var dummyServer = new MemJS.Server(); | ||
dummyServer.write = function(requestBuf) { | ||
var request = MemJS.Utils.parseMessage(requestBuf); | ||
t.equal('hello', request.key.toString()); | ||
t.equal('world', request.val.toString()); | ||
n += 1; | ||
dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); | ||
}; | ||
var client = new MemJS.Client([dummyServer]); | ||
return client.set('hello', 'world').then(function(val) { | ||
t.equal(true, val); | ||
t.equal(1, n, 'Ensure set is called'); | ||
t.end(); | ||
}); | ||
}); | ||
test('SetWithExpiration', function(t) { | ||
@@ -247,2 +305,39 @@ var n = 0; | ||
test('SetSerialize', function(t) { | ||
var n = 0; | ||
var sn = 0; | ||
var dummyServer = new MemJS.Server(); | ||
dummyServer.write = function(requestBuf) { | ||
var request = MemJS.Utils.parseMessage(requestBuf); | ||
t.equal('hello', request.key.toString()); | ||
t.equal('serialized', request.val.toString()); | ||
n += 1; | ||
dummyServer.respond({header: {status: 3, opaque: request.header.opaque}}); | ||
}; | ||
var client = new MemJS.Client([dummyServer], { | ||
serializer: { | ||
serialize: function(opcode, value, extras){ | ||
sn += 1; | ||
return { value: 'serialized', extras: extras }; | ||
}, | ||
deserialize: function (opcode, value, extras) { | ||
return { value: value, extras: extras }; | ||
} | ||
} | ||
}); | ||
var assertor = function(err, val) { | ||
t.equal(null, val); | ||
t.equal('MemJS SET: ' + errors[3], err.message); | ||
t.equal(1, n, 'Ensure set is called'); | ||
t.equal(1, sn, 'Ensure serialization is called once'); | ||
}; | ||
client.set('hello', 'world', {}, assertor); | ||
n = 0; | ||
sn = 0; | ||
return client.set('hello', 'world', {}).catch(function(err) { | ||
assertor(err, null); | ||
}); | ||
}); | ||
test('AddSuccessful', function(t) { | ||
@@ -314,2 +409,42 @@ var n = 0; | ||
test('AddSerializer', function(t) { | ||
var n = 0; | ||
var sn = 0; | ||
var dummyServer = new MemJS.Server(); | ||
dummyServer.write = function(requestBuf) { | ||
var request = MemJS.Utils.parseMessage(requestBuf); | ||
t.equal('hello', request.key.toString()); | ||
t.equal('serialized', request.val.toString()); | ||
t.equal('0000000100000400', request.extras.toString('hex')); | ||
n += 1; | ||
dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); | ||
}; | ||
var client = new MemJS.Client([dummyServer], { | ||
expires: 1024, | ||
serializer: { | ||
serialize: function(opcode, value, extras){ | ||
sn += 1; | ||
extras.writeUInt32BE(1, 0); | ||
return { value: 'serialized', extras: extras }; | ||
}, | ||
deserialize: function (opcode, value, extras) { | ||
return { value: value, extras: extras }; | ||
} | ||
} | ||
}); | ||
var assertor = function(err, val) { | ||
t.equal(null, err); | ||
t.equal(true, val); | ||
t.equal(1, n, 'Ensure add is called'); | ||
t.equal(1, sn, 'Ensure serialization is called once'); | ||
}; | ||
client.add('hello', 'world', {}, assertor); | ||
n = 0; | ||
sn = 0; | ||
return client.add('hello', 'world', {}).then(function(success) { | ||
assertor(null, success); | ||
}); | ||
}); | ||
test('ReplaceSuccessful', function(t) { | ||
@@ -734,2 +869,28 @@ var n = 0; | ||
}); | ||
test('Very Large Client Seq', function(t) { | ||
var n = 0; | ||
var dummyServer = new MemJS.Server(); | ||
dummyServer.write = function(requestBuf) { | ||
var request = MemJS.Utils.parseMessage(requestBuf); | ||
t.equal('hello', request.key.toString()); | ||
t.equal('world', request.val.toString()); | ||
t.equal('0000000000000400', request.extras.toString('hex')); | ||
n += 1; | ||
dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); | ||
}; | ||
var client = new MemJS.Client([dummyServer], {expires: 1024}); | ||
client.seq = Math.pow(2,33); | ||
var assertor = function(err, val) { | ||
t.equal(null, err); | ||
t.equal(true, val); | ||
t.equal(1, n, 'Ensure add is called'); | ||
}; | ||
client.add('hello', 'world', {}, assertor); | ||
n = 0; | ||
return client.add('hello', 'world', {}).then(function(success) { | ||
assertor(null, success); | ||
}); | ||
}); | ||
return; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
87675
20
2323