From 984a55f6c07dda4fcaf3f6ec718902f3e3b2adb7 Mon Sep 17 00:00:00 2001 From: Spencer Alger Date: Tue, 29 Oct 2013 08:48:29 -0700 Subject: [PATCH] Cleaned up the generation script, fixing the doc-blocks above the client actions. Replaced the transport, giving it all of the functionality that was brought over to the client and making the client simply a place for the API to live. Essentially a shell that can easily be removed. spec'd out the TransportRequest which will eventually inherit from one of server possible promise implementations and will be plugable. It will also implement the "abort" functionality needed in an environment like node.js --- scripts/generate/js_api/actions.js | 123 +++ scripts/generate/js_api/index.js | 83 +- scripts/generate/js_api/spec.js | 58 -- .../generate/js_api/templates/api_file.tmpl | 2 +- .../js_api/templates/client_action.tmpl | 4 +- scripts/generate/js_api/templates/index.js | 174 +--- scripts/stupid-benchmark.js | 8 +- src/lib/api.js | 845 ++++++++++-------- src/lib/client.js | 156 +--- src/lib/client_action.js | 37 +- src/lib/client_config.js | 107 +-- src/lib/connection.js | 14 +- src/lib/connection_pool.js | 20 +- src/lib/connections/http.js | 99 +- src/lib/connections/jquery.js | 17 +- src/lib/connections/xhr.js | 68 +- src/lib/errors.js | 7 +- src/lib/host.js | 65 ++ src/lib/log.js | 4 +- src/lib/transport.js | 54 ++ src/lib/transport_request.js | 147 +++ src/lib/utils.js | 58 +- test/integration/yaml_suite/index.js | 26 +- test/integration/yaml_suite/server.js | 2 +- test/unit/es_server.test.js | 2 +- 25 files changed, 1128 insertions(+), 1052 deletions(-) create mode 100644 scripts/generate/js_api/actions.js delete mode 100644 scripts/generate/js_api/spec.js create mode 100644 src/lib/host.js create mode 100644 src/lib/transport.js create mode 100644 src/lib/transport_request.js diff --git a/scripts/generate/js_api/actions.js b/scripts/generate/js_api/actions.js new file mode 100644 index 000000000..90d0615f6 --- /dev/null +++ b/scripts/generate/js_api/actions.js @@ -0,0 +1,123 @@ +var _ = require('../../../src/lib/utils'); + +var EventEmitter = require('events').EventEmitter; +var aliases = require('./aliases'); + +var castExistsRE = /exists/; +var usesBulkBodyRE = /^(bulk|msearch)$/; +var urlParamRE = /\{(\w+)\}/g; + +var specCount = 0; +var actions = []; +var doneParsing = false; + +require('../../get_spec') + .get('api/*.json') + .on('entry', transformFile) + .on('end', function () { + doneParsing = true; + if (actions.length === specCount) { + module.exports.emit('ready', actions); + } + }); + +function transformFile(entry) { + specCount++; + + // itterate all of the specs within the file, should only be one + _.each(JSON.parse(entry.data), function (def, name) { + var steps = name.split('.'); + var allParams = _.extend({}, def.url.params, def.url.parts); + var spec = { + name: name, + methods: _.map(def.methods, function (m) { return m.toUpperCase(); }), + params: def.url.params, + body: def.body || null, + path2lib: _.repeat('../', steps.length + 1) + 'lib/' + }; + + if (def.body && def.body.requires) { + spec.needBody = true; + } + + if (usesBulkBodyRE.test(name)) { + spec.bulkBody = true; + } + + if (castExistsRE.test(name)) { + spec.castExists = true; + } + + var urls = _.difference(def.url.paths, aliases[name]); + urls = _.map(urls, function (url, i) { + var optionalVars = {}; + var requiredVars = {}; + var param; + var target; + var match; + + if (url.charAt(0) !== '/') { + url = '/' + url; + } + + while (match = urlParamRE.exec(url)) { + param = def.url.parts[match[1]] || {}; + target = (param.required || !param.default) ? requiredVars : optionalVars; + target[match[1]] = _.omit(param, 'required'); + } + + [requiredVars, optionalVars].forEach(function (vars) { + _.each(vars, function (v, name) { + vars[name] = _.omit(v, 'description'); + }); + }); + + return _.omit({ + fmt: url.replace(urlParamRE, '<%=$1%>'), + opt: _.size(optionalVars) ? optionalVars : null, + req: _.size(requiredVars) ? requiredVars : null, + sortOrder: _.size(requiredVars) * -1 + }, function (v) { + return !v; + }); + }); + + spec.urls = _.map(_.sortBy(urls, 'sortOrder'), function (url) { + return _.omit(url, 'sortOrder'); + }); + + spec.params = _.transform(spec.params, function (note, param, name) { + param.name = name; + note[name] = _.pick(param, [ + 'type', 'default', 'options', 'required' + ]); + }, {}); + + // escape method names with "special" keywords + var location = _.map(spec.name.split('.'), _.camelCase) + .join('.prototype.') + .replace(/(^|\.)(delete|default)(\.|$)/g, '[\'$2\']'); + + var action = { + spec: _.pick(spec, [ + 'methods', + 'params', + 'urls', + 'needBody', + 'bulkBody', + 'castExists', + 'castNotFound' + ]), + location: location, + docUrl: def.documentation, + name: spec.name, + allParams: allParams + }; + + if (actions.push(action) === specCount && doneParsing) { + module.exports.emit('ready', action); + } + }); +} + +module.exports = new EventEmitter(); diff --git a/scripts/generate/js_api/index.js b/scripts/generate/js_api/index.js index 151eba7e9..f40f6d0b6 100644 --- a/scripts/generate/js_api/index.js +++ b/scripts/generate/js_api/index.js @@ -9,83 +9,18 @@ var urlParamRE = /\{(\w+)\}/g; var outputPath = _.joinPath(__dirname, '../../../src/lib/api.js'); -require('./spec').on('ready', function (specs) { +require('./actions').on('ready', function (actions) { var defs = []; - var namespaces = []; + + var namespaces = _.filter(_.map(actions, function (action) { + if (~action.location.indexOf('.')) { + var path = action.location.split('.').slice(0, -1); + _.pull(path, 'prototype'); + return path.join('.'); + } + })); clean(outputPath); - var actions = _.map(specs, function (spec) { - spec.urls = _.map( - _.sortBy( - _.transform(spec.urls, function (note, url, i) { - var optionalVars = {}; - var requiredVars = {}; - var param; - var target; - var match; - - if (url.charAt(0) !== '/') { - url = '/' + url; - } - - while (match = urlParamRE.exec(url)) { - param = spec.urlParts[match[1]] || {}; - target = (param.required || !param.default) ? requiredVars : optionalVars; - target[match[1]] = _.omit(param, 'required'); - } - - [requiredVars, optionalVars].forEach(function (vars) { - _.each(vars, function (v, name) { - vars[name] = _.omit(v, 'description'); - }); - }); - - note.push(_.omit({ - fmt: url.replace(urlParamRE, '<%=$1%>'), - opt: _.size(optionalVars) ? optionalVars : null, - req: _.size(requiredVars) ? requiredVars : null, - sortOrder: _.size(requiredVars) * -1 - }, function (v) { return !v; })); - }, []) - , 'sortOrder') - , function (url) { - return _.omit(url, 'sortOrder'); - }); - - var docUrl = spec.docUrl; - var location = _.map(spec.name.split('.'), _.camelCase).join('.'); - - spec = _.pick(spec, [ - 'methods', - 'params', - 'urls', - 'needBody', - 'bulkBody', - 'castNotFound' - ]); - - spec.params = _.transform(spec.params, function (note, param, name) { - param.name = name; - note[name] = _.pick(param, [ - 'type', 'default', 'options', 'required' - ]); - }, {}); - - if (~location.indexOf('.')) { - var steps = location.split('.'); - namespaces.push(steps.slice(0, -1).join('.')); - location = steps.join('.prototype.'); - } - - // escape method names with "special" keywords - location = location.replace(/(^|\.)(delete|default)(\.|$)/g, '[\'$2\']'); - return { - spec: spec, - location: location, - docUrl: docUrl - }; - }); - console.log('writing', actions.length, 'api actions to', outputPath); fs.writeFileSync(outputPath, templates.apiFile({ actions: actions, diff --git a/scripts/generate/js_api/spec.js b/scripts/generate/js_api/spec.js deleted file mode 100644 index d64528aec..000000000 --- a/scripts/generate/js_api/spec.js +++ /dev/null @@ -1,58 +0,0 @@ -var _ = require('../../../src/lib/utils'); - -var EventEmitter = require('events').EventEmitter; -var aliases = require('./aliases'); - -var castNotFoundRE = /exists/; -var usesBulkBodyRE = /^(bulk|msearch)$/; - -var specCount = 0; -var completedSpecs = []; -var doneParsing = false; - -require('../../get_spec') - .get('api/*.json') - .on('entry', transformFile) - .on('end', function () { - doneParsing = true; - if (completedSpecs.length === specCount) { - module.exports.emit('ready', completedSpecs); - } - }); - -function transformFile(entry) { - specCount++; - - var file = entry.data; - // itterate all of the specs within the file, should only be one - _.each(JSON.parse(file), function (def, name) { - var steps = name.split('.'); - var spec = { - name: name, - methods: _.map(def.methods, function (m) { return m.toUpperCase(); }), - docUrl: def.documentation, - urlParts: def.url.parts, - params: def.url.params, - urls: _.difference(def.url.paths, aliases[name]), - body: def.body || null, - path2lib: _.repeat('../', steps.length + 1) + 'lib/' - }; - - if (def.body && def.body.requires) { - spec.needBody = true; - } - - if (usesBulkBodyRE.test(name)) { - spec.bulkBody = true; - } - - if (castNotFoundRE.test(name)) { - spec.castNotFound = true; - } - if (completedSpecs.push(spec) === specCount && doneParsing) { - module.exports.emit('ready', completedSpecs); - } - }); -} - -module.exports = new EventEmitter(); diff --git a/scripts/generate/js_api/templates/api_file.tmpl b/scripts/generate/js_api/templates/api_file.tmpl index f8f324728..3f3726281 100644 --- a/scripts/generate/js_api/templates/api_file.tmpl +++ b/scripts/generate/js_api/templates/api_file.tmpl @@ -1,4 +1,4 @@ -var ca = require('./client_action').create; +var ca = require('./client_action'); var errors = require('./errors'); var api = module.exports = {}; diff --git a/scripts/generate/js_api/templates/client_action.tmpl b/scripts/generate/js_api/templates/client_action.tmpl index ed2df5ada..81477174b 100644 --- a/scripts/generate/js_api/templates/client_action.tmpl +++ b/scripts/generate/js_api/templates/client_action.tmpl @@ -1,8 +1,8 @@ /** - * Perform a [<%= spec.name %>](<%= docUrl %>) request + * Perform a [<%= name %>](<%= docUrl %>) request * * @param {Object} params - An object with parameters used to carry out this action<% -_.each(spec.params, function(param, paramName) { %> +_.each(allParams, function(param, paramName) { %> * @param {<%= paramType(param.type) %>} <%= paramWithDefault('params.' + paramName, param.default) %><% if (param.description) { %> - <%= param.description %><% diff --git a/scripts/generate/js_api/templates/index.js b/scripts/generate/js_api/templates/index.js index dd316f67a..d7d915ff9 100644 --- a/scripts/generate/js_api/templates/index.js +++ b/scripts/generate/js_api/templates/index.js @@ -1,8 +1,7 @@ -var _ = require('../../../../src/lib/utils') - , fs = require('fs') - , path = require('path') - , urlParamRE = /\{(\w+)\}/g; +var _ = require('../../../../src/lib/utils'); +var fs = require('fs'); +var path = require('path'); /** @@ -16,7 +15,7 @@ function lines(i) { if (line === '') { // no indent on empty lines l.lines.push(''); - } else if (typeof line !== 'undefined') { + } else if (line === void 0) { l.lines.push(_.repeat(' ', l.indent) + line); } return l; @@ -81,152 +80,6 @@ var templates = {}; */ var templateGlobals = { - writeParams: function (indent, params, namespace) { - var l = lines(indent); - - _.each(params, function (param, name) { - if (!param.required) { - l('if (typeof params.' + name + ' !== \'undefined\') {').in(); - } - - l.split(templates[param.type || 'any']({ - get: 'params.' + name, - set: namespace + name, - name: name - })); - - if (!param.required) { - l.out(); - l('}'); - } - l(''); - }); - - return l.toString(); - }, - - writeBrowserParams: function (indent, params, namespace) { - var l = lines(indent); - - _.each(params, function (param, name) { - if (!param.required) { - l('if (_.has(params, ' + stringify(name) + ')) {').in(); - } - switch (param.type) { - case 'enum': - l( - namespace + name + ' = _.' + - (param.type || 'any') + 'Param(params.' + name + ', ' + stringify(param.options) + - ');' - ); - break; - default: - l(namespace + name + ' = _.' + (param.type || 'any') + 'Param(params.' + name + ');'); - break; - } - if (!param.required) { - l.out('}'); - } - l(''); - }); - - return l.toString(); - }, - - writeUrls: function (indent, urls, urlParams, queryStringParams) { - var l = lines(indent); - - function urlVarIsRequired(varDetails) { - varDetails = typeof varDetails === 'string' ? urlParams[varDetails] : varDetails; - return varDetails && (varDetails.required || !varDetails.default); - } - - // turn a url string into an object describing the url, then sort them in decending order by how many args they have - urls = _.sortBy(urls, function (url) { - var requiredVars = _.filter(_.collectMatches(url, urlParamRE), function (match) { - return urlVarIsRequired(urlParams[match[1]]); - }); - return requiredVars ? requiredVars.length * -1 : 0; - }); - - _.each(urls, function (url, urlIndex) { - // collect the vars from the url and replace them to form the js that will build the url - var makeL = lines(), vars = []; - - makeL('request.path = \'' + url.replace(urlParamRE, function (match, varName) { - var varDetails = urlParams[varName]; - varDetails.name = varName; - vars.push(varDetails); - if (urlVarIsRequired(varDetails)) { - return '\' + encodeURIComponent(parts.' + varName + ') + \''; - } else { - return '\' + encodeURIComponent(parts.' + varName + ' || ' + stringify(varDetails.default) + ') + \''; - } - }) + '\';'); - - makeL(_.filter(_.map(vars, function (v, i) { - if (_.has(queryStringParams, v.name)) { - // delete the param so that it's not used later on in the queryString - return 'delete params.' + v.name + ';'; - } - })).join(' ')); - - if (vars.length || urlIndex) { - var requiredVars = _.filter(vars, urlVarIsRequired); - - var condition = _.map(requiredVars, function (v) { - return 'parts.' + v.name + ')'; - }).join(' && '); - - l((urlIndex > 0 ? 'else ' : '') + (condition ? 'if (' + condition + ') ' : '') + '{') - .in() - .split(makeL.toString()) - .out('}'); - - if (urlIndex === urls.length - 1 && condition) { - l('else {') - .in('throw new TypeError(\'Unable to build a path with those params. Supply at least ' + - vars.join(', ') + '\');' - ) - .out('}'); - } - - } else { - l.split(makeL.toString()); - } - }); - l(''); - - return l.toString(); - }, - - writeRequestObjectBody: function (indent, name, body, methods) { - var parts = [], l = lines(indent); - if (~name.indexOf('exists')) { - parts.push('ignore: _.union([404], params.ignore)'); - } else { - parts.push('ignore: params.ignore'); - } - - if (body) { - if (_.contains(['bulk', 'msearch'], name)) { - parts.push('body: this.client.config.serializer.bulkBody(params.body || null)'); - } else { - parts.push('body: params.body || null'); - } - } - - if (methods.length === 1) { - parts.push('method: ' + stringify(methods[0])); - } - - _.each(parts, function (part, i) { - l(part + (i < parts.length - 1 ? ',' : '')); - }); - - return l.toString(); - }, - stringify: stringify, _: _, @@ -254,22 +107,6 @@ var templateGlobals = { } }, - returnStatement: function (indent, name) { - var l = lines(indent); - if (name.match(/(^|\.)exists/)) { - l('this.client.request(request, function (err, response) {') - .in('if (err instanceof errors.NotFound) {') - .in('cb(err, false);') - .out('} else {') - .in('cb(err, true);') - .out('}') - .out('});'); - } else { - l('this.client.request(request, cb);'); - } - return l.toString(); - }, - partials: templates }; @@ -290,6 +127,5 @@ fs.readdirSync(path.resolve(__dirname)).forEach(function (filename) { templates.text = templates.string; module.exports = { - apiFile: templates.api_file, - urlParamRE: urlParamRE + apiFile: templates.api_file }; diff --git a/scripts/stupid-benchmark.js b/scripts/stupid-benchmark.js index 051a72e30..0dfdd114b 100644 --- a/scripts/stupid-benchmark.js +++ b/scripts/stupid-benchmark.js @@ -12,16 +12,16 @@ var client = new es.Client({ maxSockets: 100 }); -console.log('clearing existing "test-docs" indices'); - async.series([ function (done) { + console.log('clearing existing "test-docs" indices'); client.indices.delete({ index: 'test-docs', ignore: 404 }, done); }, function (done) { + console.log('waiting for cluster'); client.cluster.health({ wait_for_status: 'yellow' }, done); @@ -43,4 +43,6 @@ async.series([ } }); } -]); +], function (err) { + if (err) console.error(err); +}); diff --git a/src/lib/api.js b/src/lib/api.js index 5181a5131..25a9e180a 100644 --- a/src/lib/api.js +++ b/src/lib/api.js @@ -1,4 +1,4 @@ -var ca = require('./client_action').create; +var ca = require('./client_action'); var errors = require('./errors'); var api = module.exports = {}; @@ -6,13 +6,14 @@ var api = module.exports = {}; api._namespaces = ['cluster', 'indices']; /** - * Perform a [](http://elasticsearch.org/guide/reference/api/bulk/) request + * Perform a [bulk](http://elasticsearch.org/guide/reference/api/bulk/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} params.consistency - * @param {Boolean} params.refresh - * @param {String} [params.replication=sync] - * @param {String} params.type + * @param {String} params.consistency - Explicit write consistency setting for the operation + * @param {Boolean} params.refresh - Refresh the index after performing the operation + * @param {String} [params.replication=sync] - Explicitely set the replication type + * @param {String} params.type - Default document type for items which don't provide one + * @param {String} params.index - Default index for items which don't provide one */ api.bulk = ca({ methods: [ @@ -72,9 +73,10 @@ api.bulk = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/search/scroll/) request + * Perform a [clear_scroll](http://www.elasticsearch.org/guide/reference/api/search/scroll/) request * * @param {Object} params - An object with parameters used to carry out this action + * @param {String|ArrayOfStrings|Boolean} params.scroll_id - A comma-separated list of scroll IDs to clear */ api.clearScroll = ca({ methods: [ @@ -103,7 +105,7 @@ api.cluster = function ClusterNS(client) { }; /** - * Perform a [](http://elasticsearch.org/guide/reference/api/admin-cluster-update-settings/) request + * Perform a [cluster.get_settings](http://elasticsearch.org/guide/reference/api/admin-cluster-update-settings/) request * * @param {Object} params - An object with parameters used to carry out this action */ @@ -121,17 +123,18 @@ api.cluster.prototype.getSettings = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/admin-cluster-health/) request + * Perform a [cluster.health](http://elasticsearch.org/guide/reference/api/admin-cluster-health/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} [params.level=cluster] - * @param {Boolean} params.local - * @param {Date|Number} params.master_timeout - * @param {Date|Number} params.timeout - * @param {Number} params.wait_for_active_shards - * @param {String} params.wait_for_nodes - * @param {Number} params.wait_for_relocating_shards - * @param {String} params.wait_for_status + * @param {String} [params.level=cluster] - Specify the level of detail for returned information + * @param {Boolean} params.local - Return local information, do not retrieve the state from master node (default: false) + * @param {Date|Number} params.master_timeout - Explicit operation timeout for connection to master node + * @param {Date|Number} params.timeout - Explicit operation timeout + * @param {Number} params.wait_for_active_shards - Wait until the specified number of shards is active + * @param {String} params.wait_for_nodes - Wait until the specified number of nodes is available + * @param {Number} params.wait_for_relocating_shards - Wait until the specified number of relocating shards is finished + * @param {String} params.wait_for_status - Wait until cluster is in a specific state + * @param {String} params.index - Limit the information returned to a specific index */ api.cluster.prototype.health = ca({ methods: [ @@ -192,13 +195,14 @@ api.cluster.prototype.health = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-cluster-nodes-hot-threads/) request + * Perform a [cluster.node_hot_threads](http://www.elasticsearch.org/guide/reference/api/admin-cluster-nodes-hot-threads/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Date|Number} params.interval - * @param {Number} params.snapshots - * @param {Number} params.threads - * @param {String} params.type + * @param {Date|Number} params.interval - The interval for the second sampling of threads + * @param {Number} params.snapshots - Number of samples of thread stacktrace (default: 10) + * @param {Number} params.threads - Specify the number of threads to provide information for (default: 3) + * @param {String} params.type - The type to sample (default: cpu) + * @param {String|ArrayOfStrings|Boolean} params.node_id - A comma-separated list of node IDs or names to limit the returned information; use `_local` to return information from the node you're connecting to, leave empty to get information from all nodes */ api.cluster.prototype.nodeHotThreads = ca({ methods: [ @@ -240,21 +244,22 @@ api.cluster.prototype.nodeHotThreads = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/admin-cluster-nodes-info/) request + * Perform a [cluster.node_info](http://elasticsearch.org/guide/reference/api/admin-cluster-nodes-info/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Boolean} params.all - * @param {Boolean} params.clear - * @param {Boolean} params.http - * @param {Boolean} params.jvm - * @param {Boolean} params.network - * @param {Boolean} params.os - * @param {Boolean} params.plugin - * @param {Boolean} params.process - * @param {Boolean} params.settings - * @param {Boolean} params.thread_pool - * @param {Date|Number} params.timeout - * @param {Boolean} params.transport + * @param {Boolean} params.all - Return all available information + * @param {Boolean} params.clear - Reset the default settings + * @param {Boolean} params.http - Return information about HTTP + * @param {Boolean} params.jvm - Return information about the JVM + * @param {Boolean} params.network - Return information about network + * @param {Boolean} params.os - Return information about the operating system + * @param {Boolean} params.plugin - Return information about plugins + * @param {Boolean} params.process - Return information about the Elasticsearch process + * @param {Boolean} params.settings - Return information about node settings + * @param {Boolean} params.thread_pool - Return information about the thread pool + * @param {Date|Number} params.timeout - Explicit operation timeout + * @param {Boolean} params.transport - Return information about transport + * @param {String|ArrayOfStrings|Boolean} params.node_id - A comma-separated list of node IDs or names to limit the returned information; use `_local` to return information from the node you're connecting to, leave empty to get information from all nodes */ api.cluster.prototype.nodeInfo = ca({ methods: [ @@ -315,11 +320,12 @@ api.cluster.prototype.nodeInfo = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/admin-cluster-nodes-shutdown/) request + * Perform a [cluster.node_shutdown](http://elasticsearch.org/guide/reference/api/admin-cluster-nodes-shutdown/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Date|Number} params.delay - * @param {Boolean} params.exit + * @param {Date|Number} params.delay - Set the delay for the operation (default: 1s) + * @param {Boolean} params.exit - Exit the JVM as well (default: true) + * @param {String|ArrayOfStrings|Boolean} params.node_id - A comma-separated list of node IDs or names to perform the operation on; use `_local` to perform the operation on the node you're connected to, leave empty to perform the operation on all nodes */ api.cluster.prototype.nodeShutdown = ca({ methods: [ @@ -350,21 +356,24 @@ api.cluster.prototype.nodeShutdown = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/admin-cluster-nodes-stats/) request + * Perform a [cluster.node_stats](http://elasticsearch.org/guide/reference/api/admin-cluster-nodes-stats/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Boolean} params.all - * @param {Boolean} params.clear - * @param {String|ArrayOfStrings|Boolean} params.fields - * @param {Boolean} params.fs - * @param {Boolean} params.http - * @param {Boolean} params.indices - * @param {Boolean} params.jvm - * @param {Boolean} params.network - * @param {Boolean} params.os - * @param {Boolean} params.process - * @param {Boolean} params.thread_pool - * @param {Boolean} params.transport + * @param {Boolean} params.all - Return all available information + * @param {Boolean} params.clear - Reset the default level of detail + * @param {String|ArrayOfStrings|Boolean} params.fields - A comma-separated list of fields to return detailed information for, when returning the `indices` metric family (supports wildcards) + * @param {Boolean} params.fs - Return information about the filesystem + * @param {Boolean} params.http - Return information about HTTP + * @param {Boolean} params.indices - Return information about indices + * @param {Boolean} params.jvm - Return information about the JVM + * @param {Boolean} params.network - Return information about network + * @param {Boolean} params.os - Return information about the operating system + * @param {Boolean} params.process - Return information about the Elasticsearch process + * @param {Boolean} params.thread_pool - Return information about the thread pool + * @param {Boolean} params.transport - Return information about transport + * @param {String} params.metric_family - Limit the information returned to a certain metric family + * @param {String} params.metric - Limit the information returned for `indices` family to a specific metric + * @param {String|ArrayOfStrings|Boolean} params.node_id - A comma-separated list of node IDs or names to limit the returned information; use `_local` to return information from the node you're connecting to, leave empty to get information from all nodes */ api.cluster.prototype.nodeStats = ca({ methods: [ @@ -425,7 +434,7 @@ api.cluster.prototype.nodeStats = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/admin-cluster-update-settings/) request + * Perform a [cluster.put_settings](http://elasticsearch.org/guide/reference/api/admin-cluster-update-settings/) request * * @param {Object} params - An object with parameters used to carry out this action */ @@ -443,11 +452,11 @@ api.cluster.prototype.putSettings = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/admin-cluster-reroute/) request + * Perform a [cluster.reroute](http://elasticsearch.org/guide/reference/api/admin-cluster-reroute/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Boolean} params.dry_run - * @param {Boolean} params.filter_metadata + * @param {Boolean} params.dry_run - Simulate the operation only and return the resulting state + * @param {Boolean} params.filter_metadata - Don't return cluster state metadata (default: false) */ api.cluster.prototype.reroute = ca({ methods: [ @@ -470,17 +479,17 @@ api.cluster.prototype.reroute = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/admin-cluster-state/) request + * Perform a [cluster.state](http://elasticsearch.org/guide/reference/api/admin-cluster-state/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Boolean} params.filter_blocks - * @param {Boolean} params.filter_index_templates - * @param {String|ArrayOfStrings|Boolean} params.filter_indices - * @param {Boolean} params.filter_metadata - * @param {Boolean} params.filter_nodes - * @param {Boolean} params.filter_routing_table - * @param {Boolean} params.local - * @param {Date|Number} params.master_timeout + * @param {Boolean} params.filter_blocks - Do not return information about blocks + * @param {Boolean} params.filter_index_templates - Do not return information about index templates + * @param {String|ArrayOfStrings|Boolean} params.filter_indices - Limit returned metadata information to specific indices + * @param {Boolean} params.filter_metadata - Do not return information about indices metadata + * @param {Boolean} params.filter_nodes - Do not return information about nodes + * @param {Boolean} params.filter_routing_table - Do not return information about shard allocation (`routing_table` and `routing_nodes`) + * @param {Boolean} params.local - Return local information, do not retrieve the state from master node (default: false) + * @param {Date|Number} params.master_timeout - Specify timeout for connection to master */ api.cluster.prototype.state = ca({ methods: [ @@ -521,14 +530,16 @@ api.cluster.prototype.state = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/count/) request + * Perform a [count](http://elasticsearch.org/guide/reference/api/count/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} [params.ignore_indices=none] - * @param {Number} params.min_score - * @param {String} params.preference - * @param {String} params.routing - * @param {String} params.source + * @param {String} [params.ignore_indices=none] - When performed on multiple indices, allows to ignore `missing` ones + * @param {Number} params.min_score - Include only documents with a specific `_score` value in the result + * @param {String} params.preference - Specify the node or shard the operation should be performed on (default: random) + * @param {String} params.routing - Specific routing value + * @param {String} params.source - The URL-encoded query definition (instead of using the request body) + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of indices to restrict the results + * @param {String|ArrayOfStrings|Boolean} params.type - A comma-separated list of types to restrict the results */ api.count = ca({ methods: [ @@ -585,21 +596,23 @@ api.count = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/index_/) request + * Perform a [create](http://elasticsearch.org/guide/reference/api/index_/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} params.consistency - * @param {String} params.id - * @param {String} params.parent - * @param {String} params.percolate - * @param {Boolean} params.refresh - * @param {String} [params.replication=sync] - * @param {String} params.routing - * @param {Date|Number} params.timeout - * @param {Date|Number} params.timestamp - * @param {Duration} params.ttl - * @param {Number} params.version - * @param {String} params.version_type + * @param {String} params.consistency - Explicit write consistency setting for the operation + * @param {String} params.id - Document ID + * @param {String} params.parent - ID of the parent document + * @param {String} params.percolate - Percolator queries to execute while indexing the document + * @param {Boolean} params.refresh - Refresh the index after performing the operation + * @param {String} [params.replication=sync] - Specific replication type + * @param {String} params.routing - Specific routing value + * @param {Date|Number} params.timeout - Explicit operation timeout + * @param {Date|Number} params.timestamp - Explicit timestamp for the document + * @param {Duration} params.ttl - Expiration time for the document + * @param {Number} params.version - Explicit version number for concurrency control + * @param {String} params.version_type - Specific version type + * @param {String} params.index - The name of the index + * @param {String} params.type - The type of the document */ api.create = ca({ methods: [ @@ -689,17 +702,20 @@ api.create = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/delete/) request + * Perform a [delete](http://elasticsearch.org/guide/reference/api/delete/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} params.consistency - * @param {String} params.parent - * @param {Boolean} params.refresh - * @param {String} [params.replication=sync] - * @param {String} params.routing - * @param {Date|Number} params.timeout - * @param {Number} params.version - * @param {String} params.version_type + * @param {String} params.consistency - Specific write consistency setting for the operation + * @param {String} params.parent - ID of parent document + * @param {Boolean} params.refresh - Refresh the index after performing the operation + * @param {String} [params.replication=sync] - Specific replication type + * @param {String} params.routing - Specific routing value + * @param {Date|Number} params.timeout - Explicit operation timeout + * @param {Number} params.version - Explicit version number for concurrency control + * @param {String} params.version_type - Specific version type + * @param {String} params.id - The document ID + * @param {String} params.index - The name of the index + * @param {String} params.type - The type of the document */ api['delete'] = ca({ methods: [ @@ -765,19 +781,21 @@ api['delete'] = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/delete-by-query/) request + * Perform a [delete_by_query](http://www.elasticsearch.org/guide/reference/api/delete-by-query/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} params.analyzer - * @param {String} params.consistency - * @param {String} [params.default_operator=OR] - * @param {String} params.df - * @param {String} [params.ignore_indices=none] - * @param {String} [params.replication=sync] - * @param {String} params.q - * @param {String} params.routing - * @param {String} params.source - * @param {Date|Number} params.timeout + * @param {String} params.analyzer - The analyzer to use for the query string + * @param {String} params.consistency - Specific write consistency setting for the operation + * @param {String} [params.default_operator=OR] - The default operator for query string query (AND or OR) + * @param {String} params.df - The field to use as default where no field prefix is given in the query string + * @param {String} [params.ignore_indices=none] - When performed on multiple indices, allows to ignore `missing` ones + * @param {String} [params.replication=sync] - Specific replication type + * @param {String} params.q - Query in the Lucene query string syntax + * @param {String} params.routing - Specific routing value + * @param {String} params.source - The URL-encoded query definition (instead of using the request body) + * @param {Date|Number} params.timeout - Explicit operation timeout + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of indices to restrict the operation; use `_all` to perform the operation on all indices + * @param {String|ArrayOfStrings|Boolean} params.type - A comma-separated list of types to restrict the operation */ api.deleteByQuery = ca({ methods: [ @@ -860,14 +878,17 @@ api.deleteByQuery = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/get/) request + * Perform a [exists](http://elasticsearch.org/guide/reference/api/get/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} params.parent - * @param {String} params.preference - * @param {Boolean} params.realtime - * @param {Boolean} params.refresh - * @param {String} params.routing + * @param {String} params.parent - The ID of the parent document + * @param {String} params.preference - Specify the node or shard the operation should be performed on (default: random) + * @param {Boolean} params.realtime - Specify whether to perform the operation in realtime or search mode + * @param {Boolean} params.refresh - Refresh the shard containing the document before performing the operation + * @param {String} params.routing - Specific routing value + * @param {String} params.id - The document ID + * @param {String} params.index - The name of the index + * @param {String} [params.type=_all] - The type of the document (use `_all` to fetch the first document matching the ID across all types) */ api.exists = ca({ methods: [ @@ -909,29 +930,32 @@ api.exists = ca({ } } ], - castNotFound: true + castExists: true }); /** - * Perform a [](http://elasticsearch.org/guide/reference/api/explain/) request + * Perform a [explain](http://elasticsearch.org/guide/reference/api/explain/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Boolean} params.analyze_wildcard - * @param {String} params.analyzer - * @param {String} [params.default_operator=OR] - * @param {String} params.df - * @param {String|ArrayOfStrings|Boolean} params.fields - * @param {Boolean} params.lenient - * @param {Boolean} params.lowercase_expanded_terms - * @param {String} params.parent - * @param {String} params.preference - * @param {String} params.q - * @param {String} params.routing - * @param {String} params.source - * @param {String|ArrayOfStrings|Boolean} params._source - * @param {String|ArrayOfStrings|Boolean} params._source_exclude - * @param {String|ArrayOfStrings|Boolean} params._source_include + * @param {Boolean} params.analyze_wildcard - Specify whether wildcards and prefix queries in the query string query should be analyzed (default: false) + * @param {String} params.analyzer - The analyzer for the query string query + * @param {String} [params.default_operator=OR] - The default operator for query string query (AND or OR) + * @param {String} params.df - The default field for query string query (default: _all) + * @param {String|ArrayOfStrings|Boolean} params.fields - A comma-separated list of fields to return in the response + * @param {Boolean} params.lenient - Specify whether format-based query failures (such as providing text to a numeric field) should be ignored + * @param {Boolean} params.lowercase_expanded_terms - Specify whether query terms should be lowercased + * @param {String} params.parent - The ID of the parent document + * @param {String} params.preference - Specify the node or shard the operation should be performed on (default: random) + * @param {String} params.q - Query in the Lucene query string syntax + * @param {String} params.routing - Specific routing value + * @param {String} params.source - The URL-encoded query definition (instead of using the request body) + * @param {String|ArrayOfStrings|Boolean} params._source - True or false to return the _source field or not, or a list of fields to return + * @param {String|ArrayOfStrings|Boolean} params._source_exclude - A list of fields to exclude from the returned _source field + * @param {String|ArrayOfStrings|Boolean} params._source_include - A list of fields to extract and return from the _source field + * @param {String} params.id - The document ID + * @param {String} params.index - The name of the index + * @param {String} params.type - The type of the document */ api.explain = ca({ methods: [ @@ -1010,18 +1034,21 @@ api.explain = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/get/) request + * Perform a [get](http://elasticsearch.org/guide/reference/api/get/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String|ArrayOfStrings|Boolean} params.fields - * @param {String} params.parent - * @param {String} params.preference - * @param {Boolean} params.realtime - * @param {Boolean} params.refresh - * @param {String} params.routing - * @param {String|ArrayOfStrings|Boolean} params._source - * @param {String|ArrayOfStrings|Boolean} params._source_exclude - * @param {String|ArrayOfStrings|Boolean} params._source_include + * @param {String|ArrayOfStrings|Boolean} params.fields - A comma-separated list of fields to return in the response + * @param {String} params.parent - The ID of the parent document + * @param {String} params.preference - Specify the node or shard the operation should be performed on (default: random) + * @param {Boolean} params.realtime - Specify whether to perform the operation in realtime or search mode + * @param {Boolean} params.refresh - Refresh the shard containing the document before performing the operation + * @param {String} params.routing - Specific routing value + * @param {String|ArrayOfStrings|Boolean} params._source - True or false to return the _source field or not, or a list of fields to return + * @param {String|ArrayOfStrings|Boolean} params._source_exclude - A list of fields to exclude from the returned _source field + * @param {String|ArrayOfStrings|Boolean} params._source_include - A list of fields to extract and return from the _source field + * @param {String} params.id - The document ID + * @param {String} params.index - The name of the index + * @param {String} [params.type=_all] - The type of the document (use `_all` to fetch the first document matching the ID across all types) */ api.get = ca({ methods: [ @@ -1079,16 +1106,19 @@ api.get = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/get/) request + * Perform a [get_source](http://elasticsearch.org/guide/reference/api/get/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String|ArrayOfStrings|Boolean} params.exclude - * @param {String|ArrayOfStrings|Boolean} params.include - * @param {String} params.parent - * @param {String} params.preference - * @param {Boolean} params.realtime - * @param {Boolean} params.refresh - * @param {String} params.routing + * @param {String|ArrayOfStrings|Boolean} params.exclude - A list of fields to exclude from the returned _source field + * @param {String|ArrayOfStrings|Boolean} params.include - A list of fields to extract and return from the _source field + * @param {String} params.parent - The ID of the parent document + * @param {String} params.preference - Specify the node or shard the operation should be performed on (default: random) + * @param {Boolean} params.realtime - Specify whether to perform the operation in realtime or search mode + * @param {Boolean} params.refresh - Refresh the shard containing the document before performing the operation + * @param {String} params.routing - Specific routing value + * @param {String} params.id - The document ID + * @param {String} params.index - The name of the index + * @param {String} [params.type=_all] - The type of the document; use `_all` to fetch the first document matching the ID across all types */ api.getSource = ca({ methods: [ @@ -1140,21 +1170,24 @@ api.getSource = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/index_/) request + * Perform a [index](http://elasticsearch.org/guide/reference/api/index_/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} params.consistency - * @param {String} [params.op_type=index] - * @param {String} params.parent - * @param {String} params.percolate - * @param {Boolean} params.refresh - * @param {String} [params.replication=sync] - * @param {String} params.routing - * @param {Date|Number} params.timeout - * @param {Date|Number} params.timestamp - * @param {Duration} params.ttl - * @param {Number} params.version - * @param {String} params.version_type + * @param {String} params.consistency - Explicit write consistency setting for the operation + * @param {String} [params.op_type=index] - Explicit operation type + * @param {String} params.parent - ID of the parent document + * @param {String} params.percolate - Percolator queries to execute while indexing the document + * @param {Boolean} params.refresh - Refresh the index after performing the operation + * @param {String} [params.replication=sync] - Specific replication type + * @param {String} params.routing - Specific routing value + * @param {Date|Number} params.timeout - Explicit operation timeout + * @param {Date|Number} params.timestamp - Explicit timestamp for the document + * @param {Duration} params.ttl - Expiration time for the document + * @param {Number} params.version - Explicit version number for concurrency control + * @param {String} params.version_type - Specific version type + * @param {String} params.id - Document ID + * @param {String} params.index - The name of the index + * @param {String} params.type - The type of the document */ api.index = ca({ methods: [ @@ -1257,17 +1290,17 @@ api.indices = function IndicesNS(client) { }; /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-analyze/) request + * Perform a [indices.analyze](http://www.elasticsearch.org/guide/reference/api/admin-indices-analyze/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} params.analyzer - * @param {String} params.field - * @param {String|ArrayOfStrings|Boolean} params.filters - * @param {String} params.index - * @param {Boolean} params.prefer_local - * @param {String} params.text - * @param {String} params.tokenizer - * @param {String} [params.format=detailed] + * @param {String} params.analyzer - The name of the analyzer to use + * @param {String} params.field - Use the analyzer configured for this field (instead of passing the analyzer name) + * @param {String|ArrayOfStrings|Boolean} params.filters - A comma-separated list of filters to use for the analysis + * @param {String} params.index - The name of the index to scope the operation + * @param {Boolean} params.prefer_local - With `true`, specify that a local shard should be used if available, with `false`, use a random shard (default: true) + * @param {String} params.text - The text on which the analysis should be performed (when request body is not used) + * @param {String} params.tokenizer - The name of the tokenizer to use for the analysis + * @param {String} [params.format=detailed] - Format of the output */ api.indices.prototype.analyze = ca({ methods: [ @@ -1322,20 +1355,20 @@ api.indices.prototype.analyze = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-clearcache/) request + * Perform a [indices.clear_cache](http://www.elasticsearch.org/guide/reference/api/admin-indices-clearcache/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Boolean} params.field_data - * @param {Boolean} params.fielddata - * @param {String|ArrayOfStrings|Boolean} params.fields - * @param {Boolean} params.filter - * @param {Boolean} params.filter_cache - * @param {Boolean} params.filter_keys - * @param {Boolean} params.id - * @param {Boolean} params.id_cache - * @param {String} [params.ignore_indices=none] - * @param {String|ArrayOfStrings|Boolean} params.index - * @param {Boolean} params.recycler + * @param {Boolean} params.field_data - Clear field data + * @param {Boolean} params.fielddata - Clear field data + * @param {String|ArrayOfStrings|Boolean} params.fields - A comma-separated list of fields to clear when using the `field_data` parameter (default: all) + * @param {Boolean} params.filter - Clear filter caches + * @param {Boolean} params.filter_cache - Clear filter caches + * @param {Boolean} params.filter_keys - A comma-separated list of keys to clear when using the `filter_cache` parameter (default: all) + * @param {Boolean} params.id - Clear ID caches for parent/child + * @param {Boolean} params.id_cache - Clear ID caches for parent/child + * @param {String} [params.ignore_indices=none] - When performed on multiple indices, allows to ignore `missing` ones + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index name to limit the operation + * @param {Boolean} params.recycler - Clear the recycler cache */ api.indices.prototype.clearCache = ca({ methods: [ @@ -1399,11 +1432,12 @@ api.indices.prototype.clearCache = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-open-close/) request + * Perform a [indices.close](http://www.elasticsearch.org/guide/reference/api/admin-indices-open-close/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Date|Number} params.timeout - * @param {Date|Number} params.master_timeout + * @param {Date|Number} params.timeout - Explicit operation timeout + * @param {Date|Number} params.master_timeout - Specify timeout for connection to master + * @param {String} params.index - The name of the index */ api.indices.prototype.close = ca({ methods: [ @@ -1431,11 +1465,12 @@ api.indices.prototype.close = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-create-index/) request + * Perform a [indices.create](http://www.elasticsearch.org/guide/reference/api/admin-indices-create-index/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Date|Number} params.timeout - * @param {Date|Number} params.master_timeout + * @param {Date|Number} params.timeout - Explicit operation timeout + * @param {Date|Number} params.master_timeout - Specify timeout for connection to master + * @param {String} params.index - The name of the index */ api.indices.prototype.create = ca({ methods: [ @@ -1464,11 +1499,12 @@ api.indices.prototype.create = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-delete-index/) request + * Perform a [indices.delete](http://www.elasticsearch.org/guide/reference/api/admin-indices-delete-index/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Date|Number} params.timeout - * @param {Date|Number} params.master_timeout + * @param {Date|Number} params.timeout - Explicit operation timeout + * @param {Date|Number} params.master_timeout - Specify timeout for connection to master + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of indices to delete; use `_all` or empty string to delete all indices */ api.indices.prototype['delete'] = ca({ methods: [ @@ -1499,11 +1535,13 @@ api.indices.prototype['delete'] = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request + * Perform a [indices.delete_alias](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Date|Number} params.timeout - * @param {Date|Number} params.master_timeout + * @param {Date|Number} params.timeout - Explicit timestamp for the document + * @param {Date|Number} params.master_timeout - Specify timeout for connection to master + * @param {String} params.index - The name of the index with an alias + * @param {String} params.name - The name of the alias to be deleted */ api.indices.prototype.deleteAlias = ca({ methods: [ @@ -1534,10 +1572,12 @@ api.indices.prototype.deleteAlias = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-delete-mapping/) request + * Perform a [indices.delete_mapping](http://www.elasticsearch.org/guide/reference/api/admin-indices-delete-mapping/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Date|Number} params.master_timeout + * @param {Date|Number} params.master_timeout - Specify timeout for connection to master + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names; use `_all` for all indices + * @param {String} params.type - The name of the document type to delete */ api.indices.prototype.deleteMapping = ca({ methods: [ @@ -1565,11 +1605,12 @@ api.indices.prototype.deleteMapping = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-templates/) request + * Perform a [indices.delete_template](http://www.elasticsearch.org/guide/reference/api/admin-indices-templates/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Date|Number} params.timeout - * @param {Date|Number} params.master_timeout + * @param {Date|Number} params.timeout - Explicit operation timeout + * @param {Date|Number} params.master_timeout - Specify timeout for connection to master + * @param {String} params.name - The name of the template */ api.indices.prototype.deleteTemplate = ca({ methods: [ @@ -1597,10 +1638,13 @@ api.indices.prototype.deleteTemplate = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-warmers/) request + * Perform a [indices.delete_warmer](http://www.elasticsearch.org/guide/reference/api/admin-indices-warmers/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Date|Number} params.master_timeout + * @param {Date|Number} params.master_timeout - Specify timeout for connection to master + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names to register warmer for; use `_all` or empty string to perform the operation on all indices + * @param {String} params.name - The name of the warmer (supports wildcards); leave empty to delete all warmers + * @param {String|ArrayOfStrings|Boolean} params.type - A comma-separated list of document types to register warmer for; use `_all` or empty string to perform the operation on all types */ api.indices.prototype.deleteWarmer = ca({ methods: [ @@ -1650,9 +1694,10 @@ api.indices.prototype.deleteWarmer = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-indices-exists/) request + * Perform a [indices.exists](http://www.elasticsearch.org/guide/reference/api/admin-indices-indices-exists/) request * * @param {Object} params - An object with parameters used to carry out this action + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of indices to check */ api.indices.prototype.exists = ca({ methods: [ @@ -1669,15 +1714,17 @@ api.indices.prototype.exists = ca({ } } ], - castNotFound: true + castExists: true }); /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request + * Perform a [indices.exists_alias](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} [params.ignore_indices=none] + * @param {String} [params.ignore_indices=none] - When performed on multiple indices, allows to ignore `missing` ones + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names to filter aliases + * @param {String|ArrayOfStrings|Boolean} params.name - A comma-separated list of alias names to return */ api.indices.prototype.existsAlias = ca({ methods: [ @@ -1714,15 +1761,17 @@ api.indices.prototype.existsAlias = ca({ } } ], - castNotFound: true + castExists: true }); /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-types-exists/) request + * Perform a [indices.exists_type](http://www.elasticsearch.org/guide/reference/api/admin-indices-types-exists/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} [params.ignore_indices=none] + * @param {String} [params.ignore_indices=none] - When performed on multiple indices, allows to ignore `missing` ones + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names; use `_all` to check the types across all indices + * @param {String|ArrayOfStrings|Boolean} params.type - A comma-separated list of document types to check */ api.indices.prototype.existsType = ca({ methods: [ @@ -1751,18 +1800,19 @@ api.indices.prototype.existsType = ca({ } } ], - castNotFound: true + castExists: true }); /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-flush/) request + * Perform a [indices.flush](http://www.elasticsearch.org/guide/reference/api/admin-indices-flush/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Boolean} params.force - * @param {Boolean} params.full - * @param {String} [params.ignore_indices=none] - * @param {Boolean} params.refresh + * @param {Boolean} params.force - TODO: ? + * @param {Boolean} params.full - TODO: ? + * @param {String} [params.ignore_indices=none] - When performed on multiple indices, allows to ignore `missing` ones + * @param {Boolean} params.refresh - Refresh the index after performing the operation + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names; use `_all` or empty string for all indices */ api.indices.prototype.flush = ca({ methods: [ @@ -1805,10 +1855,12 @@ api.indices.prototype.flush = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request + * Perform a [indices.get_alias](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} [params.ignore_indices=none] + * @param {String} [params.ignore_indices=none] - When performed on multiple indices, allows to ignore `missing` ones + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names to filter aliases + * @param {String|ArrayOfStrings|Boolean} params.name - A comma-separated list of alias names to return */ api.indices.prototype.getAlias = ca({ methods: [ @@ -1849,10 +1901,11 @@ api.indices.prototype.getAlias = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request + * Perform a [indices.get_aliases](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Date|Number} params.timeout + * @param {Date|Number} params.timeout - Explicit operation timeout + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names to filter aliases */ api.indices.prototype.getAliases = ca({ methods: [ @@ -1880,9 +1933,11 @@ api.indices.prototype.getAliases = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-get-mapping/) request + * Perform a [indices.get_mapping](http://www.elasticsearch.org/guide/reference/api/admin-indices-get-mapping/) request * * @param {Object} params - An object with parameters used to carry out this action + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names + * @param {String|ArrayOfStrings|Boolean} params.type - A comma-separated list of document types */ api.indices.prototype.getMapping = ca({ methods: [ @@ -1917,9 +1972,10 @@ api.indices.prototype.getMapping = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-get-settings/) request + * Perform a [indices.get_settings](http://www.elasticsearch.org/guide/reference/api/admin-indices-get-settings/) request * * @param {Object} params - An object with parameters used to carry out this action + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices */ api.indices.prototype.getSettings = ca({ methods: [ @@ -1943,9 +1999,10 @@ api.indices.prototype.getSettings = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-templates/) request + * Perform a [indices.get_template](http://www.elasticsearch.org/guide/reference/api/admin-indices-templates/) request * * @param {Object} params - An object with parameters used to carry out this action + * @param {String} params.name - The name of the template */ api.indices.prototype.getTemplate = ca({ methods: [ @@ -1969,9 +2026,12 @@ api.indices.prototype.getTemplate = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-warmers/) request + * Perform a [indices.get_warmer](http://www.elasticsearch.org/guide/reference/api/admin-indices-warmers/) request * * @param {Object} params - An object with parameters used to carry out this action + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names to restrict the operation; use `_all` to perform the operation on all indices + * @param {String} params.name - The name of the warmer (supports wildcards); leave empty to get all warmers + * @param {String|ArrayOfStrings|Boolean} params.type - A comma-separated list of document types to restrict the operation; leave empty to perform the operation on all types */ api.indices.prototype.getWarmer = ca({ methods: [ @@ -2017,11 +2077,12 @@ api.indices.prototype.getWarmer = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-open-close/) request + * Perform a [indices.open](http://www.elasticsearch.org/guide/reference/api/admin-indices-open-close/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Date|Number} params.timeout - * @param {Date|Number} params.master_timeout + * @param {Date|Number} params.timeout - Explicit operation timeout + * @param {Date|Number} params.master_timeout - Specify timeout for connection to master + * @param {String} params.index - The name of the index */ api.indices.prototype.open = ca({ methods: [ @@ -2049,16 +2110,17 @@ api.indices.prototype.open = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-optimize/) request + * Perform a [indices.optimize](http://www.elasticsearch.org/guide/reference/api/admin-indices-optimize/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Boolean} params.flush - * @param {String} [params.ignore_indices=none] - * @param {Number} params.max_num_segments - * @param {Boolean} params.only_expunge_deletes - * @param {*} params.operation_threading - * @param {Boolean} params.refresh - * @param {Boolean} params.wait_for_merge + * @param {Boolean} params.flush - Specify whether the index should be flushed after performing the operation (default: true) + * @param {String} [params.ignore_indices=none] - When performed on multiple indices, allows to ignore `missing` ones + * @param {Number} params.max_num_segments - The number of segments the index should be merged into (default: dynamic) + * @param {Boolean} params.only_expunge_deletes - Specify whether the operation should only expunge deleted documents + * @param {*} params.operation_threading - TODO: ? + * @param {Boolean} params.refresh - Specify whether the index should be refreshed after performing the operation (default: true) + * @param {Boolean} params.wait_for_merge - Specify whether the request should block until the merge process is finished (default: true) + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices */ api.indices.prototype.optimize = ca({ methods: [ @@ -2108,11 +2170,13 @@ api.indices.prototype.optimize = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request + * Perform a [indices.put_alias](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Date|Number} params.timeout - * @param {Date|Number} params.master_timeout + * @param {Date|Number} params.timeout - Explicit timestamp for the document + * @param {Date|Number} params.master_timeout - Specify timeout for connection to master + * @param {String} params.index - The name of the index with an alias + * @param {String} params.name - The name of the alias to be created or updated */ api.indices.prototype.putAlias = ca({ methods: [ @@ -2162,12 +2226,14 @@ api.indices.prototype.putAlias = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-put-mapping/) request + * Perform a [indices.put_mapping](http://www.elasticsearch.org/guide/reference/api/admin-indices-put-mapping/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Boolean} params.ignore_conflicts - * @param {Date|Number} params.timeout - * @param {Date|Number} params.master_timeout + * @param {Boolean} params.ignore_conflicts - Specify whether to ignore conflicts while updating the mapping (default: false) + * @param {Date|Number} params.timeout - Explicit operation timeout + * @param {Date|Number} params.master_timeout - Specify timeout for connection to master + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names; use `_all` to perform the operation on all indices + * @param {String} params.type - The name of the document type */ api.indices.prototype.putMapping = ca({ methods: [ @@ -2202,10 +2268,11 @@ api.indices.prototype.putMapping = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-update-settings/) request + * Perform a [indices.put_settings](http://www.elasticsearch.org/guide/reference/api/admin-indices-update-settings/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Date|Number} params.master_timeout + * @param {Date|Number} params.master_timeout - Specify timeout for connection to master + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices */ api.indices.prototype.putSettings = ca({ methods: [ @@ -2233,12 +2300,13 @@ api.indices.prototype.putSettings = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-templates/) request + * Perform a [indices.put_template](http://www.elasticsearch.org/guide/reference/api/admin-indices-templates/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Number} params.order - * @param {Date|Number} params.timeout - * @param {Date|Number} params.master_timeout + * @param {Number} params.order - The order for this template when merging multiple matching ones (higher numbers are merged later, overriding the lower numbers) + * @param {Date|Number} params.timeout - Explicit operation timeout + * @param {Date|Number} params.master_timeout - Specify timeout for connection to master + * @param {String} params.name - The name of the template */ api.indices.prototype.putTemplate = ca({ methods: [ @@ -2270,10 +2338,13 @@ api.indices.prototype.putTemplate = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-warmers/) request + * Perform a [indices.put_warmer](http://www.elasticsearch.org/guide/reference/api/admin-indices-warmers/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Date|Number} params.master_timeout + * @param {Date|Number} params.master_timeout - Specify timeout for connection to master + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names to register the warmer for; use `_all` or empty string to perform the operation on all indices + * @param {String} params.name - The name of the warmer + * @param {String|ArrayOfStrings|Boolean} params.type - A comma-separated list of document types to register the warmer for; leave empty to perform the operation on all types */ api.indices.prototype.putWarmer = ca({ methods: [ @@ -2315,11 +2386,12 @@ api.indices.prototype.putWarmer = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-refresh/) request + * Perform a [indices.refresh](http://www.elasticsearch.org/guide/reference/api/admin-indices-refresh/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} [params.ignore_indices=none] - * @param {*} params.operation_threading + * @param {String} [params.ignore_indices=none] - When performed on multiple indices, allows to ignore `missing` ones + * @param {*} params.operation_threading - TODO: ? + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices */ api.indices.prototype.refresh = ca({ methods: [ @@ -2354,11 +2426,12 @@ api.indices.prototype.refresh = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/admin-indices-segments/) request + * Perform a [indices.segments](http://elasticsearch.org/guide/reference/api/admin-indices-segments/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} [params.ignore_indices=none] - * @param {*} params.operation_threading + * @param {String} [params.ignore_indices=none] - When performed on multiple indices, allows to ignore `missing` ones + * @param {*} params.operation_threading - TODO: ? + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices */ api.indices.prototype.segments = ca({ methods: [ @@ -2392,10 +2465,11 @@ api.indices.prototype.segments = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-gateway-snapshot/) request + * Perform a [indices.snapshot_index](http://www.elasticsearch.org/guide/reference/api/admin-indices-gateway-snapshot/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} [params.ignore_indices=none] + * @param {String} [params.ignore_indices=none] - When performed on multiple indices, allows to ignore `missing` ones + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names; use `_all` or empty string for all indices */ api.indices.prototype.snapshotIndex = ca({ methods: [ @@ -2428,29 +2502,33 @@ api.indices.prototype.snapshotIndex = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/admin-indices-stats/) request + * Perform a [indices.stats](http://elasticsearch.org/guide/reference/api/admin-indices-stats/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Boolean} params.all - * @param {Boolean} params.clear - * @param {Boolean} params.completion - * @param {String|ArrayOfStrings|Boolean} params.completion_fields - * @param {Boolean} params.docs - * @param {Boolean} params.fielddata - * @param {String|ArrayOfStrings|Boolean} params.fielddata_fields - * @param {String|ArrayOfStrings|Boolean} params.fields - * @param {Boolean} params.filter_cache - * @param {Boolean} params.flush - * @param {Boolean} params.get - * @param {Boolean} params.groups - * @param {Boolean} params.id_cache - * @param {String} [params.ignore_indices=none] - * @param {Boolean} params.indexing - * @param {Boolean} params.merge - * @param {Boolean} params.refresh - * @param {Boolean} params.search - * @param {Boolean} params.store - * @param {Boolean} params.warmer + * @param {Boolean} params.all - Return all available information + * @param {Boolean} params.clear - Reset the default level of detail + * @param {Boolean} params.completion - Return information about completion suggester stats + * @param {String|ArrayOfStrings|Boolean} params.completion_fields - A comma-separated list of fields for `completion` metric (supports wildcards) + * @param {Boolean} params.docs - Return information about indexed and deleted documents + * @param {Boolean} params.fielddata - Return information about field data + * @param {String|ArrayOfStrings|Boolean} params.fielddata_fields - A comma-separated list of fields for `fielddata` metric (supports wildcards) + * @param {String|ArrayOfStrings|Boolean} params.fields - A comma-separated list of fields to return detailed information for, when returning the `search` statistics + * @param {Boolean} params.filter_cache - Return information about filter cache + * @param {Boolean} params.flush - Return information about flush operations + * @param {Boolean} params.get - Return information about get operations + * @param {Boolean} params.groups - A comma-separated list of search groups for `search` statistics + * @param {Boolean} params.id_cache - Return information about ID cache + * @param {String} [params.ignore_indices=none] - When performed on multiple indices, allows to ignore `missing` ones + * @param {Boolean} params.indexing - Return information about indexing operations + * @param {Boolean} params.merge - Return information about merge operations + * @param {Boolean} params.refresh - Return information about refresh operations + * @param {Boolean} params.search - Return information about search operations; use the `groups` parameter to include information for specific search groups + * @param {Boolean} params.store - Return information about the size of the index + * @param {Boolean} params.warmer - Return information about warmers + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices + * @param {String|ArrayOfStrings|Boolean} params.indexing_types - A comma-separated list of document types to include in the `indexing` statistics + * @param {String} params.metric_family - Limit the information returned to a specific metric + * @param {String|ArrayOfStrings|Boolean} params.search_groups - A comma-separated list of search groups to include in the `search` statistics */ api.indices.prototype.stats = ca({ methods: [ @@ -2540,13 +2618,14 @@ api.indices.prototype.stats = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/admin-indices-status/) request + * Perform a [indices.status](http://elasticsearch.org/guide/reference/api/admin-indices-status/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} [params.ignore_indices=none] - * @param {*} params.operation_threading - * @param {Boolean} params.recovery - * @param {Boolean} params.snapshot + * @param {String} [params.ignore_indices=none] - When performed on multiple indices, allows to ignore `missing` ones + * @param {*} params.operation_threading - TODO: ? + * @param {Boolean} params.recovery - Return information about shard recovery + * @param {Boolean} params.snapshot - TODO: ? + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices */ api.indices.prototype.status = ca({ methods: [ @@ -2586,11 +2665,12 @@ api.indices.prototype.status = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request + * Perform a [indices.update_aliases](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Date|Number} params.timeout - * @param {Date|Number} params.master_timeout + * @param {Date|Number} params.timeout - Request timeout + * @param {Date|Number} params.master_timeout - Specify timeout for connection to master + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names to filter aliases */ api.indices.prototype.updateAliases = ca({ methods: [ @@ -2613,14 +2693,16 @@ api.indices.prototype.updateAliases = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/validate/) request + * Perform a [indices.validate_query](http://www.elasticsearch.org/guide/reference/api/validate/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Boolean} params.explain - * @param {String} [params.ignore_indices=none] - * @param {*} params.operation_threading - * @param {String} params.source - * @param {String} params.q + * @param {Boolean} params.explain - Return detailed information about the error + * @param {String} [params.ignore_indices=none] - When performed on multiple indices, allows to ignore `missing` ones + * @param {*} params.operation_threading - TODO: ? + * @param {String} params.source - The URL-encoded query definition (instead of using the request body) + * @param {String} params.q - Query in the Lucene query string syntax + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names to restrict the operation; use `_all` or empty string to perform the operation on all indices + * @param {String|ArrayOfStrings|Boolean} params.type - A comma-separated list of document types to restrict the operation; leave empty to perform the operation on all types */ api.indices.prototype.validateQuery = ca({ methods: [ @@ -2675,7 +2757,7 @@ api.indices.prototype.validateQuery = ca({ /** - * Perform a [](http://elasticsearch.org/guide/) request + * Perform a [info](http://elasticsearch.org/guide/) request * * @param {Object} params - An object with parameters used to carry out this action */ @@ -2694,16 +2776,18 @@ api.info = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/multi-get/) request + * Perform a [mget](http://elasticsearch.org/guide/reference/api/multi-get/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String|ArrayOfStrings|Boolean} params.fields - * @param {String} params.preference - * @param {Boolean} params.realtime - * @param {Boolean} params.refresh - * @param {String|ArrayOfStrings|Boolean} params._source - * @param {String|ArrayOfStrings|Boolean} params._source_exclude - * @param {String|ArrayOfStrings|Boolean} params._source_include + * @param {String|ArrayOfStrings|Boolean} params.fields - A comma-separated list of fields to return in the response + * @param {String} params.preference - Specify the node or shard the operation should be performed on (default: random) + * @param {Boolean} params.realtime - Specify whether to perform the operation in realtime or search mode + * @param {Boolean} params.refresh - Refresh the shard containing the document before performing the operation + * @param {String|ArrayOfStrings|Boolean} params._source - True or false to return the _source field or not, or a list of fields to return + * @param {String|ArrayOfStrings|Boolean} params._source_exclude - A list of fields to exclude from the returned _source field + * @param {String|ArrayOfStrings|Boolean} params._source_include - A list of fields to extract and return from the _source field + * @param {String} params.index - The name of the index + * @param {String} params.type - The type of the document */ api.mget = ca({ methods: [ @@ -2761,28 +2845,31 @@ api.mget = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/more-like-this/) request + * Perform a [mlt](http://elasticsearch.org/guide/reference/api/more-like-this/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Number} params.boost_terms - * @param {Number} params.max_doc_freq - * @param {Number} params.max_query_terms - * @param {Number} params.max_word_len - * @param {Number} params.min_doc_freq - * @param {Number} params.min_term_freq - * @param {Number} params.min_word_len - * @param {String|ArrayOfStrings|Boolean} params.mlt_fields - * @param {Number} params.percent_terms_to_match - * @param {String} params.routing - * @param {Number} params.search_from - * @param {String|ArrayOfStrings|Boolean} params.search_indices - * @param {String} params.search_query_hint - * @param {String} params.search_scroll - * @param {Number} params.search_size - * @param {String} params.search_source - * @param {String} params.search_type - * @param {String|ArrayOfStrings|Boolean} params.search_types - * @param {String|ArrayOfStrings|Boolean} params.stop_words + * @param {Number} params.boost_terms - The boost factor + * @param {Number} params.max_doc_freq - The word occurrence frequency as count: words with higher occurrence in the corpus will be ignored + * @param {Number} params.max_query_terms - The maximum query terms to be included in the generated query + * @param {Number} params.max_word_len - The minimum length of the word: longer words will be ignored + * @param {Number} params.min_doc_freq - The word occurrence frequency as count: words with lower occurrence in the corpus will be ignored + * @param {Number} params.min_term_freq - The term frequency as percent: terms with lower occurence in the source document will be ignored + * @param {Number} params.min_word_len - The minimum length of the word: shorter words will be ignored + * @param {String|ArrayOfStrings|Boolean} params.mlt_fields - Specific fields to perform the query against + * @param {Number} params.percent_terms_to_match - How many terms have to match in order to consider the document a match (default: 0.3) + * @param {String} params.routing - Specific routing value + * @param {Number} params.search_from - The offset from which to return results + * @param {String|ArrayOfStrings|Boolean} params.search_indices - A comma-separated list of indices to perform the query against (default: the index containing the document) + * @param {String} params.search_query_hint - The search query hint + * @param {String} params.search_scroll - A scroll search request definition + * @param {Number} params.search_size - The number of documents to return (default: 10) + * @param {String} params.search_source - A specific search request definition (instead of using the request body) + * @param {String} params.search_type - Specific search type (eg. `dfs_then_fetch`, `count`, etc) + * @param {String|ArrayOfStrings|Boolean} params.search_types - A comma-separated list of types to perform the query against (default: the same type as the document) + * @param {String|ArrayOfStrings|Boolean} params.stop_words - A list of stop words to be ignored + * @param {String} params.id - The document ID + * @param {String} params.index - The name of the index + * @param {String} params.type - The type of the document (use `_all` to fetch the first document matching the ID across all types) */ api.mlt = ca({ methods: [ @@ -2868,10 +2955,12 @@ api.mlt = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/multi-search/) request + * Perform a [msearch](http://www.elasticsearch.org/guide/reference/api/multi-search/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} params.search_type + * @param {String} params.search_type - Search operation type + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names to use as default + * @param {String|ArrayOfStrings|Boolean} params.type - A comma-separated list of document types to use as default */ api.msearch = ca({ methods: [ @@ -2920,10 +3009,12 @@ api.msearch = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/percolate/) request + * Perform a [percolate](http://elasticsearch.org/guide/reference/api/percolate/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Boolean} params.prefer_local + * @param {Boolean} params.prefer_local - With `true`, specify that a local shard should be used if available, with `false`, use a random shard (default: true) + * @param {String} params.index - The name of the index with a registered percolator query + * @param {String} params.type - The document type */ api.percolate = ca({ methods: [ @@ -2952,11 +3043,11 @@ api.percolate = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/search/scroll/) request + * Perform a [scroll](http://www.elasticsearch.org/guide/reference/api/search/scroll/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {Duration} params.scroll - * @param {String} params.scroll_id + * @param {Duration} params.scroll - Specify how long a consistent view of the index should be maintained for scrolled search + * @param {String} params.scroll_id - The scroll ID */ api.scroll = ca({ methods: [ @@ -2988,38 +3079,40 @@ api.scroll = ca({ /** - * Perform a [](http://www.elasticsearch.org/guide/reference/api/search/) request + * Perform a [search](http://www.elasticsearch.org/guide/reference/api/search/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} params.analyzer - * @param {Boolean} params.analyze_wildcard - * @param {String} [params.default_operator=OR] - * @param {String} params.df - * @param {Boolean} params.explain - * @param {String|ArrayOfStrings|Boolean} params.fields - * @param {Number} params.from - * @param {String} [params.ignore_indices=none] - * @param {String|ArrayOfStrings|Boolean} params.indices_boost - * @param {Boolean} params.lenient - * @param {Boolean} params.lowercase_expanded_terms - * @param {String} params.preference - * @param {String} params.q - * @param {String|ArrayOfStrings|Boolean} params.routing - * @param {Duration} params.scroll - * @param {String} params.search_type - * @param {Number} params.size - * @param {String|ArrayOfStrings|Boolean} params.sort - * @param {String} params.source - * @param {String|ArrayOfStrings|Boolean} params._source - * @param {String|ArrayOfStrings|Boolean} params._source_exclude - * @param {String|ArrayOfStrings|Boolean} params._source_include - * @param {String|ArrayOfStrings|Boolean} params.stats - * @param {String} params.suggest_field - * @param {String} [params.suggest_mode=missing] - * @param {Number} params.suggest_size - * @param {Text} params.suggest_text - * @param {Date|Number} params.timeout - * @param {Boolean} params.version + * @param {String} params.analyzer - The analyzer to use for the query string + * @param {Boolean} params.analyze_wildcard - Specify whether wildcard and prefix queries should be analyzed (default: false) + * @param {String} [params.default_operator=OR] - The default operator for query string query (AND or OR) + * @param {String} params.df - The field to use as default where no field prefix is given in the query string + * @param {Boolean} params.explain - Specify whether to return detailed information about score computation as part of a hit + * @param {String|ArrayOfStrings|Boolean} params.fields - A comma-separated list of fields to return as part of a hit + * @param {Number} params.from - Starting offset (default: 0) + * @param {String} [params.ignore_indices=none] - When performed on multiple indices, allows to ignore `missing` ones + * @param {String|ArrayOfStrings|Boolean} params.indices_boost - Comma-separated list of index boosts + * @param {Boolean} params.lenient - Specify whether format-based query failures (such as providing text to a numeric field) should be ignored + * @param {Boolean} params.lowercase_expanded_terms - Specify whether query terms should be lowercased + * @param {String} params.preference - Specify the node or shard the operation should be performed on (default: random) + * @param {String} params.q - Query in the Lucene query string syntax + * @param {String|ArrayOfStrings|Boolean} params.routing - A comma-separated list of specific routing values + * @param {Duration} params.scroll - Specify how long a consistent view of the index should be maintained for scrolled search + * @param {String} params.search_type - Search operation type + * @param {Number} params.size - Number of hits to return (default: 10) + * @param {String|ArrayOfStrings|Boolean} params.sort - A comma-separated list of : pairs + * @param {String} params.source - The URL-encoded request definition using the Query DSL (instead of using request body) + * @param {String|ArrayOfStrings|Boolean} params._source - True or false to return the _source field or not, or a list of fields to return + * @param {String|ArrayOfStrings|Boolean} params._source_exclude - A list of fields to exclude from the returned _source field + * @param {String|ArrayOfStrings|Boolean} params._source_include - A list of fields to extract and return from the _source field + * @param {String|ArrayOfStrings|Boolean} params.stats - Specific 'tag' of the request for logging and statistical purposes + * @param {String} params.suggest_field - Specify which field to use for suggestions + * @param {String} [params.suggest_mode=missing] - Specify suggest mode + * @param {Number} params.suggest_size - How many suggestions to return in response + * @param {Text} params.suggest_text - The source text for which the suggestions should be returned + * @param {Date|Number} params.timeout - Explicit operation timeout + * @param {Boolean} params.version - Specify whether to return document version as part of a hit + * @param {String|ArrayOfStrings|Boolean} [params.index=_all] - A comma-separated list of index names to search; use `_all` or empty string to perform the operation on all indices + * @param {String|ArrayOfStrings|Boolean} params.type - A comma-separated list of document types to search; leave empty to perform the operation on all types */ api.search = ca({ methods: [ @@ -3168,13 +3261,14 @@ api.search = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/search/suggest/) request + * Perform a [suggest](http://elasticsearch.org/guide/reference/api/search/suggest/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} [params.ignore_indices=none] - * @param {String} params.preference - * @param {String} params.routing - * @param {String} params.source + * @param {String} [params.ignore_indices=none] - When performed on multiple indices, allows to ignore `missing` ones + * @param {String} params.preference - Specify the node or shard the operation should be performed on (default: random) + * @param {String} params.routing - Specific routing value + * @param {String} params.source - The URL-encoded request definition (instead of using request body) + * @param {String|ArrayOfStrings|Boolean} params.index - A comma-separated list of index names to restrict the operation; use `_all` or empty string to perform the operation on all indices */ api.suggest = ca({ methods: [ @@ -3217,24 +3311,27 @@ api.suggest = ca({ /** - * Perform a [](http://elasticsearch.org/guide/reference/api/update/) request + * Perform a [update](http://elasticsearch.org/guide/reference/api/update/) request * * @param {Object} params - An object with parameters used to carry out this action - * @param {String} params.consistency - * @param {String|ArrayOfStrings|Boolean} params.fields - * @param {String} params.lang - * @param {String} params.parent - * @param {String} params.percolate - * @param {Boolean} params.refresh - * @param {String} [params.replication=sync] - * @param {Number} params.retry_on_conflict - * @param {String} params.routing - * @param {*} params.script - * @param {Date|Number} params.timeout - * @param {Date|Number} params.timestamp - * @param {Duration} params.ttl - * @param {Number} params.version - * @param {Number} params.version_type + * @param {String} params.consistency - Explicit write consistency setting for the operation + * @param {String|ArrayOfStrings|Boolean} params.fields - A comma-separated list of fields to return in the response + * @param {String} params.lang - The script language (default: mvel) + * @param {String} params.parent - ID of the parent document + * @param {String} params.percolate - Perform percolation during the operation; use specific registered query name, attribute, or wildcard + * @param {Boolean} params.refresh - Refresh the index after performing the operation + * @param {String} [params.replication=sync] - Specific replication type + * @param {Number} params.retry_on_conflict - Specify how many times should the operation be retried when a conflict occurs (default: 0) + * @param {String} params.routing - Specific routing value + * @param {*} params.script - The URL-encoded script definition (instead of using request body) + * @param {Date|Number} params.timeout - Explicit operation timeout + * @param {Date|Number} params.timestamp - Explicit timestamp for the document + * @param {Duration} params.ttl - Expiration time for the document + * @param {Number} params.version - Explicit version number for concurrency control + * @param {Number} params.version_type - Explicit version number for concurrency control + * @param {String} params.id - Document ID + * @param {String} params.index - The name of the index + * @param {String} params.type - The type of the document */ api.update = ca({ methods: [ diff --git a/src/lib/client.js b/src/lib/client.js index 9822cdea4..8a807a20b 100755 --- a/src/lib/client.js +++ b/src/lib/client.js @@ -32,8 +32,6 @@ module.exports = Client; var _ = require('./utils'); var ClientConfig = require('./client_config'); -var ca = require('./client_action').create; -var errors = require('./errors'); var api = require('./api.js'); function Client(config) { @@ -48,117 +46,13 @@ function Client(config) { }); this.config.client = this; + // instansiate the api's namespaces for (var i = 0; i < this._namespaces.length; i++) { this[this._namespaces[i]] = new this[this._namespaces[i]](this); } } -Client.prototype = api; - -/** - * Perform a request with the client's transport - * - * @method request - * @todo async body writing - * @todo abort - * @todo access to custom headers, modifying of request in general - * @param {object} params - * @param {String} params.url - The url for the request - * @param {String} params.method - The HTTP method for the request - * @param {String} params.body - The body of the HTTP request - * @param {Function} cb - A function to call back with (error, responseBody, responseStatus) - */ -Client.prototype.request = function (params, cb) { - var serializer = this.config.serializer; - - // in cb isn't a function make it one - cb = typeof cb === 'function' ? cb : _.noop; - - var connectionPool = this.config.connectionPool; - var log = this.config.log; - var remainingRetries = this.config.maxRetries; - var connection; - - log.debug('starting request', params); - - // get ignore and ensure that it's an array - var ignore = params.ignore; - if (ignore && !_.isArray(ignore)) { - ignore = [ignore]; - } - - // serialize the body - if (params.body) { - params.body = params.bulkBody ? serializer.bulkBody(params.body) : serializer.serialize(params.body); - } - - if (params.body && params.method === 'GET') { - respond(new TypeError('Body can not be sent with method "GET"')); - return; - } - - function sendRequestWithConnection(err, _connection) { - if (err) { - log.error(err); - respond(err); - } else if (_connection) { - connection = _connection; - log.info('Selected', _connection.status, 'Connection, making request'); - connection.request(params, checkRespForFailure); - } else { - log.warning('No living connections'); - respond(new errors.ConnectionFault('No living connections.')); - } - } - - function checkRespForFailure(err, reqParams, body, status) { - connection.setStatus(err ? 'dead' : 'alive'); - - if (err) { - log.error(err); - } - - if (err && remainingRetries) { - remainingRetries--; - log.info('Connection error, retrying'); - connectionPool.select(sendRequestWithConnection); - } else { - log.info('Request complete'); - respond(err, reqParams, body, status); - } - } - - function respond(err, reqParams, body, status) { - var parsedBody = null; - if (reqParams) { - log.trace(reqParams.method, reqParams, params.body, body, status); - } - if (!err) { - if (body) { - parsedBody = serializer.unserialize(body); - if (!parsedBody) { - err = new errors.ParseError(); - } - } else if (reqParams.method === 'HEAD') { - parsedBody = (status === 200); - } - } - - if (err) { - cb(err, parsedBody, status); - } else if ((status >= 200 && status < 300) || ignore && _.contains(ignore, status)) { - cb(void 0, parsedBody, status); - } else { - if (errors[status]) { - cb(new errors[status](parsedBody.error), parsedBody, status); - } else { - cb(new errors.Generic('unknown error'), parsedBody, status); - } - } - } - - connectionPool.select(sendRequestWithConnection); -}; +Client.prototype = _.clone(api); /** * Ping some node to ensure that the cluster is available in some respect @@ -166,44 +60,18 @@ Client.prototype.request = function (params, cb) { * @param {Object} params - Currently just a placeholder, no params used at this time * @param {Function} cb - callback */ -Client.prototype.ping = ca({ - methods: ['HEAD'], - params: {}, - url: { - fmt: '/' - } - }); +Client.prototype.ping = function (params, cb) { + if (typeof params === 'function') { + cb = params; + params = {}; + } -/** - * Ask an ES node for a list of all the nodes, add/remove nodes from the connection - * pool as appropriate - * - * @param {Function} cb - Function to call back once complete - */ -Client.prototype.sniff = function (cb) { - var config = this.config; - - // make cb a function if it isn't - cb = typeof cb === 'function' ? cb : _.noop; - - this.request({ - path: '/_cluster/nodes', - method: 'GET' - }, function (err, resp) { - if (!err && resp && resp.nodes) { - var nodes = config.nodesToHostCallback(resp.nodes); - config.connectionPool.setNodes(nodes); - } - cb(err, resp); - }); + this.config.transport.request({ + method: 'HEAD', + path: '/' + }, cb); }; - -/** - * Shutdown the connections, log outputs, and clear timers - */ Client.prototype.close = function () { - this.config.log.close(); - this.config.connectionPool.close(); + this.config.close(); }; - diff --git a/src/lib/client_action.js b/src/lib/client_action.js index 7697307b7..1a4532597 100644 --- a/src/lib/client_action.js +++ b/src/lib/client_action.js @@ -2,14 +2,13 @@ * Constructs a function that can be called to make a request to ES * @type {[type]} */ -exports.create = function clientAction(spec) { +module.exports = function ClientAction(spec, client) { return function (params, cb) { - return exec(this.client, spec, params, cb); + return exec((client || this.client).config.transport, spec, params, cb); }; }; var errors = require('./errors'); - var _ = require('./utils'); var urlParamRE = /\{(\w+)\}/g; @@ -130,7 +129,7 @@ function resolveUrl(url, params) { }, {})); } -function exec(client, spec, params, cb) { +function exec(transport, spec, params, cb) { if (typeof params === 'function') { cb = params; params = {}; @@ -148,17 +147,13 @@ function exec(client, spec, params, cb) { return _.nextTick(cb, new TypeError('A request body is required.')); } - if (params.body) { - request.body = params.body; - } + params.body && (request.body = params.body); + params.ignore && (request.ignore = _.isArray(params.ignore) ? params.ignore : [params.ignore]); + params.timeout && (request.ignore = _.isArray(params.ignore) ? params.ignore : [params.ignore]); - if (spec.bulkBody) { - request.bulkBody = true; - } - - if (params.ignore) { - request.ignore = _.isArray(params.ignore) ? params.ignore : [params.ignore]; - } + // copy over some properties from the spec + spec.bulkBody && (request.bulkBody = true); + spec.castExists && (request.castExists = true); if (spec.methods.length === 1) { request.method = spec.methods[0]; @@ -230,17 +225,7 @@ function exec(client, spec, params, cb) { } } - request.path = request.path + _.makeQueryString(query); + request.query = query; - if (spec.castNotFound) { - client.request(request, function (err, response) { - if (err instanceof errors.NotFound) { - cb(null, false); - } else { - cb(err, !err); - } - }); - } else { - client.request(request, cb); - } + transport.request(request, cb); } diff --git a/src/lib/client_config.js b/src/lib/client_config.js index 225b8574b..6e99c7260 100644 --- a/src/lib/client_config.js +++ b/src/lib/client_config.js @@ -8,24 +8,30 @@ module.exports = ClientConfig; var url = require('url'); var _ = require('./utils'); +var Host = require('./host'); var selectors = _.reKey(_.requireDir(module, './selectors'), _.camelCase); var connections = _.requireClasses(module, './connections'); var serializers = _.requireClasses(module, './serializers'); -var ConnectionPool = require('./connection_pool'); -var Log = require('./log'); var extractHostPartsRE = /\[([^:]+):(\d+)]/; var hostProtocolRE = /^([a-z]+:)?\/\//; +var defaultClasses = { + log: require('./log'), + serializer: serializers.Json, + connectionPool: require('./connection_pool'), + transport: require('./transport'), +}; + var defaultConfig = { hosts: [ { - protocol: 'http:', - hostname: 'localhost', - port: 9200 + host: 'localhost', + port: 9200, + protocol: 'http' } ], - connectionConstructor: 'Http', + connectionClass: connections.Http, selector: selectors.roundRobin, sniffOnStart: false, sniffAfterRequests: null, @@ -37,14 +43,16 @@ var defaultConfig = { nodesToHostCallback: function (nodes) { var hosts = []; _.each(nodes, function (node, id) { - var hostnameMatches = extractHostPartsRE.exec(node.hostname); + var hostnameMatches = extractHostPartsRE.exec(node.host); hosts.push({ - hostname: hostnameMatches[1], + host: hostnameMatches[1], port: hostnameMatches[2], - id: id, - name: node.name, - servername: node.hostname, - version: node.version + _meta: { + id: id, + name: node.name, + servername: node.host, + version: node.version + } }); }); return hosts; @@ -54,13 +62,13 @@ var defaultConfig = { function ClientConfig(config) { _.extend(this, defaultConfig, config); - // validate connectionConstructor - if (typeof this.connectionConstructor !== 'function') { - if (_.has(connections, this.connectionConstructor)) { - this.connectionConstructor = connections[this.connectionConstructor]; + // validate connectionClass + if (typeof this.connectionClass !== 'function') { + if (typeof connections[this.connectionClass] === 'function') { + this.connectionClass = connections[this.connectionClass]; } else { - throw new TypeError('Invalid connectionConstructor ' + this.connectionConstructor + - ', specify a function or one of ' + _.keys(connections).join(', ')); + throw new TypeError('Invalid connectionClass ' + this.connectionClass + '. ' + + 'Expected a constructor or one of ' + _.keys(connections).join(', ')); } } @@ -74,10 +82,9 @@ function ClientConfig(config) { } } - // currently not configurable because! - this.log = new Log(this); - this.connectionPool = new ConnectionPool(this); - this.serializer = new serializers.Json(this); + _.each(defaultClasses, function (DefaultClass, prop) { + this[prop] = typeof this[prop] === 'function' ? new this[prop](this) : new DefaultClass(this); + }, this); // populate the connection pool this.connectionPool.setNodes(this.prepareHosts(this.hosts)); @@ -95,49 +102,15 @@ ClientConfig.prototype.prepareHosts = function (hosts) { hosts = [hosts]; } - for (i = 0; i < hosts.length; i++) { - host = hosts[i]; - if (typeof host === 'object') { - if (host.protocol) { - // the protocol must end in a color - if (host.protocol[host.protocol.length - 1] !== ':') { - host.protocol = host.protocol + ':'; - } - } else { - host.protocol = 'http:'; - } - - if (host.host && !host.hostname) { - // utl.format && url.parse uses "hostname" to represent just the name of the host, "host" is "hostname + port" - host.hostname = host.host; - delete host.host; - } - - if (!host.hostname) { - host.hostname = 'localhost'; - } - - if (!host.port) { - host.port = 9200; - } - } else { - // assume it is a string. - - if (!hostProtocolRE.test(host)) { - // add a defaul protocol - host = 'http://' + host; - } - - // parse the url please, node - var urlInfo = url.parse(host, false, true); - - // override the host value - hosts[i] = { - protocol: urlInfo.protocol || 'http:', - hostname: urlInfo.hostname || 'localhost', - port: urlInfo.port || 9200 - }; - } - } - return hosts; + return _.map(hosts, function (host) { + return new Host(host); + }); +}; + +/** + * Shutdown the connections, log outputs, and clear timers + */ +ClientConfig.prototype.close = function () { + this.log.close(); + this.connectionPool.close(); }; diff --git a/src/lib/connection.js b/src/lib/connection.js index d5facb8d0..a48e29859 100644 --- a/src/lib/connection.js +++ b/src/lib/connection.js @@ -5,18 +5,18 @@ var _ = require('./utils'), /** * Abstract class used for Connection classes - * @param client {Client} - The client that this connection belongs to - * @param config {Object} - a map of configuration details for this connection - * @param [config.hostname=localhost] {String} - The hostname for the node this connection connects to - * @param [config.port=9200] {Integer} - The port on the server that ES is listening to * @class ConnectionAbstract * @constructor */ -function ConnectionAbstract(config, nodeInfo) { +function ConnectionAbstract(host, config) { EventEmitter.call(this); this.config = config; - this.hostname = nodeInfo.hostname || 'localhost'; - this.port = nodeInfo.port || 9200; + this.host = host; + this.requestCount = 0; + + if (!this.host) { + throw new Error('Missing host config'); + } _.makeBoundMethods(this); } diff --git a/src/lib/connection_pool.js b/src/lib/connection_pool.js index 3510c4a08..874e276e6 100644 --- a/src/lib/connection_pool.js +++ b/src/lib/connection_pool.js @@ -8,11 +8,12 @@ module.exports = ConnectionPool; -var _ = require('./utils'), - selectors = _.reKey(_.requireDir(module, './selectors'), _.camelCase), - connectors = _.reKey(_.requireDir(module, './connections'), _.studlyCase), - EventEmitter = require('events').EventEmitter, - errors = require('./errors'); +var _ = require('./utils'); +var selectors = _.reKey(_.requireDir(module, './selectors'), _.camelCase); +var connectors = _.reKey(_.requireDir(module, './connections'), _.studlyCase); +var EventEmitter = require('events').EventEmitter; +var errors = require('./errors'); +var Host = require('./host'); function ConnectionPool(config) { _.makeBoundMethods(this); @@ -32,6 +33,7 @@ ConnectionPool.prototype.select = function (cb) { try { cb(null, this.config.selector(this.connections.alive)); } catch (e) { + this.config.log.error(e); cb(e); } } @@ -46,7 +48,7 @@ ConnectionPool.prototype.onStatusChanged = _.handler(function (status, oldStatus if (oldStatus === status) { return true; } else { - this.config.log.info('connection to', _.formatUrl(connection), 'is', status); + this.config.log.info('connection id:', connection.__id, 'is', status); } switch (status) { @@ -103,12 +105,12 @@ ConnectionPool.prototype.setNodes = function (nodeConfigs) { for (i = 0; i < nodeConfigs.length; i++) { node = nodeConfigs[i]; - if (node.hostname && node.port) { - id = node.hostname + ':' + node.port; + if (node instanceof Host) { + id = node.toString(); if (this.index[id]) { delete toRemove[id]; } else { - connection = new this.config.connectionConstructor(this.config, nodeConfigs[i]); + connection = new this.config.connectionClass(node, this.config); connection.__id = id; this._add(connection); } diff --git a/src/lib/connections/http.js b/src/lib/connections/http.js index f2b0c2aa9..a04a1b4fb 100644 --- a/src/lib/connections/http.js +++ b/src/lib/connections/http.js @@ -8,22 +8,19 @@ */ module.exports = HttpConnection; -var http = require('http'), - _ = require('../utils'), - errors = require('../errors'), - ConnectionAbstract = require('../connection'), - defaultHeaders = { - 'connection': 'keep-alive' - }; +var http = require('http'); +var https = require('https'); +var _ = require('../utils'); +var errors = require('../errors'); +var qs = require('querystring'); +var ConnectionAbstract = require('../connection'); +var defaultHeaders = { + 'connection': 'keep-alive' +}; -function HttpConnection(config, nodeInfo) { - ConnectionAbstract.call(this, config, nodeInfo); - - this.protocol = nodeInfo.protocol || 'http:'; - if (this.protocol[this.protocol.length - 1] !== ':') { - this.protocol = this.protocol + ':'; - } +function HttpConnection(host, config) { + ConnectionAbstract.call(this, host, config); this.agent = new http.Agent({ keepAlive: true, @@ -35,7 +32,6 @@ function HttpConnection(config, nodeInfo) { this.on('closed', this.bound.onClosed); this.once('alive', this.bound.onAlive); - this.requestCount = 0; } _.inherits(HttpConnection, ConnectionAbstract); @@ -49,41 +45,63 @@ HttpConnection.prototype.onAlive = _.handler(function () { this.agent.maxSockets = this.config.maxSockets; }); +HttpConnection.prototype.makeReqParams = function (params) { + var reqParams = { + method: params.method, + protocol: this.host.protocol + ':', + auth: this.host.auth, + hostname: this.host.host, + port: this.host.port, + path: this.host.path + params.path, + headers: this.host.headers, + agent: this.agent + }; + + var query = qs.stringify(this.host.query ? _.defaults(params.query, this.host.query) : params.query); + reqParams.path += query ? '?' + query : ''; + + return reqParams; +}; + HttpConnection.prototype.request = function (params, cb) { var incoming; var timeoutId; - var log = this.config.log; var request; var requestId = this.requestCount; var response; var responseStarted = false; var status = 0; var timeout = params.timeout || this.config.timeout; + var log = this.config.log; - var reqParams = _.defaults({ - protocol: this.protocol, - hostname: this.hostname, - port: this.port, - path: params.path, - method: _.toUpperString(params.method) || (params.body ? 'POST' : 'GET'), - headers: _.defaults(params.headers || {}, defaultHeaders) - }); + var reqParams = this.makeReqParams(params); - // general clean-up procedure to run after the request, can only run once + // general clean-up procedure to run after the request + // completes, has an error, or is aborted. var cleanUp = function (err) { clearTimeout(timeoutId); request && request.removeAllListeners(); incoming && incoming.removeAllListeners(); - log.debug('calling back request', requestId, err ? 'with error "' + err.message + '"' : ''); - cb(err, reqParams, response, status); + if ((err instanceof Error) === false) { + err = void 0; + } else { + log.error(err); - // override so this doesn't get called again - cleanUp = _.noop; + if (err instanceof errors.RequestTimeout) { + request.on('error', function catchAbortError() { + request.removeListener('error', catchAbortError); + }); + } else { + this.setStatus('dead'); + } + } + + log.trace(params.method, reqParams, params.body, response, status); + cb(err, response, status); }; - reqParams.agent = this.agent; request = http.request(reqParams, function (_incoming) { incoming = _incoming; @@ -95,20 +113,19 @@ HttpConnection.prototype.request = function (params, cb) { response += d; }); - incoming.on('end', function requestComplete() { - cleanUp(); - }); + incoming.on('error', cleanUp); + incoming.on('end', cleanUp); }); - request.on('error', function (err) { - request.abort(); - cleanUp(err); - }); + request.on('error', cleanUp); - // timeout for the entire request. - timeoutId = setTimeout(function () { - request.emit('error', new errors.RequestTimeout('Request timed out at ' + timeout + 'ms')); - }, timeout); + if (timeout !== Infinity) { + // timeout for the entire request. + timeoutId = setTimeout(function () { + request.abort(); + request.emit('error', new errors.RequestTimeout('Request timed out at ' + timeout + 'ms')); + }, timeout); + } request.setNoDelay(true); request.setSocketKeepAlive(true); diff --git a/src/lib/connections/jquery.js b/src/lib/connections/jquery.js index 53a872cb1..2ec541b4a 100644 --- a/src/lib/connections/jquery.js +++ b/src/lib/connections/jquery.js @@ -1,9 +1,16 @@ +/* jshint browser: true, jquery: true */ + +/** + * Simple connection class for using the XHR object in browsers + * + * @class {XhrConnection} + */ module.exports = JqueryConnection; -var _ = require('../utils'), - ConnectionAbstract = require('../connection'); +function JqueryConnection() {} + +JqueryConnection.prototype.request = function (params, cb) { + var $xhr = jQuery.ajax(params).done(cb); +}; -function JqueryConnection() { -} -_.inherits(JqueryConnection, ConnectionAbstract); diff --git a/src/lib/connections/xhr.js b/src/lib/connections/xhr.js index 3ed381af3..2df9952c1 100644 --- a/src/lib/connections/xhr.js +++ b/src/lib/connections/xhr.js @@ -3,13 +3,73 @@ * * @class connections.Xhr */ - module.exports = XhrConnection; -var _ = require('../utils'), - ConnectionAbstract = require('../connection'); +/* jshint browser:true */ -function XhrConnection() { +var _ = require('../utils'); +var ConnectionAbstract = require('../connection'); +var ConnectionError = require('../errors').ConnectionError; +var TimeoutError = require('../errors').TimeoutError; +function XhrConnection(config, nodeInfo) { + ConnectionAbstract.call(this, config, nodeInfo); } _.inherits(XhrConnection, ConnectionAbstract); + +/** + * Simply returns an XHR object cross browser + * @type {Function} + */ +var getXhr = _.noop; + +if (typeof XMLHttpRequest !== 'undefined') { + // rewrite the getXhr method to always return the native implementation + getXhr = function () { + return new XMLHttpRequest(); + }; +} else { + // find the first MS implementation available + getXhr = _.first(['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'], function (appName) { + try { + var test = new window.ActiveXObject(appName); + return function () { + return new window.ActiveXObject(appName); + }; + } catch (e) { + return null; + } + }); +} + +if (!getXhr) { + throw new Error('getXhr(): XMLHttpRequest not available'); +} + +XhrConnection.prototype.request = function (params, cb) { + var xhr = getXhr(); + var timeoutId; + + if (params.auth) { + xhr.open(params.method, params.url, true, params.auth.user, params.auth.pass); + } else { + xhr.open(params.method, params.url, true); + } + + xhr.onreadystatechange = function (e) { + if (xhr.readyState === 4) { + clearTimeout(timeoutId); + cb(xhr.status ? null : new ConnectionError(), xhr.responseText, xhr.status); + } + }; + + if (params.timeout !== Infinity) { + timeoutId = setTimeout(function () { + xhr.onreadystatechange = _.noop; + xhr.abort(); + cb(new TimeoutError()); + }, params.timeout); + } + + xhr.send(params.body || null); +}; diff --git a/src/lib/errors.js b/src/lib/errors.js index 32095fd06..19a94a887 100644 --- a/src/lib/errors.js +++ b/src/lib/errors.js @@ -36,14 +36,15 @@ errors.RequestTimeout = function RequestTimeout(msg) { }; _.inherits(errors.RequestTimeout, ErrorAbstract); + /** * Request Body could not be parsed * @param {String} [msg] - An error message that will probably end up in a log. */ -errors.Serialization = function RequestTimeout(msg) { - ErrorAbstract.call(this, msg || 'Unable to parse response body', errors.RequestTimeout); +errors.Serialization = function Serialization(msg) { + ErrorAbstract.call(this, msg || 'Unable to parse/serialize body', errors.Serialization); }; -_.inherits(errors.RequestTimeout, ErrorAbstract); +_.inherits(errors.Serialization, ErrorAbstract); var statusCodes = { diff --git a/src/lib/host.js b/src/lib/host.js new file mode 100644 index 000000000..daac90965 --- /dev/null +++ b/src/lib/host.js @@ -0,0 +1,65 @@ +/** + * Class to wrap URLS, formatting them and maintaining their seperate details + * @type {[type]} + */ +module.exports = Host; + +var url = require('url'); +var qs = require('querystring'); +var _ = require('./utils'); + +var startsWithProtocolRE = /^([a-z]+:)?\/\//; + +// simple reference used when formatting as a url +var defaultPort = { + http: 80, + https: 443 +}; + +function Host(config) { + if (this instanceof Host) { + if (typeof config === 'string') { + return Host.fromString(config); + } else { + _.extend(this, config || {}); + } + } else { + return new Host(config); + } +} + +Host.fromString = function (urlString) { + if (!startsWithProtocolRE.test(urlString)) { + urlString = 'http://' + urlString; + } + var u = url.parse(urlString, true, true); + return new Host({ + protocol: u.protocol ? u.protocol.substring(0, u.protocol.length - 1) : 'http', + host: u.hostname || 'localhost', + port: u.port || 9200, + auth: u.auth || '', + path: u.pathname, + query: u.query, + }); +}; + +Host.prototype = { + protocol: 'http', + host: 'localhost', + port: 9200, + auth: '', + path: '', + query: {} +}; + +Host.prototype.toUrl = function (path, query) { + if (query) { + query = '?' + qs.stringify(_.defaults(typeof query === 'string' ? qs.parse(query) : query, this.query)); + } else { + query = ''; + } + + return this.protocol + '://' + + this.host + (this.port !== defaultPort[this.protocol] ? ':' + this.port : '') + + '/' + this.path + (path || '') + query; +}; diff --git a/src/lib/log.js b/src/lib/log.js index 26a6974c3..1449a7f3b 100755 --- a/src/lib/log.js +++ b/src/lib/log.js @@ -17,7 +17,7 @@ var _ = require('./utils'), * @param {string} output.type - The name of the logger to use for this output */ function Log(config) { - this.config = config; + this.config = config || {}; var i; var output = config.log || 2; @@ -250,7 +250,7 @@ Log.prototype.debug = function (/* ...msg */) { Log.prototype.trace = function (method, requestUrl, body, responseBody, responseStatus) { if (EventEmitter.listenerCount(this, 'trace')) { if (typeof requestUrl === 'object') { - requestUrl = _.formatUrl(requestUrl); + requestUrl = url.format(requestUrl); } return this.emit('trace', method, requestUrl, body, responseBody, responseStatus); } diff --git a/src/lib/transport.js b/src/lib/transport.js new file mode 100644 index 000000000..efe853fb1 --- /dev/null +++ b/src/lib/transport.js @@ -0,0 +1,54 @@ +/** + * Class that manages making request, called by all of the API methods. + * @type {[type]} + */ +module.exports = Transport; + +var _ = require('./utils'); +var TransportRequest = require('./transport_request'); +var errors = require('./errors'); + +function Transport(config) { + this.config = config; +} + +/** + * Perform a request with the client's transport + * + * @method request + * @todo async body writing + * @todo abort + * @todo access to custom headers, modifying of request in general + * @param {object} params + * @param {String} params.url - The url for the request + * @param {String} params.method - The HTTP method for the request + * @param {String} params.body - The body of the HTTP request + * @param {Function} cb - A function to call back with (error, responseBody, responseStatus) + */ +Transport.prototype.request = function (params, cb) { + return new TransportRequest(this.config, params, cb); +}; + +/** + * Ask an ES node for a list of all the nodes, add/remove nodes from the connection + * pool as appropriate + * + * @param {Function} cb - Function to call back once complete + */ +Transport.prototype.sniff = function (cb) { + var config = this.config; + + // make cb a function if it isn't + cb = typeof cb === 'function' ? cb : _.noop; + + this.request({ + path: '/_cluster/nodes', + method: 'GET' + }, function (err, resp) { + if (!err && resp && resp.nodes) { + var nodes = config.nodesToHostCallback(resp.nodes); + config.connectionPool.setNodes(nodes); + } + cb(err, resp); + }); +}; diff --git a/src/lib/transport_request.js b/src/lib/transport_request.js new file mode 100644 index 000000000..0f0ee9dc1 --- /dev/null +++ b/src/lib/transport_request.js @@ -0,0 +1,147 @@ +/** + * Constructs a function that can be called to make a request to ES + * @type {[type]} + */ +module.exports = TransportRequest; + +var _ = require('./utils'); +var EventEmitter = require('events').EventEmitter; +var errors = require('./errors'); + +function TransportRequest(config, params, cb) { + // setup event emitter + EventEmitter.call(this); + // copy cetain methods into the bound object + _.makeBoundMethods(this); + + this._params = params; + this._log = config.log; + this._serializer = config.serializer; + this._connectionPool = config.connectionPool; + this._remainingRetries = config.maxRetries; + + // in cb isn't a function make it one + if (typeof cb === 'function') { + this.once('done', cb); + } + + this._startRequest(); +} +_.inherits(TransportRequest, EventEmitter); + +TransportRequest.prototype._startRequest = function () { + var params = this._params; + + this._log.debug('starting request', params); + + if (params.body && params.method === 'GET') { + process.nextTick(_.bindKey(this, 'respond', new TypeError('Body can not be sent with method "GET"'))); + return; + } + + // serialize the body + if (params.body) { + params.body = this._serializer[params.bulkBody ? 'bulkBody' : 'serialize'](params.body); + } + + params.req = { + path: params.path, + query: params.query, + method: params.method, + body: params.body, + }; + + this._connectionPool.select(this.bound._sendReqWithCon); +}; + +TransportRequest.prototype._sendReqWithCon = _.handler(function (err, con) { + if (err) { + this._respond(err); + } else if (con) { + this._connection = con; + this._log.info('Selected', con.status, 'Connection, making request'); + this._request = con.request(this._params.req, this.bound._checkRespForFail); + } else { + this._log.warning('No living connections'); + this._respond(new errors.ConnectionFault('No living connections.')); + } +}); + +TransportRequest.prototype._checkRespForFail = _.handler(function (err, body, status) { + if (err && this._remainingRetries) { + this._remainingRetries--; + this._log.info('Connection error, retrying'); + this._connectionPool.select(this.bound._sendReqWithCon); + } else { + this._log.info('Request complete'); + this._respond(err, body, status); + } +}); + +TransportRequest.prototype._respond = _.handler(function (err, body, status) { + if (this._response) { + throw new Error('Request responded twice'); + } + + var parsedBody; + var serializer = this._serializer; + + // get ignore and ensure that it's an array + var ignore = this._params.ignore; + if (ignore && !_.isArray(ignore)) { + ignore = [ignore]; + } + + if (!err && body) { + parsedBody = serializer.unserialize(body); + if (parsedBody == null) { + err = new errors.Serialization(); + } + } + + if (!err) { + if ((status < 200 || status >= 300) && !_.contains(ignore, status)) { + if (errors[status]) { + err = new errors[status](parsedBody && parsedBody.error); + } else { + err = new errors.Generic('unknown error'); + } + } + } + + if (this._params.castExists) { + if (err && err instanceof errors.NotFound) { + parsedBody = false; + err = void 0; + } else { + parsedBody = !err; + } + } + + this._error = err; + this._response = { + body: parsedBody, + status: status + }; + + this.emit('done', this._error, this._response.body, this._response.status); +}); + +TransportRequest.prototype.abort = function () { + this.aborted = true; + if (this.__request) { + this.__request.abort(); + return true; + } + return false; +}; + +TransportRequest.prototype.then = function (callback, errback) { + if (this._error) { + errback(this._error); + } else if (this._response) { + callback(this._response); + } else { + this.once('done', _.bindKey(this, 'then', callback, errback)); + } +}; diff --git a/src/lib/utils.js b/src/lib/utils.js index 11cb1d74c..8d39d11be 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -2,8 +2,6 @@ var path = require('path'), _ = require('lodash'), fs = require('fs'), requireDir = require('require-directory'), - qs = require('querystring'), - url = require('url'), nodeUtils = require('util'); /** @@ -70,7 +68,7 @@ utils.requireClasses = function (module, dirPath) { */ utils.reKey = function (obj, transform, recursive) { // defaults - if (typeof recursive === 'undefined') { recursive = true; } + if (recursive === void 0) { recursive = true; } if (typeof transform !== 'function') { throw new TypeError('invalid transform function'); } var out = {}; @@ -252,19 +250,6 @@ utils.repeat = function (what, times) { return (new Array(times + 1)).join(what); }; -/** - * Convert an object into a query string - * - * @method makeQueryString - * @param {Object} obj - The object to convert - * @param {Boolean} [start=true] - Should the query string start with a '?' - * @return {String} - */ -utils.makeQueryString = function (obj, start) { - var str = qs.stringify(obj); - return (start === false || str === '') ? str : '?' + str; -}; - /** * Override node's util.inherits function to also supply a callSuper function on the child class that can be called * with the instance and the arguments passed to the child's constructor. This should only be called from within the @@ -310,45 +295,6 @@ utils.collectMatches = function (text, regExp) { return matches; }; -var startsWithProtocolRE = /^([a-z]+:)?\/\//; - -/** - * Runs a string through node's url.parse, removing the return value's host property and insuring the text has a - * protocol first - * - * @todo Tests - * @param urlString {String} - a url of some sort - * @returns {Object} - an object containing 'hostname', 'port', 'protocol', 'path', and a few other keys - */ -utils.parseUrl = function (urlString) { - if (!startsWithProtocolRE.text(urlString)) { - urlString = 'http://' + urlString; - } - var info = url.parse(urlString); - return info; -}; - -/** - * Formats a urlinfo object, sort of juggling the 'host' and 'hostname' keys based on the presense of the port and - * including http: as the default protocol. - * - * @todo Tests, - * @todo add checking for ':' at the end of the protocol - * @param urlInfo {Object} - An object, similar to that returned from _.parseUrl - * @returns {String} - */ -utils.formatUrl = function (urlInfo) { - var info = _.pick(urlInfo, ['protocol', 'hostname', 'port']); - if (info.port && urlInfo.host && !info.hostname) { - info.hostname = urlInfo.host; - delete info.host; - } - if (!info.protocol) { - info.protocol = 'http:'; - } - return url.format(info); -}; - /** * Call a function, applying the arguments object to it in an optimized way, rather than always turning it into an array * @@ -425,7 +371,7 @@ _.scheduled = _.handler; * ``` * * @param {Object} obj - The object to bind the methods to - * @param {Array} [methods] - The methods to bind, false values === bind them all + * @param {Array} [methods] - The methods to bind, false values === bind all flagged with _provideBound */ _.makeBoundMethods = function (obj, methods) { obj.bound = {}; diff --git a/test/integration/yaml_suite/index.js b/test/integration/yaml_suite/index.js index 04521c765..d368b768f 100644 --- a/test/integration/yaml_suite/index.js +++ b/test/integration/yaml_suite/index.js @@ -12,7 +12,7 @@ var argv = require('optimist') .default('executable', process.env.ES_HOME ? path.join(process.env.ES_HOME, './bin/elasticsearch') : null) .default('clusterName', 'yaml-test-runner') .default('dataPath', '/tmp/yaml-test-runner') - .default('hostname', 'localhost') + .default('host', 'localhost') .default('port', '9200') .default('match', '**') .boolean('createServer') @@ -49,7 +49,7 @@ function createClient() { client = new es.Client({ hosts: [ { - hostname: esServer ? esServer.__hostname : argv.hostname, + host: esServer ? esServer.__hostname : argv.host, port: esServer ? esServer.__port : argv.port } ], @@ -343,7 +343,7 @@ ActionRunner.prototype = { , remainingSteps; for (i = 0; from != null && i < steps.length; i++) { - if (typeof from[steps[i]] === 'undefined') { + if (from[steps[i]] === void 0) { remainingSteps = steps.slice(i).join('.').replace(/\\\./g, '.'); from = from[remainingSteps]; break; @@ -429,7 +429,7 @@ ActionRunner.prototype = { catcher = null; } - clientAction.call(client, params, _.bind(function (error, body, status) { + var cb = _.bind(function (error, body, status) { this._last_requests_response = body; if (error) { @@ -451,7 +451,23 @@ ActionRunner.prototype = { } done(error); - }, this)); + }, this); + + // switch (Math.round(Math.random() * 100) % 3) { + // case 0: + // clientAction.call(client, params).then(function (resp) { + // cb(void 0, resp.body, resp.status); + // }, function (err) { + // cb(err); + // }); + // break; + // case 1: + // clientAction.call(client, params).once('done', cb); + // break; + // case 2: + clientAction.call(client, params, cb); + // break; + // } } else { done(new Error('stepped in do_do, did not find a function')); } diff --git a/test/integration/yaml_suite/server.js b/test/integration/yaml_suite/server.js index 065e8170b..d3c54b13f 100644 --- a/test/integration/yaml_suite/server.js +++ b/test/integration/yaml_suite/server.js @@ -21,7 +21,7 @@ exports.start = function (params, cb) { '-Des.discovery.zen.ping.multicast.enabled=false', ], { - cwd: undefined, + cwd: void 0, env: process.env, stdio: [ 'ignore', diff --git a/test/unit/es_server.test.js b/test/unit/es_server.test.js index 05b14cc79..7dd807b93 100644 --- a/test/unit/es_server.test.js +++ b/test/unit/es_server.test.js @@ -19,7 +19,7 @@ describe('EsServer Mock', function () { function makeRequest(opts, respCb) { opts = _.defaults(opts || {}, { - hostname: 'localhost', + host: 'localhost', port: port });