aerospike
Advanced tools
Comparing version 2.5.2 to 2.6.0
# Backward Incompatible API Changes | ||
## Version 2.6.0 | ||
### Deprecations | ||
| Deprecated Function | Replacement | Remarks | | ||
| ---------------------------- | ---------------------------------------------- | ------------------------------------------- | | ||
| `Infoy#parseInfo` | `Info#parse` | `parse` and `parseInfo` both parse the info data returned by the Aerospike server; there are some minor differences between the parsed data returned by the two functions for some info keys | | ||
| `Client#udfRegisterWait` | `UdfJob#waitUntilDone` | An `UdfJob` instance is passed to the client's `udfRegister`/`udfRemove` callback functions. | | ||
## Version 2.4.4 | ||
### Deprecation of LargeList Functionality | ||
Aerospike will no longer support the Large Data Type (LDT) feature so all | ||
LargeList related functions have been marked as deprecated. Please refer to | ||
[this article](http://www.aerospike.com/blog/aerospike-ldt/) on the Aerospike | ||
company blog for more details. | ||
### Deprecations | ||
| Deprecated Function | Replacement | Remarks | | ||
| ---------------------------- | ---------------------------------------------- | ------------------------------------------- | | ||
| `Client#LargeList` | - | see above | | ||
| `LargeList#*` | - | see above | | ||
## Version 2.4.0 | ||
@@ -390,1 +415,2 @@ | ||
| `Client#add` | `Client#incr` | - | | ||
:q |
@@ -21,3 +21,3 @@ ### The Node.js Cluster Module | ||
Each Aerospike client instance runs an extra cluster _tend_ thread that | ||
periodically polls the server nodes for cluster status. This is reuquired to, | ||
periodically polls the server nodes for cluster status. This is required to, | ||
among other things, maintain the data partition map, so that the client knows | ||
@@ -24,0 +24,0 @@ how to send database commands to the cluster node that holds the master replica |
@@ -18,4 +18,5 @@ { | ||
"yargs": ">=1.2.1", | ||
"sleep": "^3.0.0" | ||
"sleep": "^3.0.0", | ||
"deasync": "^0.1.4" | ||
} | ||
} |
@@ -24,4 +24,2 @@ // ***************************************************************************** | ||
const yargs = require('yargs') | ||
const path = require('path') | ||
const iteration = require('./iteration') | ||
@@ -82,7 +80,2 @@ // ***************************************************************************** | ||
describe: 'Password to connect to secured cluster' | ||
}, | ||
iterations: { | ||
alias: 'I', | ||
default: 1, | ||
describe: 'Number of iterations' | ||
} | ||
@@ -106,4 +99,2 @@ }) | ||
iteration.setLimit(argv.iterations) | ||
// ***************************************************************************** | ||
@@ -134,7 +125,7 @@ // Configure the client. | ||
function run (client, done) { | ||
client.udfRegister(file, function (err) { | ||
client.udfRegister(file, function (err, job) { | ||
if (err) throw err | ||
client.udfRegisterWait(path.basename(file), 1000, function (err) { | ||
job.waitUntilDone(function (err) { | ||
if (err) throw err | ||
!argv.quiet && console.log('UDF Registration Successful - %s', file) | ||
!argv.quiet && console.log('UDF module registered successfully: %s', file) | ||
done() | ||
@@ -141,0 +132,0 @@ }) |
@@ -24,3 +24,2 @@ // ***************************************************************************** | ||
const yargs = require('yargs') | ||
const iteration = require('./iteration') | ||
@@ -81,7 +80,2 @@ // ***************************************************************************** | ||
describe: 'Password to connect to secured cluster' | ||
}, | ||
iterations: { | ||
alias: 'I', | ||
default: 1, | ||
describe: 'Number of iterations' | ||
} | ||
@@ -105,4 +99,2 @@ }) | ||
iteration.setLimit(argv.iterations) | ||
// ***************************************************************************** | ||
@@ -133,6 +125,9 @@ // Configure the client. | ||
function run (client, done) { | ||
client.udfRemove(module, function (err) { | ||
client.udfRemove(module, function (err, job) { | ||
if (err) throw err | ||
!argv.quiet && console.log('OK.') | ||
iteration.next(run, client, done) | ||
job.waitUntilDone(function (err) { | ||
if (err) throw err | ||
!argv.quiet && console.log('UDF module removed successfully: %s', module) | ||
done() | ||
}) | ||
}) | ||
@@ -139,0 +134,0 @@ } |
@@ -0,1 +1,14 @@ | ||
v2.6.0 / 2017-05-25 | ||
=================== | ||
* **New Features** | ||
* Expose new consistency level in batch policy [#197](https://github.com/aerospike/aerospike-client-nodejs/pull/197) | ||
* Add interface to dynamically add/remove seed hosts [#194](https://github.com/aerospike/aerospike-client-nodejs/pull/194) | ||
* New UDF register/unregister job to async wait for job completion [#198](https://github.com/aerospike/aerospike-client-nodejs/pull/198) | ||
* Improved Info.parse() function, replacing Info.parseInfo() | ||
* **Updates** | ||
* Update C client library to [v4.1.6](http://www.aerospike.com/download/client/c/notes.html#4.1.6). | ||
* The Client#udfRegisterWait and Info#parseInfo functions have been marked deprecated. See [API Changes](https://github.com/aerospike/aerospike-client-nodejs/blob/master/docs/api-changes.md) for details. | ||
v2.5.2 / 2017-04-20 | ||
@@ -2,0 +15,0 @@ =================== |
@@ -123,2 +123,4 @@ // ***************************************************************************** | ||
this.port = config.port | ||
} else { | ||
this.port = 3000 | ||
} | ||
@@ -125,0 +127,0 @@ |
@@ -93,3 +93,3 @@ // ***************************************************************************** | ||
} else { | ||
info = Info.parseInfo(info) | ||
info = Info.parse(info) | ||
sindexInfo.push(info[sindex] || {load_pct: 0}) | ||
@@ -96,0 +96,0 @@ } |
236
lib/info.js
@@ -20,5 +20,15 @@ // ***************************************************************************** | ||
* | ||
* @description Utility methods for dealing with info data returned by Aerospike cluster nodes. | ||
* @description The info protocol provides access to configuration and | ||
* statistics for the Aerospike server. This module provides the {@link | ||
* module:aerospike/info.parse|parse} utility function for parsing the info | ||
* data returned by the Aerospike server. | ||
* | ||
* **Note:** The {@link module:aerospike/info.parseInfo|parseInfo} function is | ||
* deprecated since v2.6; the new {@link module:aerospike/info.parse|parse} | ||
* function should be used instead. The two functions do the same thing but | ||
* <code>parse()<code> uses customized parsing logic for some info keys and | ||
* therefore can return different results from <code>parseInfo</code>. | ||
* | ||
* @see {@link Client#info} | ||
* @see <a href="http://www.aerospike.com/docs/reference/info" title="Info Command Reference">⇑Info Command Reference</a> | ||
* | ||
@@ -31,9 +41,12 @@ * @example | ||
* | ||
* var infoCb = function (error, infoStr) { | ||
* if (error) { | ||
* console.error('error retrieving info: %s', error.message) | ||
* var cmd = 'build\nfeatures' | ||
* client.infoAny(cmd, (err, infoStr) => { | ||
* if (err) { | ||
* console.error('error retrieving info for cmd "%s": %s [%d]', | ||
* cmd, err.message, err.code) | ||
* } else { | ||
* var info = Aerospike.info.parseInfo(infoStr) | ||
* console.log(info) // => { features: | ||
* // [ 'cdt-list', | ||
* var info = Aerospike.info.parse(infoStr) | ||
* console.log(info) // => { build: '3.12.0', | ||
* // features: [ | ||
* // 'cdt-list', | ||
* // 'pipelining', | ||
@@ -44,7 +57,59 @@ * // 'geo', | ||
* } | ||
* } | ||
* client.info('features', infoCb, () => client.close()) | ||
* client.close() | ||
* }) | ||
* }) | ||
*/ | ||
/** | ||
* @function module:aerospike/info.parse | ||
* | ||
* @summary Parses the info string returned from a cluster node into key-value pairs. | ||
* | ||
* @param {string} info - The info string returned by the cluster node. | ||
* @returns {Object} key-value pairs | ||
* | ||
* @since v2.6 | ||
*/ | ||
function parse (info) { | ||
if (!info) return {} | ||
var infoHash = parseKeyValue(info, '\n', '\t') | ||
Object.keys(infoHash).forEach(function (key) { | ||
var separators = getSeparators(key) | ||
if (separators) { | ||
var value = infoHash[key] | ||
infoHash[key] = splitString(value, separators) | ||
} | ||
}) | ||
return infoHash | ||
} | ||
/** | ||
* @function module:aerospike/info.parseInfo | ||
* | ||
* @summary Parses the info string returned from a cluster node into key-value pairs. | ||
* | ||
* @param {string} info - The info string returned by the cluster node. | ||
* @returns {Object} key-value pairs | ||
* | ||
* @deprecated since v2.6 - use {@link module:aerospike/info.parse|parse} instead. | ||
*/ | ||
function parseInfoOld (info) { | ||
if (!info) return {} | ||
var infoHash = parseKeyValue(info, '\n', '\t') | ||
Object.keys(infoHash).forEach(function (key) { | ||
var value = infoHash[key] | ||
infoHash[key] = smartParse(value) | ||
}) | ||
return infoHash | ||
} | ||
/** | ||
* Parses a string value into a primitive type (string or number). | ||
* | ||
* Ex.: | ||
* - parseValue('foo') => 'foo' | ||
* - parseValue('42') => 42 | ||
* | ||
* @private | ||
*/ | ||
function parseValue (value) { | ||
@@ -57,2 +122,11 @@ if (Number(value).toString() === value) { | ||
/** | ||
* Parses a string value representing a key-value-map separated by sep1 and | ||
* sep2 into an Object. | ||
* | ||
* Ex.: | ||
* - parseKeyValue('a=1;b=2', ';', '=') => { a: 1, b: 2 } | ||
* | ||
* @private | ||
*/ | ||
function parseKeyValue (str, sep1, sep2) { | ||
@@ -70,28 +144,140 @@ var result = {} | ||
/** | ||
* @function module:aerospike/info.parseInfo | ||
* Split string into list or key-value-pairs depending on whether | ||
* the given separator chars appear in the string. This is the logic used by | ||
* the old parseInfo function and the default logic used by the new parse | ||
* function unless a specific format is defined for an info key. | ||
* | ||
* @summary Parses the info string returned from a cluster node into key-value pairs. | ||
* Ex.: | ||
* - smartParse('foo') => 'foo' | ||
* - smartParse('foo;bar') => ['foo', 'bar'] | ||
* - smartParse('foo=1;bar=2') => {foo: 1, bar: 2} | ||
* | ||
* @param {string} info - The info string returned by the cluster node. | ||
* @returns {Object} key-value pairs | ||
* @private | ||
*/ | ||
function parseInfo (info) { | ||
if (!info) return {} | ||
var infoHash = parseKeyValue(info, '\n', '\t') | ||
Object.keys(infoHash).forEach(function (key) { | ||
var value = infoHash[key] | ||
if ((typeof value === 'string') && value.indexOf(';') >= 0) { | ||
if (value.indexOf('=') >= 0) { | ||
value = parseKeyValue(value, ';', '=') | ||
function smartParse (str, sep1, sep2) { | ||
sep1 = sep1 || ';' | ||
sep2 = sep2 || '=' | ||
if ((typeof str === 'string') && str.indexOf(sep1) >= 0) { | ||
if (str.indexOf(sep2) >= 0) { | ||
return parseKeyValue(str, sep1, sep2) | ||
} else { | ||
return str.split(sep1) | ||
} | ||
} | ||
return str | ||
} | ||
/** | ||
* Normalizes the key name in an info hash by turning a parameterized key into | ||
* a unique key name. | ||
* | ||
* Ex.: | ||
* - normalizeKey('sindex/test/idx-name') => 'sindex-stats' | ||
* | ||
* @private | ||
*/ | ||
function normalizeKey (key) { | ||
if (key.startsWith('sindex')) { | ||
return key.split('/').length === 3 ? 'sindex-stats' : 'sindex-list' | ||
} else if (key.startsWith('bins/')) { | ||
return 'bins-ns' | ||
} else if (key.startsWith('namespace/')) { | ||
return 'namespace' | ||
} | ||
return key | ||
} | ||
/** | ||
* Returns separators to use for the given info key. | ||
* | ||
* @private | ||
*/ | ||
function getSeparators (key) { | ||
var name = normalizeKey(key) | ||
var separators = SEPARATORS[name] || DEFAULT_SEPARATORS | ||
return separators | ||
} | ||
/** | ||
* Splits a string into a, possibly nested, array or object using the given | ||
* separators. | ||
* | ||
* @private | ||
*/ | ||
function splitString (str, separators) { | ||
if (separators.length === 0) { | ||
return str | ||
} | ||
var sep = separators[0] | ||
switch (typeof sep) { | ||
case 'function': | ||
return sep(str) | ||
case 'string': | ||
if (sep.length === 2) { | ||
var map = parseKeyValue(str, sep[0], sep[1]) | ||
Object.keys(map).forEach(function (key) { | ||
var value = map[key] | ||
map[key] = splitString(value, separators.slice(1)) | ||
}) | ||
return map | ||
} else { | ||
value = value.split(';') | ||
var list = str.split(sep) | ||
if (list.slice(-1)[0].length === 0) { | ||
list.pop() | ||
} | ||
return list.map(function (e) { | ||
return splitString(e, separators.slice(1)) | ||
}) | ||
} | ||
infoHash[key] = value | ||
} | ||
} | ||
/** | ||
* Separators to use for specific info keys. A single-char separator splits the | ||
* info value into a list of strings; a separator consisting of two characters | ||
* splits the info value into a list of key-value-pairs. For keys containing | ||
* nested key-value-lists, multiple separators can be specified. For info keys | ||
* that require more complex parsing logic, a split function can | ||
* be specified instead of a character separator. | ||
* | ||
* @private | ||
*/ | ||
const SEPARATORS = { | ||
'bins': [';:', splitBins], | ||
'bins-ns': [splitBins], | ||
'namespace': [';='], | ||
'service': [';'], | ||
'sindex-list': [';', ':='], | ||
'statistics': [';='], | ||
'udf-list': [';', ',='], | ||
'udf-stats': [';='] | ||
} | ||
const DEFAULT_SEPARATORS = [smartParse] | ||
/********************************************************** | ||
* Functions for dealing with specific info command results | ||
**********************************************************/ | ||
function splitBins (str) { | ||
var stats = {} | ||
var names = [] | ||
str.split(',').forEach(function (elem) { | ||
var parts = elem.split('=', 2) | ||
if (parts.length === 2) { | ||
stats[parts[0]] = parts[1] | ||
} else { | ||
names.push(parts[0]) | ||
} | ||
}) | ||
return infoHash | ||
return { | ||
stats: stats, | ||
names: names | ||
} | ||
} | ||
module.exports = { | ||
parseInfo: parseInfo | ||
parse: parse, | ||
// deprecated - use parse() instead | ||
parseInfo: parseInfoOld | ||
} |
{ | ||
"name": "aerospike", | ||
"version": "2.5.2", | ||
"version": "2.6.0", | ||
"description": "Aerospike Client Library", | ||
@@ -33,3 +33,4 @@ "tags": [ | ||
"apidocs": "jsdoc -c jsdoc.json", | ||
"preversion": "npm test" | ||
"preversion": "npm test", | ||
"cppcheck": "cppcheck --quiet --enable=warning,style -I src/include src/main/" | ||
}, | ||
@@ -44,3 +45,2 @@ "dependencies": { | ||
"standard": "^9.0", | ||
"deasync": "^0.1.4", | ||
"jsdoc": "^3.4.0", | ||
@@ -47,0 +47,0 @@ "ink-docstrap": "^1.1.0" |
@@ -12,4 +12,6 @@ # Aerospike Node.js Client [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] | ||
This module is compatible with Node.js v0.12.x, io.js, v4.x, v5.x, v6.x and supports the following operating systems: | ||
CentOS/RHEL 6+, Debian 7/8, Ubuntu 12.04+, Fedora 20+, Korora 22+, Linuxmint and Mac OS X. | ||
This module is compatible with Node.js v4.x (LTS), v6.x (LTS) and v7.x. It | ||
supports the following operating systems: CentOS/RHEL 6/7, Debian 7/8, | ||
Ubuntu 12.04/14.04/16.04, as well as many Linux destributions compatible with | ||
one of these OS releases and macOS. | ||
@@ -16,0 +18,0 @@ - [Usage](#Usage) |
@@ -21,3 +21,2 @@ // ***************************************************************************** | ||
const AerospikeError = require('../lib/aerospike_error') | ||
const Info = require('../lib/info') | ||
const Job = require('../lib/job') | ||
@@ -53,11 +52,4 @@ const IndexJob = require('../lib/index_job') | ||
} | ||
} else if (info.length > 0) { | ||
var done = info.every(function (response) { | ||
var stats = Info.parseInfo(response.info)[sindex] | ||
var noIndexErr = (typeof stats === 'string') && (stats.indexOf('FAIL:201:NO INDEX') >= 0) | ||
return !noIndexErr | ||
}) | ||
callback(null, done) | ||
} else { | ||
callback(null, false) | ||
callback(null, true) | ||
} | ||
@@ -64,0 +56,0 @@ }) |
@@ -111,6 +111,6 @@ // ***************************************************************************** | ||
describe('info.parseInfo()', function () { | ||
describe('info.parse()', function () { | ||
it('should parse key-value pairs from an info string', function () { | ||
var infoStr = 'version\t1\nedition\tCommunity Edition\n' | ||
var infoHash = info.parseInfo(infoStr) | ||
var infoHash = info.parse(infoStr) | ||
expect(infoHash).to.eql({version: 1, edition: 'Community Edition'}) | ||
@@ -121,3 +121,3 @@ }) | ||
var infoStr = 'statistics\tmem=10;req=20\n' | ||
var infoHash = info.parseInfo(infoStr) | ||
var infoHash = info.parse(infoStr) | ||
expect(infoHash['statistics']).to.eql({mem: 10, req: 20}) | ||
@@ -128,3 +128,3 @@ }) | ||
var infoStr = 'features\tgeo;double\n' | ||
var infoHash = info.parseInfo(infoStr) | ||
var infoHash = info.parse(infoStr) | ||
expect(infoHash['features']).to.eql(['geo', 'double']) | ||
@@ -135,3 +135,3 @@ }) | ||
var infoStr = 'version\t1' | ||
var infoHash = info.parseInfo(infoStr) | ||
var infoHash = info.parse(infoStr) | ||
expect(infoHash['version']).to.be.a('number') | ||
@@ -142,5 +142,20 @@ }) | ||
var infoStr = '' | ||
var infoHash = info.parseInfo(infoStr) | ||
var infoHash = info.parse(infoStr) | ||
expect(infoHash).to.eql({}) | ||
}) | ||
it('should parse the udf-list info key', function () { | ||
var infoStr = 'udf-list\tfilename=mod1.lua,hash=00557374fc319b8d0f38c6668015db35358d7b62,type=LUA;filename=mod2.lua,hash=c96771bd8ce6911a22a592e4857fd47082f14990,type=LUA;' | ||
var infoHash = info.parse(infoStr) | ||
expect(infoHash['udf-list']).to.eql([ | ||
{ filename: 'mod1.lua', hash: '00557374fc319b8d0f38c6668015db35358d7b62', type: 'LUA' }, | ||
{ filename: 'mod2.lua', hash: 'c96771bd8ce6911a22a592e4857fd47082f14990', type: 'LUA' } | ||
]) | ||
}) | ||
it('should parse the bins info key', function () { | ||
var infoStr = 'bins\ttest:bin_names=2,bin_names_quota=32768,bin1,bin2;' | ||
var infoHash = info.parse(infoStr) | ||
expect(infoHash['bins']).to.eql({ test: { names: ['bin1', 'bin2'], stats: { bin_names: 2, bin_names_quota: 32768 } } }) | ||
}) | ||
}) |
@@ -49,6 +49,5 @@ // ***************************************************************************** | ||
var script = path.join(__dirname, filename) | ||
var self = this | ||
this.client.udfRegister(script, function (err) { | ||
this.client.udfRegister(script, function (err, job) { | ||
if (err) throw err | ||
self.client.udfRegisterWait(filename, 50, function (err) { | ||
job.waitUntilDone(50, function (err) { | ||
if (err) throw err | ||
@@ -61,5 +60,8 @@ callback() | ||
UDFHelper.prototype.remove = function (filename, callback) { | ||
this.client.udfRemove(filename, function (err) { | ||
this.client.udfRemove(filename, function (err, job) { | ||
if (err && err.code !== Aerospike.status.AEROSPIKE_ERR_UDF) throw err | ||
callback() | ||
job.waitUntilDone(50, function (err) { | ||
if (err) throw err | ||
callback() | ||
}) | ||
}) | ||
@@ -126,3 +128,3 @@ } | ||
results.forEach(function (response) { | ||
var info = Info.parseInfo(response.info) | ||
var info = Info.parse(response.info) | ||
self.edition = info['edition'] | ||
@@ -147,3 +149,3 @@ self.build = info['build'] | ||
var info = results.pop()['info'] | ||
self.nsconfig = Info.parseInfo(info)[nsKey] | ||
self.nsconfig = Info.parse(info)[nsKey] | ||
done() | ||
@@ -156,3 +158,3 @@ }) | ||
if (err) throw err | ||
var service = Info.parseInfo(response).service | ||
var service = Info.parse(response).service | ||
if (Array.isArray(service)) { | ||
@@ -159,0 +161,0 @@ service = service.pop() |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
1442482
6
19180
443