Comparing version 4.2.1 to 4.2.2
# node-influx Changelog | ||
## 2016-09-15, Version 4.2.2 | ||
Shoutout to @dandv for lots of awesome PRs this release! | ||
* improvement: sort tags before writing for greater performance (#179) | ||
* improvement: make code compliant with the latest `standard` rules (#161) | ||
* bug: fix escaping of quotes in strings (#183) | ||
* bug: fix empty result from `getDatabaseNames` throwing errors (#168) | ||
* docs: fix messy terminology and typos (#183 and #170) | ||
* docs: include the full license file and copyright (#180) | ||
* docs: fix instructions to run `standard` instead of just `lint` (#181) | ||
## 2016-05-05, Version 4.2.0 | ||
### Notable changes | ||
### Notable changes | ||
@@ -7,0 +19,0 @@ * typings: Added TypeScript definitions, thanks to @SPARTAN563 (#129) |
53
index.js
@@ -19,2 +19,12 @@ var InfluxRequest = require('./lib/InfluxRequest.js') | ||
/** | ||
* Backslash-escape commas, equal signs and spaces per | ||
* https://docs.influxdata.com/influxdb/v1.0/write_protocols/line_protocol_tutorial/#special-characters-and-keywords | ||
* @param {string} s | ||
* @returns {string} | ||
*/ | ||
function escape (s) { | ||
return s.replace(/[ ,=]/g, '\\$&') | ||
} | ||
function parseOptionsUrl (url_) { | ||
@@ -107,3 +117,3 @@ var parsed = url.parse(url_) | ||
if (_.isObject(body) && body.results && _.isArray(body.results)) { | ||
for (var i = 0;i <= body.results.length;++i) { | ||
for (var i = 0; i <= body.results.length; ++i) { | ||
if (body.results[i] && body.results[i].error && body.results[i].error !== '') { | ||
@@ -179,3 +189,13 @@ return callback(new Error(body.results[i].error)) | ||
} | ||
return callback(err, _.map(results[0].series[0].values, function (dbarray) {return dbarray[0]})) | ||
var names = _.get(results, '[0].series[0].values') | ||
if (!_.isArray(names)) { | ||
return callback(new Error('bad response from server', results)) | ||
} | ||
callback(null, names.map(function (dbarray) { | ||
if (_.isArray(dbarray)) { | ||
return dbarray[0] | ||
} | ||
})) | ||
}) | ||
@@ -208,3 +228,3 @@ } | ||
.flattenDepth(2) | ||
.map(function (value) {return value.split(',', 1)[0]}) | ||
.map(function (value) { return value.split(',', 1)[0] }) | ||
.uniq() | ||
@@ -218,3 +238,2 @@ .value() | ||
}) | ||
} | ||
@@ -238,3 +257,2 @@ | ||
}) | ||
} | ||
@@ -306,5 +324,5 @@ | ||
if (typeof value === 'string') { | ||
output.push(key + '="' + value + '"') | ||
output.push(escape(key) + '="' + value.replace(/"/g, '\\"') + '"') // For string field values use a backslash character to escape double quotes | ||
} else { | ||
output.push(key + '=' + value) | ||
output.push(escape(key) + '=' + value) | ||
} | ||
@@ -315,2 +333,8 @@ }) | ||
/** | ||
* Return a sorted string of comma-separated key=value tags, with escaped values | ||
* @param object | ||
* @returns {string} | ||
* @private | ||
*/ | ||
InfluxDB.prototype._createKeyTagString = function (object) { | ||
@@ -320,8 +344,9 @@ var output = [] | ||
if (typeof value === 'string') { | ||
output.push(key + '=' + value.replace(/ /g, '\\ ').replace(/,/g, '\\,').replace(/=/g, '\\=')) | ||
output.push(escape(key) + '=' + escape(value)) | ||
} else { | ||
output.push(key + '=' + value) | ||
output.push(escape(key) + '=' + value) | ||
} | ||
}) | ||
return output.join(',') | ||
// "For best performance you should sort tags by key before sending them to the database." | ||
return output.sort().join(',') | ||
} | ||
@@ -332,4 +357,4 @@ | ||
var output = [] | ||
_.forEach(series, function (values, seriesName) { | ||
_.each(values, function (points) { | ||
_.forEach(series, function (fields, seriesName) { | ||
_.each(fields, function (points) { | ||
var line = seriesName.replace(/ /g, '\\ ').replace(/,/g, '\\,') | ||
@@ -384,4 +409,4 @@ if (points[1] && _.isObject(points[1]) && _.keys(points[1]).length > 0) { | ||
InfluxDB.prototype.writePoint = function (seriesName, values, tags, options, callback) { | ||
this.writePoints(seriesName, [[values, tags]], options, callback) | ||
InfluxDB.prototype.writePoint = function (seriesName, fields, tags, options, callback) { | ||
this.writePoints(seriesName, [[fields, tags]], options, callback) | ||
} | ||
@@ -388,0 +413,0 @@ |
@@ -90,6 +90,6 @@ var request = require('request') | ||
return url.format({ | ||
protocol: host.protocol, | ||
hostname: host.name, | ||
port: host.port | ||
}) + '/' + path | ||
protocol: host.protocol, | ||
hostname: host.name, | ||
port: host.port | ||
}) + '/' + path | ||
} | ||
@@ -124,3 +124,2 @@ | ||
return callback(err, response, body) | ||
} | ||
@@ -127,0 +126,0 @@ |
{ | ||
"name": "influx", | ||
"version": "4.2.1", | ||
"version": "4.2.2", | ||
"description": "InfluxDB Client", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
183
README.md
@@ -29,3 +29,3 @@ # node-influx | ||
Version 3.x.x is compatible with InfluxDB 0.8.x - 3.x will no longer have updates by core contributers, please consider upgrading. | ||
Version 3.x.x is compatible with InfluxDB 0.8.x - 3.x will no longer have updates by core contributors, please consider upgrading. | ||
@@ -43,16 +43,16 @@ | ||
//cluster configuration | ||
hosts : [ | ||
hosts: [ | ||
{ | ||
host : 'localhost', | ||
port : 8060, //optional. default 8086 | ||
protocol : 'http' //optional. default 'http' | ||
host: 'localhost', | ||
port: 8060, //optional. default 8086 | ||
protocol: 'http' //optional. default 'http' | ||
} | ||
], | ||
// or single-host configuration | ||
host : 'localhost', | ||
port : 8086, // optional, default 8086 | ||
protocol : 'http', // optional, default 'http' | ||
username : 'dbuser', | ||
password : 'f4ncyp4ass', | ||
database : 'my_database' | ||
host: 'localhost', | ||
port: 8086, // optional, default 8086 | ||
protocol: 'http', // optional, default 'http' | ||
username: 'dbuser', | ||
password: 'f4ncyp4ass', | ||
database: 'my_database' | ||
}) | ||
@@ -95,8 +95,8 @@ | ||
| protocol [optional] | protocol, default: http | | ||
| hosts [optional] | Array of hosts for cluster configuration, e.g. [ {host: 'localhost', port : 8086},...] Port is optional | | ||
| hosts [optional] | Array of hosts for cluster configuration, e.g. [ {host: 'localhost', port: 8086},...] Port is optional | | ||
| depreciatedLogging [optional] | logging function for depreciated warnings, defaults to console.log | | ||
| failoverTimeout [optional] | number of ms node-influx will take a host out of the balancing after a request failed, default: 60000 | | ||
| requestTimeout [optional] | number of ms to wait before a request times out. defaults to 'null' (waits until connection is closed). Use with caution! | | ||
| maxRetries [options] | max number of retries until a request raises an error (e.g. 'no hosts available'), default : 2 | | ||
| timePrecision [optional] |Time precision, default : ms | | ||
| maxRetries [options] | max number of retries until a request raises an error (e.g. 'no hosts available'), default: 2 | | ||
| timePrecision [optional] |Time precision, default: ms | | ||
@@ -129,3 +129,3 @@ | ||
```js | ||
getHostsAvailable( ) | ||
getHostsAvailable( ) | ||
``` | ||
@@ -144,3 +144,3 @@ | ||
```js | ||
client.createDatabase(databaseName, function(err, result) {} ) | ||
client.createDatabase(databaseName, function (err, result) { }) | ||
``` | ||
@@ -153,3 +153,3 @@ | ||
```js | ||
client.getDatabaseNames( function(err,arrayDatabaseNames){ } ) | ||
client.getDatabaseNames(function (err, arrayDatabaseNames) { }) | ||
``` | ||
@@ -161,3 +161,3 @@ | ||
```js | ||
dropDatabase ( databaseName, function(err,response) { }) | ||
dropDatabase (databaseName, function (err, response) { }) | ||
``` | ||
@@ -170,3 +170,3 @@ | ||
```js | ||
client.getMeasurements(function(err,arrayMeasurements){ } ) | ||
client.getMeasurements(function (err, arrayMeasurements) { }) | ||
``` | ||
@@ -179,3 +179,3 @@ | ||
```js | ||
dropSeries ( measurementName, function(err,response) { }) | ||
dropSeries (measurementName, function (err, response) { }) | ||
``` | ||
@@ -188,3 +188,3 @@ | ||
```js | ||
client.getSeries([measurementName], function(err,arraySeriesNames){} ) | ||
client.getSeries([measurementName], function (err, arraySeriesNames) { }) | ||
``` | ||
@@ -196,3 +196,3 @@ | ||
```js | ||
client.getSeriesNames([measurementName], function(err,arraySeriesNames){} ) { } | ||
client.getSeriesNames([measurementName], function (err, arraySeriesNames) { }) | ||
``` | ||
@@ -205,3 +205,3 @@ | ||
```js | ||
dropSeries ( seriesId, function(err,response) { }) | ||
dropSeries (seriesId, function (err, response) { }) | ||
``` | ||
@@ -222,3 +222,3 @@ | ||
```js | ||
client.createUser(username, password, isAdmin, function(err,response) { }) | ||
client.createUser(username, password, isAdmin, function (err, response) { }) | ||
``` | ||
@@ -230,3 +230,3 @@ | ||
```js | ||
client.setPassword(username, password, function (err, reponse) {} ) | ||
client.setPassword(username, password, function (err, response) { }) | ||
``` | ||
@@ -239,3 +239,3 @@ | ||
```js | ||
client.grantPrivilege(privilege, databaseName, userName, function (err, reponse) {} ) | ||
client.grantPrivilege(privilege, databaseName, userName, function (err, response) { }) | ||
``` | ||
@@ -247,3 +247,3 @@ | ||
```js | ||
client.revokePrivilege(privilege, databaseName, userName, function (err, reponse) {} ) | ||
client.revokePrivilege(privilege, databaseName, userName, function (err, response) { }) | ||
``` | ||
@@ -255,3 +255,3 @@ | ||
```js | ||
client.grantAdminPrivileges(userName, function (err, reponse) {} ) | ||
client.grantAdminPrivileges(userName, function (err, response) { }) | ||
``` | ||
@@ -263,3 +263,3 @@ | ||
```js | ||
client.revokeAdminPrivileges(userName, function (err, reponse) {} ) | ||
client.revokeAdminPrivileges(userName, function (err, response) { }) | ||
``` | ||
@@ -270,3 +270,3 @@ | ||
```js | ||
client.dropUser(userName, function(err,response) {] ) | ||
client.dropUser(userName, function (err, response) { }) | ||
``` | ||
@@ -279,9 +279,10 @@ | ||
```js | ||
var point = { attr : value, time : new Date()}; | ||
client.writePoint(seriesName, values, tags, [options], function(err, response) { }) | ||
client.writePoint(seriesName, values, tags, [options], function (err) { }) | ||
``` | ||
`values` can be either an objekt or a single value. For the latter the columname is set to `value`. | ||
You can set the time by passing an object propety called `time`. The time an be either an integer value or a Date object. When providing a single value, don't forget to adjust the time precision accordingly. The default value is `ms`. | ||
`values` can be either an object or a single value. In the latter case, the field key is set to `value`. | ||
You can set the time by passing an object property called `time`. The time can be either an integer value or a Date object. When providing a single value, don't forget to adjust the time precision accordingly. The default value is `ms`. | ||
The `tags` will be automatically sorted, for maximum write throughput performance. | ||
The parameter `options` is an optional and can have following fields: | ||
@@ -296,9 +297,9 @@ - `db`: Database to work with | ||
//write a single point with two values and two tags. time is omitted | ||
client.writePoint(info.series.name, {value: 232, value2: 123}, { foo: 'bar', foobar: 'baz'}, done) | ||
client.writePoint(info.series.name, {value: 232, value2: 123}, {foo: 'bar', foobar: 'baz'}, done) | ||
//write a single point with the value "1". The value "1" corresponds to { value : 1 } | ||
client.writePoint(info.series.name, 1, { foo: 'bar', foobar: 'baz'}, done) | ||
//write a single point with the value "1". The value "1" corresponds to {value: 1} | ||
client.writePoint(info.series.name, 1, {foo: 'bar', foobar: 'baz'}, done) | ||
//write a single point, providing an integer timestamp and time precision 's' for seconds | ||
client.writePoint(info.series.name, {time: 1234567890, value: 232}, null, {precision : 's'}, done) | ||
client.writePoint(info.series.name, {time: 1234567890, value: 232}, null, {precision: 's'}, done) | ||
@@ -314,15 +315,19 @@ //write a single point, providing a Date object. Precision is set to default 'ms' for milliseconds. | ||
`Points` is an array of points. Each point containing two objects - the actual values and tags. | ||
```js | ||
client.writePoints(seriesName, points, [options], function (err) { }) | ||
``` | ||
`Points` is an array of points. Each point is an array of two objects - the [field set](https://docs.influxdata.com/influxdb/v1.0/write_protocols/line_protocol_tutorial/#field-set), and the [tag set](https://docs.influxdata.com/influxdb/v1.0/write_protocols/line_protocol_tutorial/#tag-set). If you want to add a timestamp, add a `time` key in the first object. (We're looking for input on this API - see [#182](https://github.com/node-influx/node-influx/issues/182).) | ||
```js | ||
var points = [ | ||
//first value with tag | ||
[{value: 232}, { tag: 'foobar'}], | ||
//second value with different tag | ||
[{value: 212}, { someothertag: 'baz'}], | ||
//third value, passed as integer. Different tag | ||
[123, { foobar: 'baz'}], | ||
//value providing timestamp, without tags | ||
[{value: 122, time : new Date()}] | ||
] | ||
client.writePoints(seriesName, points, [options], callback) { } | ||
// One field with one tag | ||
[{value: 232}, {tag: 'foobar'}], | ||
// One field with two tags | ||
[{value: 212}, {tag1: 'baz', tag2: 'quux'}], | ||
// Field with just value (key defaults to 'value'). Different tag. | ||
[123, {foobar: 'baz'}], | ||
// Timestamp, one field, no tags | ||
[{value: 122, time: new Date()}] | ||
]; | ||
client.writePoints(seriesName, points, [options], callback) | ||
``` | ||
@@ -339,29 +344,29 @@ | ||
```js | ||
var points = [ | ||
//first value with tag | ||
[{value: 232}, { tag: 'foobar'}], | ||
//second value with different tag | ||
[{value: 212}, { someothertag: 'baz'}], | ||
//third value, passed as integer. Different tag | ||
[123, { foobar: 'baz'}], | ||
//value providing timestamp, without tags | ||
[{value: 122, time : new Date()}] | ||
var points1 = [ | ||
// One field with one tag | ||
[{value: 232}, {tag: 'foobar'}], | ||
// One field with two tags | ||
[{value: 212}, {tag1: 'baz', tag2: 'quux'}], | ||
// Field with just value (key defaults to 'value'). Different tag. | ||
[123, {foobar: 'baz'}], | ||
// Timestamp, one field, no tags | ||
[{value: 122, time: new Date()}] | ||
] | ||
var points2 = [ | ||
//first value with tag | ||
[{value: 1232}, { tag: 'foobar'}], | ||
//second value with different tag | ||
[{value: 223212}, { someothertag: 'baz'}], | ||
//third value, passed as integer. Different tag | ||
[12345, { foobar: 'baz'}], | ||
//value providing timestamp, without tags | ||
[{value: 23122, time : new Date()}] | ||
] | ||
// One field with one tag | ||
[{value: 1232}, {tag: 'foobar'}], | ||
// Another field with a different tag | ||
[{value: 223212}, {someothertag: 'baz'}], | ||
// Third field | ||
[12345, {foobar: 'baz'}], | ||
// Timestamp, one field, no tags | ||
[{value: 23122, time: new Date()}] | ||
]; | ||
var series = { | ||
series_name_one : points, | ||
series_name_two : points2 | ||
series_name_one: points1, | ||
series_name_two: points2 | ||
}; | ||
client.writeSeries(series, [options], function(err,response) { }) | ||
client.writeSeries(series, [options], function (err, response) { }) | ||
``` | ||
@@ -381,3 +386,3 @@ | ||
var query = 'SELECT MEDIAN(column) FROM myseries WHERE time > now() - 24h'; | ||
client.query([database], query, function(err, results) { }) | ||
client.query([database], query, function (err, results) { }) | ||
@@ -395,5 +400,5 @@ ``` | ||
// -> results =[ | ||
// [ { value : 1, tagname : 'tagvalue'}, {value : 3, othertag : 'value}], | ||
// [ {avgvalue : 2.345}] | ||
// -> results =[ | ||
// [ {value: 1, tagname: 'tagvalue'}, {value: 3, othertag: 'value}], | ||
// [ {avgvalue: 2.345}] | ||
// ] | ||
@@ -409,3 +414,3 @@ | ||
var query = 'SELECT MEDIAN(column) FROM myseries WHERE time > now() - 24h'; | ||
client.queryRaw([database], query, function(err, results) { }) | ||
client.queryRaw([database], query, function (err, results) { }) | ||
@@ -419,3 +424,3 @@ ``` | ||
```js | ||
client.createContinuousQuery('testQuery', 'SELECT COUNT(value) INTO valuesCount_1h FROM ' + info.series.name + ' GROUP BY time(1h) ', function (err, res) {} ) | ||
client.createContinuousQuery('testQuery', 'SELECT COUNT(value) INTO valuesCount_1h FROM ' + info.series.name + ' GROUP BY time(1h) ', function (err, results) {} ) | ||
``` | ||
@@ -427,3 +432,3 @@ | ||
```js | ||
getContinuousQueries( function(err,arrayContinuousQueries) { }) | ||
client.getContinuousQueries(function (err, arrayContinuousQueries) { }) | ||
``` | ||
@@ -435,3 +440,3 @@ | ||
```js | ||
dropContinuousQuery( queryName, [databaseName], callback) { } | ||
client.dropContinuousQuery(queryName, [databaseName], function (err, results) { }) | ||
``` | ||
@@ -445,3 +450,3 @@ | ||
```js | ||
client.getRetentionPolicies(databaseName, function(err,response) {} ) | ||
client.getRetentionPolicies(databaseName, function (err, response) { }) | ||
``` | ||
@@ -454,3 +459,3 @@ | ||
```js | ||
client.createRetentionPolicy(rpName, databaseName, duration, replication, isDefault, function(err,response) {} ) | ||
client.createRetentionPolicy(rpName, databaseName, duration, replication, isDefault, function (err, response) { }) | ||
``` | ||
@@ -460,3 +465,3 @@ | ||
```js | ||
client.createRetentionPolicy('my_ret_pol_name', 'my_database', '1d', 1, true, function (err,resonse) {}) | ||
client.createRetentionPolicy('my_ret_pol_name', 'my_database', '1d', 1, true, function (err, response) { }) | ||
``` | ||
@@ -469,3 +474,3 @@ | ||
```js | ||
client.alterRetentionPolicy(rpName, databaseName, duration, replication, isDefault, function(err,response) {} ) | ||
client.alterRetentionPolicy(rpName, databaseName, duration, replication, isDefault, function (err, response) { }) | ||
``` | ||
@@ -484,3 +489,3 @@ | ||
docker run -d -p 8083:8083 -p 8086:8086 --expose 8090 --expose 8099 tutum/influxdb | ||
docker run -d -p 8083:8083 -p 8086:8086 --expose 8090 --expose 8099 tutum/influxdb:0.13 | ||
@@ -491,13 +496,11 @@ Then to run the test harness use `npm test`. | ||
If you want to add features, fix bugs or improve node-influx please open a pull-request. | ||
Please note, we are following [Javascript Standard Style](https://github.com/feross/standard). Before opening a PR | ||
your code should pass Standard. | ||
If you want to add features, fix bugs or improve `node-influx`, please open a pull-request. | ||
Please note, we are following [Javascript Standard Style](https://github.com/feross/standard). | ||
Before opening a PR, your code should pass Standard: | ||
`npm install standard` | ||
`standard` | ||
npm run lint | ||
## License | ||
## Licence | ||
MIT |
935
test.js
/* eslint-env mocha */ | ||
var influx = require('./') | ||
var assert = require('assert') | ||
var request = require('request') | ||
before(function (done) { | ||
// Before doing anything validate that InfluxDB is a recent version and running | ||
request('http://localhost:8086/ping', function (err, response, body) { | ||
if (err) return done(err) | ||
var version = response.headers['x-influxdb-version'] | ||
var major = version.split('.')[0] | ||
var minor = version.split('.')[1] | ||
assert.equal(major, 0) | ||
assert(minor >= 13) | ||
done() | ||
}) | ||
}) | ||
describe('InfluxDB', function () { | ||
@@ -9,3 +24,2 @@ var client | ||
var failClient | ||
var failoverClient | ||
@@ -27,3 +41,3 @@ var info = { | ||
series: { | ||
name: 'response_time', | ||
numName: 'number_test', | ||
strName: 'string_test' | ||
@@ -33,2 +47,15 @@ } | ||
beforeEach(function (done) { | ||
client = influx({host: info.server.host, port: info.server.port, username: info.server.username, password: info.server.password, database: info.db.name, retentionPolicy: info.db.retentionPolicy}) | ||
assert(client instanceof influx.InfluxDB) | ||
failClient = influx({host: info.server.host, port: 6543, username: info.server.username, password: info.server.password, database: info.db.name}) | ||
assert(failClient instanceof influx.InfluxDB) | ||
dbClient = influx({host: info.server.host, port: info.server.port, username: info.server.username, password: info.server.password, database: info.db.name}) | ||
assert(dbClient instanceof influx.InfluxDB) | ||
done() | ||
}) | ||
describe('#InfluxDB', function () { | ||
@@ -41,17 +68,2 @@ it('should exist as a function (class)', function () { | ||
describe('create client', function () { | ||
it('should create an instance without error', function () { | ||
client = influx({host: info.server.host, port: info.server.port, username: info.server.username, password: info.server.password, database: info.db.name, retentionPolicy: info.db.retentionPolicy}) | ||
dbClient = influx({host: info.server.host, port: info.server.port, username: info.server.username, password: info.server.password, database: info.db.name}) | ||
failClient = influx({host: info.server.host, port: 6543, username: info.server.username, password: info.server.password, database: info.db.name}) | ||
failoverClient = influx({hosts: [ | ||
{host: '192.168.255.1'}, | ||
{host: '192.168.255.2'}, | ||
{host: '192.168.255.3'}, | ||
{host: '192.168.255.4'}, | ||
{host: info.server.host, port: info.server.port} | ||
], username: info.server.username, passwort: info.server.password, database: info.db.name}) | ||
assert(client instanceof influx.InfluxDB) | ||
}) | ||
describe('configured using URLs', function () { | ||
@@ -89,61 +101,52 @@ it('should parse it when passed as `options`', function () { | ||
describe('#setRequestTimeout', function () { | ||
it('should set the default request timeout value', function () { | ||
var timeout = failoverClient.setRequestTimeout(5000) | ||
assert.equal(timeout, 5000) | ||
}) | ||
}) | ||
describe('#noNetwork', function () { | ||
// Tests for library internals, do not send or recieve any data | ||
describe('#setFailoverTimeout', function () { | ||
it('should set the default request timeout value', function () { | ||
var timeout = failoverClient.setFailoverTimeout(2000) | ||
assert.equal(timeout, 2000) | ||
}) | ||
}) | ||
describe('#url', function () { | ||
it('should build a properly formatted url', function () { | ||
var url = client.url('query', { db: info.db.name, rp: info.db.retentionPolicy, precision: info.server.timePrecision }) | ||
assert.equal(url, /* 'http://'+info.server.host+':8086/' + */ 'query?u=' + info.server.username + '&p=' + info.server.password + '&db=' + info.db.name + '&rp=' + info.db.retentionPolicy + '&precision=' + info.server.timePrecision) | ||
}) | ||
describe('#url', function () { | ||
it('should build a properly formatted url', function () { | ||
var url = client.url('query', { db: info.db.name, rp: info.db.retentionPolicy, precision: info.server.timePrecision }) | ||
assert.equal(url, /* 'http://'+info.server.host+':8086/' + */ 'query?u=' + info.server.username + '&p=' + info.server.password + '&db=' + info.db.name + '&rp=' + info.db.retentionPolicy + '&precision=' + info.server.timePrecision) | ||
it('should build a properly formatted url', function () { | ||
var url = client.url('query') | ||
assert.equal(url, /* 'http://'+info.server.host+':8086/' + */ 'query?u=' + info.server.username + '&p=' + info.server.password + '&precision=' + info.server.timePrecision + '&db=' + info.db.name + '&rp=' + info.db.retentionPolicy) | ||
}) | ||
}) | ||
it('should build a properly formatted url', function () { | ||
var url = client.url('query') | ||
assert.equal(url, /* 'http://'+info.server.host+':8086/' + */ 'query?u=' + info.server.username + '&p=' + info.server.password + '&precision=' + info.server.timePrecision + '&db=' + info.db.name + '&rp=' + info.db.retentionPolicy) | ||
describe('#_createKeyTagString', function () { | ||
it('should build a properly formatted tags string', function () { | ||
var str = client._createKeyTagString({tag_1: 'value', tag2: 'value value', tag3: 'value,value'}) | ||
assert.equal(str, 'tag2=value\\ value,tag3=value\\,value,tag_1=value') // tags should be sorted | ||
}) | ||
}) | ||
}) | ||
describe('#_createKeyTagString', function () { | ||
it('should build a properly formatted string', function () { | ||
var str = client._createKeyTagString({tag_1: 'value', tag2: 'value value', tag3: 'value,value'}) | ||
assert.equal(str, 'tag_1=value,tag2=value\\ value,tag3=value\\,value') | ||
describe('#_createKeyValueString', function () { | ||
it('should build a properly formatted fieldset', function () { | ||
var str = client._createKeyValueString({a: 1, b: 2}) | ||
assert.equal(str, 'a=1,b=2') | ||
str = client._createKeyValueString({'temp=rature': 82, 'location place': 'us-midwest', 'comma, and quote': "'= "}) | ||
assert.equal(str, 'temp\\=rature=82,location\\ place="us-midwest",comma\\,\\ and\\ quote="\'= "') | ||
}) | ||
}) | ||
}) | ||
describe('#_createKeyValueString', function () { | ||
it('should build a properly formatted string', function () { | ||
var str = client._createKeyValueString({a: 1, b: 2}) | ||
assert.equal(str, 'a=1,b=2') | ||
describe('parseResult()', function () { | ||
it('should build a properly formatted response', function (done) { | ||
client._parseResults([{'series': [{'name': 'myseries2', 'tags': {'mytag': 'foobarfoo'}, 'columns': ['time', 'value'], 'values': [['2015-06-27T06:25:54.411900884Z', 55]]}, {'name': 'myseries2', 'tags': {'mytag': 'foobarfoo2'}, 'columns': ['time', 'value'], 'values': [['2015-06-27T06:25:54.411900884Z', 29]]}]}], | ||
function (err, results) { | ||
if (err) return done(err) | ||
assert.deepEqual(results, | ||
[ [ { time: '2015-06-27T06:25:54.411900884Z', | ||
value: 55, | ||
mytag: 'foobarfoo' }, | ||
{ time: '2015-06-27T06:25:54.411900884Z', | ||
value: 29, | ||
mytag: 'foobarfoo2' } ] ] | ||
) | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
describe('parseResult()', function () { | ||
it('should build a properly formatted response', function (done) { | ||
client._parseResults([{'series': [{'name': 'myseries2', 'tags': {'mytag': 'foobarfoo'}, 'columns': ['time', 'value'], 'values': [['2015-06-27T06:25:54.411900884Z', 55]]}, {'name': 'myseries2', 'tags': {'mytag': 'foobarfoo2'}, 'columns': ['time', 'value'], 'values': [['2015-06-27T06:25:54.411900884Z', 29]]}]}], | ||
function (err, results) { | ||
if (err) return done(err) | ||
assert.deepEqual(results, | ||
[ [ { time: '2015-06-27T06:25:54.411900884Z', | ||
value: 55, | ||
mytag: 'foobarfoo' }, | ||
{ time: '2015-06-27T06:25:54.411900884Z', | ||
value: 29, | ||
mytag: 'foobarfoo2' } ] ] | ||
) | ||
done() | ||
}) | ||
}) | ||
}) | ||
describe('#availableHosts', function () { | ||
@@ -167,9 +170,10 @@ it('should return one host', function (done) { | ||
describe('#createDatabase', function () { | ||
it('should create a new database without error', function (done) { | ||
client.createDatabase(info.db.name, done) | ||
}) | ||
it('should not throw an error if db already exists', function (done) { | ||
client.createDatabase(info.db.name, function (err) { | ||
done(err) | ||
describe('#disabledHosts', function () { | ||
it('should return failed host', function (done) { | ||
// Issue any request so that library disables a host | ||
failClient.getUsers(function () { | ||
var hosts = failClient.getHostsDisabled() | ||
assert.equal(hosts.length, 1) | ||
assert.equal(hosts[0].name, info.server.host) | ||
done() | ||
}) | ||
@@ -179,85 +183,130 @@ }) | ||
describe('#getDatabaseNames', function () { | ||
it('should return array of database names', function (done) { | ||
client.getDatabaseNames(function (err, dbs) { | ||
if (err) return done(err) | ||
assert(dbs instanceof Array) | ||
assert.notEqual(dbs.indexOf(info.db.name), -1) | ||
done() | ||
describe('#users', function () { | ||
describe('#createUser', function () { | ||
it('should create a user without error', function (done) { | ||
client.createUser(info.db.username, info.db.password, true, done) | ||
}) | ||
}) | ||
it('should bubble errors through', function (done) { | ||
failClient.getDatabaseNames(function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
it('should error when creating an existing user', function (done) { | ||
client.createUser(info.db.username, info.db.password, function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
}) | ||
}) | ||
after(function (done) { | ||
client.dropUser(info.db.username, done) | ||
}) | ||
}) | ||
}) | ||
describe('#disabledHosts', function () { | ||
it('should return failed host', function (done) { | ||
var hosts = failClient.getHostsDisabled() | ||
assert.equal(hosts.length, 1) | ||
assert.equal(hosts[0].name, info.server.host) | ||
done() | ||
describe('#dropUser', function () { | ||
before(function (done) { | ||
client.createUser(info.db.username, info.db.password, true, done) | ||
}) | ||
it('should delete a user without error', function (done) { | ||
client.dropUser(info.db.username, done) | ||
}) | ||
it('should error when deleting a user that does not exist', function (done) { | ||
client.dropUser(info.db.username, function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
describe('#createUser', function () { | ||
it('should create a user without error', function (done) { | ||
client.createUser(info.db.username, info.db.password, true, done) | ||
}) | ||
it('should error when creating an existing user', function (done) { | ||
client.createUser(info.db.username, info.db.password, function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
describe('#withExistingUser', function () { | ||
beforeEach(function (done) { | ||
client.createUser(info.db.username, info.db.password, true, done) | ||
}) | ||
}) | ||
}) | ||
afterEach(function (done) { | ||
client.dropUser(info.db.username, done) | ||
}) | ||
describe('#getUsers', function () { | ||
it('should get an array of database users', function (done) { | ||
client.getUsers(function (err, users) { | ||
assert.equal(err, null) | ||
assert(users instanceof Array) | ||
assert.equal(users.length, 1) | ||
done() | ||
describe('#getUsers', function () { | ||
it('should get an array of database users', function (done) { | ||
client.getUsers(function (err, users) { | ||
assert.equal(err, null) | ||
assert(users instanceof Array) | ||
assert.equal(users.length, 1) | ||
done() | ||
}) | ||
}) | ||
it('should error with failClient', function (done) { | ||
failClient.getUsers(function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
it('should error when deleting an existing user', function (done) { | ||
failClient.getUsers(function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
describe('#setPassword', function () { | ||
it('should update user password without error', function (done) { | ||
client.setPassword(info.db.username, info.db.password, done) | ||
}) | ||
}) | ||
}) | ||
}) | ||
describe('#grantAndRevokePrivileges', function () { | ||
it('should grant user privileges without error', function (done) { | ||
client.grantPrivilege('READ', info.db.name, info.db.username, done) | ||
}) | ||
it('should error when granting user invalid privilege', function (done) { | ||
client.grantPrivilege('BEER', info.db.name, info.db.username, function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
}) | ||
}) | ||
it('should revoke user privileges without error', function (done) { | ||
client.revokePrivilege('READ', info.db.name, info.db.username, done) | ||
}) | ||
it('should error when revoking invalid privilege', function (done) { | ||
client.revokePrivilege('BEER', info.db.name, info.db.username, function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
}) | ||
}) | ||
}) | ||
describe('#setPassword', function () { | ||
it('should update user password without error', function (done) { | ||
client.setPassword(info.db.username, info.db.password, done) | ||
describe('#grantAndRevokeAdminPrivileges', function () { | ||
it('should grant admin privileges without error', function (done) { | ||
client.grantAdminPrivileges(info.db.username, done) | ||
}) | ||
it('should error when granting invalid privilege', function (done) { | ||
client.grantAdminPrivileges('invalidPriv', function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
}) | ||
}) | ||
it('should revoke admin privileges without error', function (done) { | ||
client.revokeAdminPrivileges(info.db.username, done) | ||
}) | ||
it('should error when revoking invalid privilege', function (done) { | ||
client.revokeAdminPrivileges('invalidPriv', function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
}) | ||
describe('#grantPrivilege', function () { | ||
it('should grant user privileges without error', function (done) { | ||
client.grantPrivilege('READ', info.db.name, info.db.username, done) | ||
describe('#createDatabase', function () { | ||
it('should create a new database without error', function (done) { | ||
client.createDatabase(info.db.name, done) | ||
}) | ||
it('should error when granting user privilege', function (done) { | ||
client.grantPrivilege('BEER', info.db.name, info.db.username, function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
}) | ||
afterEach(function (done) { | ||
client.dropDatabase(info.db.name, done) | ||
}) | ||
}) | ||
describe('#revokePrivilege', function () { | ||
it('should revoke user privileges without error', function (done) { | ||
client.revokePrivilege('READ', info.db.name, info.db.username, done) | ||
describe('#dropDatabase', function () { | ||
beforeEach(function (done) { | ||
client.createDatabase(info.db.name, done) | ||
}) | ||
it('should error when updating user privilege', function (done) { | ||
client.revokePrivilege('BEER', info.db.name, info.db.username, function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
it('should delete the database without error', function (done) { | ||
client.dropDatabase(info.db.name, done) | ||
}) | ||
it('should not error if database didn\'t exist', function (done) { | ||
client.dropDatabase(info.db.name, function (err) { | ||
if (err) return done(err) | ||
client.dropDatabase(info.db.name, function (err) { | ||
done(err) | ||
}) | ||
}) | ||
@@ -267,211 +316,307 @@ }) | ||
describe('#grantAdminPrivileges', function () { | ||
it('should grant admin privileges without error', function (done) { | ||
client.grantAdminPrivileges(info.db.username, done) | ||
describe('#withDatabase', function () { | ||
beforeEach(function (done) { | ||
client.createDatabase(info.db.name, done) | ||
}) | ||
it('should error when granting admin privileges', function (done) { | ||
client.grantAdminPrivileges('yourmum', function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
}) | ||
afterEach(function (done) { | ||
client.dropDatabase(info.db.name, done) | ||
}) | ||
}) | ||
describe('#revokeAdminPrivileges', function () { | ||
it('should revoke admin privileges without error', function (done) { | ||
client.revokeAdminPrivileges(info.db.username, done) | ||
}) | ||
it('should error when revoking admin privileges', function (done) { | ||
client.revokeAdminPrivileges('yourmum', function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
describe('#duplicateDatabase', function () { | ||
it('should not report an error if db already exists', function (done) { | ||
client.createDatabase(info.db.name, function (err) { | ||
done(err) | ||
}) | ||
}) | ||
}) | ||
}) | ||
describe('#dropUser', function () { | ||
it('should delete a user without error', function (done) { | ||
client.dropUser(info.db.username, done) | ||
}) | ||
it('should error when deleting an existing user', function (done) { | ||
client.dropUser(info.db.username, function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
describe('#getDatabaseNames', function () { | ||
it('should return array of database names', function (done) { | ||
client.getDatabaseNames(function (err, dbs) { | ||
if (err) return done(err) | ||
assert(dbs instanceof Array) | ||
assert.notEqual(dbs.indexOf(info.db.name), -1) | ||
done() | ||
}) | ||
}) | ||
it('should bubble errors through', function (done) { | ||
failClient.getDatabaseNames(function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
describe('#createRetentionPolicy', function () { | ||
it('should create a rentention policy', function (done) { | ||
dbClient.createRetentionPolicy(info.db.retentionPolicy, info.db.name, '1d', 1, true, done) | ||
describe('#retentionPolicies', function () { | ||
beforeEach(function (done) { | ||
dbClient.createRetentionPolicy(info.db.retentionPolicy, info.db.name, '1d', 1, true, done) | ||
}) | ||
it('should get an array of retention policies', function (done) { | ||
client.getRetentionPolicies(info.db.name, function (err, rps) { | ||
assert.equal(err, null) | ||
assert(rps instanceof Array) | ||
assert.equal(rps.length, 1) | ||
done() | ||
}) | ||
}) | ||
it('should alter a rentention policy', function (done) { | ||
dbClient.alterRetentionPolicy(info.db.retentionPolicy, info.db.name, '1h', 1, true, done) | ||
}) | ||
}) | ||
}) | ||
describe('#getRetentionPolicies', function () { | ||
it('should get an array of retention policies', function (done) { | ||
client.getRetentionPolicies(info.db.name, function (err, rps) { | ||
assert.equal(err, null) | ||
assert(rps instanceof Array) | ||
assert.equal(rps.length, 1) | ||
done() | ||
describe('#writePoint', function () { | ||
this.timeout(5000) | ||
it('should write a generic point into the database', function (done) { | ||
dbClient.writePoint(info.series.numName, {value: 232, value2: 123}, {foo: 'bar', foobar: 'baz'}, done) | ||
}) | ||
}) | ||
}) | ||
describe('#alterRetentionPolicy', function () { | ||
it('should alter a rentention policy', function (done) { | ||
dbClient.alterRetentionPolicy(info.db.retentionPolicy, info.db.name, '1h', 1, true, done) | ||
}) | ||
}) | ||
it('should write a generic point into the database', function (done) { | ||
dbClient.writePoint(info.series.numName, 1, {foo: 'bar', foobar: 'baz'}, done) | ||
}) | ||
describe('#writePoint', function () { | ||
this.timeout(5000) | ||
it('should write a generic point into the database', function (done) { | ||
dbClient.writePoint(info.series.numName, {time: 1234567890, value: 232}, {}, done) | ||
}) | ||
it('should write a generic point into the database', function (done) { | ||
dbClient.writePoint(info.series.name, {value: 232, value2: 123}, { foo: 'bar', foobar: 'baz'}, done) | ||
}) | ||
it('should write a point with time into the database', function (done) { | ||
dbClient.writePoint(info.series.numName, {time: new Date(), value: 232}, {}, done) | ||
}) | ||
it('should write a generic point into the database', function (done) { | ||
dbClient.writePoint(info.series.name, 1, { foo: 'bar', foobar: 'baz'}, done) | ||
}) | ||
it('should write a point with a string as value into the database', function (done) { | ||
dbClient.writePoint(info.series.strName, {value: 'my test string'}, {}, done) | ||
}) | ||
it('should write a generic point into the database', function (done) { | ||
dbClient.writePoint(info.series.name, {time: 1234567890, value: 232}, {}, done) | ||
it('should write a point with a string as value into the database (using different method)', function (done) { | ||
dbClient.writePoint(info.series.strName, 'my second test string', {}, done) | ||
}) | ||
it('should write a point that has "length" in its keys (#126)', function (done) { | ||
dbClient.writePoint(info.series.strName, {length: 3}, {length: '5'}, done) | ||
}) | ||
}) | ||
it('should write a point with time into the database', function (done) { | ||
dbClient.writePoint(info.series.name, {time: new Date(), value: 232}, {}, done) | ||
describe('#writePoints', function () { | ||
this.timeout(10000) | ||
it('should write multiple points to the same time series, same column names', function (done) { | ||
var points = [ | ||
[{value: 232}, {foobar: 'baz'}], | ||
[{value: 212}, {foobar: 'baz'}], | ||
[{value: 452}, {foobar: 'baz'}], | ||
[{value: 122}] | ||
] | ||
dbClient.writePoints(info.series.numName, points, done) | ||
}) | ||
it('should write multiple points to the same time series, differing column names', function (done) { | ||
var points = [ | ||
[{value: 232}, {foobar: 'baz'}], | ||
[{othervalue: 212}, {foobar: 'baz'}], | ||
[{andanothervalue: 452}, {foobar: 'baz'}] | ||
] | ||
dbClient.writePoints(info.series.numName, points, done) | ||
}) | ||
}) | ||
it('should write a point with a string as value into the database', function (done) { | ||
dbClient.writePoint(info.series.strName, {value: 'my test string'}, {}, done) | ||
describe('#writeSeries', function () { | ||
it('should write multiple points to multiple time series, same column names', function (done) { | ||
var points = [ | ||
[{value: 232}, {foobar: 'baz'}], | ||
[{value: 212}, {foobar: 'baz'}], | ||
[{value: 452}, {foobar: 'baz'}], | ||
[{value: 122}] | ||
] | ||
var data = { | ||
series1: points, | ||
series2: points | ||
} | ||
dbClient.writeSeries(data, done) | ||
}) | ||
it('should write multiple points to multiple time series, differing column names', function (done) { | ||
var points = [ | ||
[{value: 232}, {foobar: 'baz'}], | ||
[{othervalue: 212}, {foobar: 'baz'}], | ||
[{andanothervalue: 452}, {foobar: 'baz'}] | ||
] | ||
var data = { | ||
series1: points, | ||
series2: points | ||
} | ||
dbClient.writeSeries(data, done) | ||
}) | ||
it('should write multiple points to multiple time series, differing column names, specified timestamps', function (done) { | ||
var points = [ | ||
[{value: 232, time: 1234567787}, {foobar: 'baz'}], | ||
[{othervalue: 212, time: 1234567777}, {foobar: 'baz'}], | ||
[{andanothervalue: 452, time: 1234567747}, {foobar: 'baz'}] | ||
] | ||
var data = { | ||
series1: points, | ||
series2: points | ||
} | ||
var response = dbClient._prepareValues(data) | ||
var expected = 'series1,foobar=baz value=232 1234567787\nseries1,foobar=baz othervalue=212 1234567777\nseries1,foobar=baz andanothervalue=452 1234567747\nseries2,foobar=baz value=232 1234567787\nseries2,foobar=baz othervalue=212 1234567777\nseries2,foobar=baz andanothervalue=452 1234567747' | ||
assert.equal(response, expected) | ||
done() | ||
}) | ||
}) | ||
it('should write a point with a string as value into the database (using different method)', function (done) { | ||
dbClient.writePoint(info.series.strName, 'my second test string', {}, done) | ||
}) | ||
describe('#withPointsInDB', function () { | ||
beforeEach(function (done) { | ||
dbClient.writePoint(info.series.numName, {value: 100, value2: 200}, {field1: 'f1', field2: 'f2'}, function () { | ||
dbClient.writePoint(info.series.numName, {value: 101, value2: 201}, {field1: 'f1'}, function () { | ||
dbClient.writePoint(info.series.strName, {value: 'my test string'}, {}, function () { | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
it('should write a point that has "length" in its keys', function (done) { | ||
dbClient.writePoint(info.series.strName, {length: 3}, {length: '5'}, done) | ||
}) | ||
}) | ||
describe('#query', function () { | ||
it('should read a point from the database', function (done) { | ||
dbClient.query('SELECT value FROM ' + info.series.numName + ';', function (err, res) { | ||
assert.equal(err, null) | ||
assert(res instanceof Array) | ||
assert.equal(res.length, 1) | ||
assert.equal(res[0].length, 2) | ||
assert.equal(res[0][0].value, 100) | ||
assert.equal(res[0][1].value, 101) | ||
done() | ||
}) | ||
}) | ||
}) | ||
describe('#writePoints', function () { | ||
this.timeout(10000) | ||
it('should write multiple points to the same time series, same column names', function (done) { | ||
var points = [ | ||
[{value: 232}, { foobar: 'baz'}], | ||
[{value: 212}, { foobar: 'baz'}], | ||
[{value: 452}, { foobar: 'baz'}], | ||
[{value: 122}] | ||
] | ||
dbClient.writePoints(info.series.name, points, done) | ||
}) | ||
it('should write multiple points to the same time series, differing column names', function (done) { | ||
var points = [ | ||
[{value: 232}, { foobar: 'baz'}], | ||
[{othervalue: 212}, { foobar: 'baz'}], | ||
[{andanothervalue: 452}, { foobar: 'baz'}] | ||
] | ||
dbClient.writePoints(info.series.name, points, done) | ||
}) | ||
}) | ||
describe('#queryRaw', function () { | ||
it('should read a point from the database and return raw values', function (done) { | ||
dbClient.queryRaw('SELECT value FROM ' + info.series.numName + ';', function (err, res) { | ||
assert.equal(err, null) | ||
assert(res instanceof Array) | ||
assert.equal(res.length, 1) | ||
assert.equal(res[0].series.length, 1) | ||
done() | ||
}) | ||
}) | ||
}) | ||
describe('#writeSeries', function () { | ||
it('should write multiple points to multiple time series, same column names', function (done) { | ||
var points = [ | ||
[{value: 232}, { foobar: 'baz'}], | ||
[{value: 212}, { foobar: 'baz'}], | ||
[{value: 452}, { foobar: 'baz'}], | ||
[{value: 122}] | ||
] | ||
var data = { | ||
series1: points, | ||
series2: points | ||
} | ||
dbClient.writeSeries(data, done) | ||
}) | ||
it('should write multiple points to multiple time series, differing column names', function (done) { | ||
var points = [ | ||
[{value: 232}, { foobar: 'baz'}], | ||
[{othervalue: 212}, { foobar: 'baz'}], | ||
[{andanothervalue: 452}, { foobar: 'baz'}] | ||
] | ||
var data = { | ||
series1: points, | ||
series2: points | ||
} | ||
dbClient.writeSeries(data, done) | ||
}) | ||
it('should write multiple points to multiple time series, differing column names, specified timestamps', function (done) { | ||
var points = [ | ||
[{value: 232, time: 1234567787}, { foobar: 'baz'}], | ||
[{othervalue: 212, time: 1234567777}, { foobar: 'baz'}], | ||
[{andanothervalue: 452, time: 1234567747}, { foobar: 'baz'}] | ||
] | ||
var data = { | ||
series1: points, | ||
series2: points | ||
} | ||
var response = dbClient._prepareValues(data) | ||
var expected = 'series1,foobar=baz value=232 1234567787\nseries1,foobar=baz othervalue=212 1234567777\nseries1,foobar=baz andanothervalue=452 1234567747\nseries2,foobar=baz value=232 1234567787\nseries2,foobar=baz othervalue=212 1234567777\nseries2,foobar=baz andanothervalue=452 1234567747' | ||
assert.equal(response, expected) | ||
done() | ||
}) | ||
}) | ||
describe('#escapingRoundtrip', function () { | ||
it('should escape, write, read, and unescape a point', function (done) { | ||
dbClient.writePoint(info.series.numName, | ||
{'value,= 1': ',"= ', '"': 2}, | ||
{tag1: 'escapingRoundTrip', 'commas, and = signs': 'space != ,'}, function (err) { | ||
assert.equal(err, null) | ||
dbClient.query('SELECT * FROM ' + info.series.numName + " WHERE tag1='escapingRoundTrip';", function (err, res) { | ||
assert.equal(err, null) | ||
assert(res instanceof Array) | ||
assert.equal(res.length, 1, 'one series') | ||
assert.equal(res[0].length, 1, 'one result') | ||
assert.equal(res[0][0].tag1, 'escapingRoundTrip', 'the right result') | ||
assert.equal(res[0][0]['value,= 1'], ',"= ', '[,= ]-escaping field keys and values') | ||
assert.equal(res[0][0]['"'], 2, 'escaping quotes in field keys') | ||
assert.equal(res[0][0]['commas, and = signs'], 'space != ,', 'escaping tag keys and values') | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
describe('#query', function () { | ||
it('should read a point from the database', function (done) { | ||
dbClient.query('SELECT value FROM ' + info.series.name + ';', function (err, res) { | ||
assert.equal(err, null) | ||
assert(res instanceof Array) | ||
assert.equal(res.length, 1) | ||
assert(res[0].length >= 2) | ||
assert.equal(res[0][0].value, 232) | ||
done() | ||
describe('#getMeasurements', function () { | ||
it('should return array of measurements', function (done) { | ||
client.getMeasurements(function (err, measurements) { | ||
if (err) return done(err) | ||
assert(measurements instanceof Array) | ||
assert.equal(measurements.length, 1) | ||
done() | ||
}) | ||
}) | ||
it('should validate the returned measurements') | ||
}) | ||
}) | ||
}) | ||
describe('#queryRaw', function () { | ||
it('should read a point from the database and return raw values', function (done) { | ||
dbClient.queryRaw('SELECT value FROM ' + info.series.name + ';', function (err, res) { | ||
assert.equal(err, null) | ||
assert(res instanceof Array) | ||
assert.equal(res.length, 1) | ||
assert.equal(res[0].series.length, 1) | ||
done() | ||
describe('#getSeries', function () { | ||
it('should return array of series', function (done) { | ||
client.getSeries(function (err, series) { | ||
if (err) return done(err) | ||
var expected = [ { | ||
columns: [ 'key' ], | ||
values: [ | ||
[ 'number_test,field1=f1' ], | ||
[ 'number_test,field1=f1,field2=f2' ], | ||
[ 'string_test' ] | ||
] } ] | ||
assert.deepEqual(series, expected) | ||
done() | ||
}) | ||
}) | ||
it('should return array of series', function (done) { | ||
client.getSeries(info.series.numName, function (err, series) { | ||
if (err) return done(err) | ||
assert(series instanceof Array) | ||
assert.equal(series[0].values.length, 2) | ||
done() | ||
}) | ||
}) | ||
it('should bubble errors through') | ||
}) | ||
}) | ||
}) | ||
describe('#createContinuousQuery', function () { | ||
it('should create a continuous query', function (done) { | ||
dbClient.createContinuousQuery('testQuery', 'SELECT COUNT(value) INTO valuesCount_1h FROM ' + info.series.name + ' GROUP BY time(1h) ', function (err, res) { | ||
assert.equal(err, null) | ||
assert(res instanceof Array) | ||
assert.equal(res.length, 1) | ||
done() | ||
describe('#getSeriesNames', function () { | ||
it('should return array of series.numNames', function (done) { | ||
client.getSeriesNames(function (err, series) { | ||
if (err) return done(err) | ||
assert(series instanceof Array) | ||
assert.notEqual(series.indexOf(info.series.numName), -1) | ||
done() | ||
}) | ||
}) | ||
it('should return array of series.numNames from the db defined on connection', function (done) { | ||
client.getSeriesNames(function (err, series) { | ||
if (err) return done(err) | ||
assert(series instanceof Array) | ||
assert.notEqual(series.indexOf(info.series.numName), -1) | ||
done() | ||
}) | ||
}) | ||
it('should bubble errors through') | ||
}) | ||
}) | ||
}) | ||
describe('#getContinuousQueries', function () { | ||
it('should fetch all continuous queries from the database', function (done) { | ||
dbClient.getContinuousQueries(function (err, res) { | ||
assert.equal(err, null) | ||
assert(res instanceof Array) | ||
assert.equal(res.length, 1) | ||
done() | ||
describe('#dropSeries', function () { | ||
this.timeout(25000) | ||
it('should drop series', function (done) { | ||
client.dropSeries('WHERE foobar="baz"', function (err) { | ||
if (err) return done(err) | ||
assert.equal(err, null) | ||
done() | ||
}) | ||
}) | ||
it('should bubble errors through', function (done) { | ||
failClient.dropSeries(info.series.numName, function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
}) | ||
}) | ||
}) | ||
describe('#dropMeasurement', function () { | ||
this.timeout(25000) | ||
it('should drop measurement', function (done) { | ||
client.dropMeasurement(info.series.numName, function (err) { | ||
if (err) return done(err) | ||
assert.equal(err, null) | ||
done() | ||
}) | ||
}) | ||
it('should bubble errors through', function (done) { | ||
failClient.dropMeasurement(info.series.numName, function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
}) | ||
describe('#dropContinuousQuery', function () { | ||
it('should drop the continuous query from the database', function (done) { | ||
dbClient.getContinuousQueries(function (err, res) { | ||
if (err) return done(err) | ||
dbClient.dropContinuousQuery(res[0][0].name, function (err) { | ||
describe('#createContinuousQuery', function () { | ||
it('should create a continuous query', function (done) { | ||
dbClient.createContinuousQuery('testQuery', 'SELECT COUNT(value) INTO valuesCount_1h FROM ' + info.series.numName + ' GROUP BY time(1h) ', function (err, res) { | ||
assert.equal(err, null) | ||
assert(res instanceof Array) | ||
assert.equal(res.length, 1) | ||
done() | ||
@@ -481,35 +626,31 @@ }) | ||
}) | ||
}) | ||
describe('#query failover', function () { | ||
it('should exceed retry limit', function (done) { | ||
this.timeout(30000) | ||
failoverClient.query('SELECT value FROM ' + info.series.name + ';', function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
describe('#withContinuousQueryInDB', function () { | ||
beforeEach(function (done) { | ||
dbClient.createContinuousQuery('testQuery', 'SELECT COUNT(value) INTO valuesCount_1h FROM ' + info.series.numName + ' GROUP BY time(1h) ', done) | ||
}) | ||
}) | ||
}) | ||
describe('#query failover', function () { | ||
it('should read a point from the database after the failed servers have been removed', function (done) { | ||
this.timeout(25000) | ||
failoverClient.query('SELECT value FROM ' + info.series.name + ';', function (err, res) { | ||
assert.equal(err, null) | ||
assert(res instanceof Array) | ||
assert.equal(res.length, 1) | ||
assert(res[0].length >= 2) | ||
assert.equal(res[0][0].value, 232) | ||
done() | ||
describe('#getContinuousQueries', function () { | ||
it('should fetch all continuous queries from the database', function (done) { | ||
dbClient.getContinuousQueries(function (err, res) { | ||
assert.equal(err, null) | ||
assert(res instanceof Array) | ||
assert.equal(res.length, 1) | ||
// XXX Double check API / documentation, extra level of arrays? | ||
// assert.equal(res[0].name, 'testQuery') | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
}) | ||
describe('#getMeasurements', function () { | ||
it('should return array of measurements', function (done) { | ||
client.getMeasurements(function (err, measurements) { | ||
if (err) return done(err) | ||
assert(measurements instanceof Array) | ||
assert.equal(measurements.length, 1) | ||
done() | ||
describe('#dropContinuousQuery', function () { | ||
it('should drop the continuous query from the database', function (done) { | ||
dbClient.getContinuousQueries(function (err, res) { | ||
if (err) return done(err) | ||
dbClient.dropContinuousQuery(res[0][0].name, function (err) { | ||
assert.equal(err, null) | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
@@ -519,89 +660,83 @@ }) | ||
describe('#getSeries', function () { | ||
it('should return array of series', function (done) { | ||
client.getSeries(function (err, series) { | ||
if (err) return done(err) | ||
assert(series[0].values instanceof Array) | ||
assert(series[0].values.length >= 3) | ||
done() | ||
describe('#failoverClient', function () { | ||
var normalClient | ||
var failoverClient | ||
var failoverdb = 'test_db_failover' | ||
before(function (done) { | ||
normalClient = influx({host: info.server.host, port: info.server.port, username: info.server.username, password: info.server.password, database: failoverdb}) | ||
normalClient.createDatabase(failoverdb, function (err, response) { | ||
assert.equal(err, null) | ||
normalClient.writePoint(info.series.numName, {value: 232, value2: 123}, {foo: 'bar', foobar: 'baz'}, function (err, response) { | ||
assert.equal(err, null) | ||
done() | ||
}) | ||
}) | ||
}) | ||
it('should return array of series', function (done) { | ||
client.getSeries(info.series.name, function (err, series) { | ||
if (err) return done(err) | ||
assert(series instanceof Array) | ||
assert.equal(series[0].values.length, 3) | ||
done() | ||
}) | ||
beforeEach(function (done) { | ||
failoverClient = influx({hosts: [ | ||
{host: '192.168.255.1'}, | ||
{host: '192.168.255.2'}, | ||
{host: '192.168.255.3'}, | ||
{host: '192.168.255.4'}, | ||
{host: info.server.host, port: info.server.port} | ||
], username: info.server.username, passwort: info.server.password, database: failoverdb}) | ||
done() | ||
}) | ||
it('should bubble errors through') | ||
}) | ||
describe('#getSeriesNames', function () { | ||
it('should return array of series names', function (done) { | ||
client.getSeriesNames(function (err, series) { | ||
if (err) return done(err) | ||
assert(series instanceof Array) | ||
assert.notEqual(series.indexOf(info.series.name), -1) | ||
done() | ||
}) | ||
after(function (done) { | ||
normalClient.dropDatabase(failoverdb, done) | ||
}) | ||
it('should return array of series names from the db defined on connection', function (done) { | ||
client.getSeriesNames(function (err, series) { | ||
if (err) return done(err) | ||
assert(series instanceof Array) | ||
assert.notEqual(series.indexOf(info.series.name), -1) | ||
describe('#setRequestTimeout', function () { | ||
it('should set the default request timeout value', function (done) { | ||
var timeout = failoverClient.setRequestTimeout(5000) | ||
assert.equal(timeout, 5000) | ||
done() | ||
}) | ||
}) | ||
it('should bubble errors through') | ||
}) | ||
describe('#dropSeries', function () { | ||
this.timeout(25000) | ||
it('should drop series', function (done) { | ||
client.dropSeries('WHERE foobar="baz"', function (err) { | ||
if (err) return done(err) | ||
assert.equal(err, null) | ||
describe('#setFailoverTimeout', function () { | ||
it('should set the default request timeout value', function (done) { | ||
var timeout = failoverClient.setFailoverTimeout(2000) | ||
assert.equal(timeout, 2000) | ||
done() | ||
}) | ||
}) | ||
it('should bubble errors through', function (done) { | ||
failClient.dropSeries(info.series.name, function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
}) | ||
}) | ||
}) | ||
describe('#dropMeasurement', function () { | ||
this.timeout(25000) | ||
it('should drop measurement', function (done) { | ||
client.dropMeasurement(info.series.name, function (err) { | ||
if (err) return done(err) | ||
assert.equal(err, null) | ||
done() | ||
describe('#exceedRetryLimit', function () { | ||
it('should exceed retry limit', function (done) { | ||
// Validate default retry value will still cause failure | ||
assert.equal(failoverClient.options.maxRetries, 2) | ||
failoverClient.setRequestTimeout(1000) | ||
// Should fail after ~3 seconds (third failed retry) | ||
this.timeout(4000) | ||
failoverClient.query('SELECT value FROM ' + info.series.numName + ';', function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
}) | ||
}) | ||
}) | ||
it('should bubble errors through', function (done) { | ||
failClient.dropMeasurement(info.series.name, function (err) { | ||
assert(err instanceof Error) | ||
done() | ||
}) | ||
}) | ||
}) | ||
describe('#dropDatabase', function () { | ||
this.timeout(25000) | ||
it('should delete the database without error', function (done) { | ||
client.dropDatabase(info.db.name, done) | ||
}) | ||
it('should not error if database didn\'t exist', function (done) { | ||
client.dropDatabase(info.db.name, function (err) { | ||
done(err) | ||
describe('#queryFailover', function () { | ||
it('should read a point from the database after the failed servers have been removed', function (done) { | ||
// FIXME: This is a bit of a hack, but there's currently no API to dynamically change this | ||
failoverClient.request.options.maxRetries = 5 | ||
failoverClient.setRequestTimeout(1000) | ||
// Should succeed on 5th server it tries (4s of timeouts) | ||
this.timeout(10000) | ||
failoverClient.query('SELECT value FROM ' + info.series.numName + ';', function (err, res) { | ||
assert.equal(err, null) | ||
assert(res instanceof Array) | ||
assert.equal(res.length, 1) | ||
assert(res[0].length === 1) | ||
assert.equal(res[0][0].value, 232) | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
}) | ||
@@ -608,0 +743,0 @@ |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
84727
17
1638
472
1