Compare commits

..

16 Commits

18 changed files with 432 additions and 21 deletions

View File

@ -1,4 +1,4 @@
ARG NODE_JS_VERSION=10 ARG NODE_JS_VERSION=16
FROM node:${NODE_JS_VERSION} FROM node:${NODE_JS_VERSION}
# Create app directory # Create app directory

107
.ci/make.mjs Normal file
View File

@ -0,0 +1,107 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* global $ argv */
'use strict'
import 'zx/globals'
import { readFile, writeFile } from 'fs/promises'
import assert from 'assert'
import { join } from 'desm'
import semver from 'semver'
assert(typeof argv.task === 'string', 'Missing task parameter')
switch (argv.task) {
case 'release':
release(argv._).catch(onError)
break
case 'bump':
bump(argv._).catch(onError)
break
case 'codegen':
codegen(argv._).catch(onError)
break
default:
console.log(`Unknown task: ${argv.task}`)
process.exit(1)
}
async function release (args) {
assert(args.length === 2, 'Release task expects two parameters')
let [version, outputFolder] = args
if (process.env.WORKFLOW === 'snapshot' && !version.endsWith('SNAPSHOT')) {
version = `${version}-SNAPSHOT`
}
await bump([version])
const packageJson = JSON.parse(await readFile(
join(import.meta.url, '..', 'package.json'),
'utf8'
))
await $`npm pack`
await $`zip elasticsearch-js-${version}.zip elastic-elasticsearch-${packageJson.version}.tgz`
await $`rm elastic-elasticsearch-${packageJson.version}.tgz`
await $`mv ${join(import.meta.url, '..', `elasticsearch-js-${version}.zip`)} ${join(import.meta.url, '..', outputFolder, `elasticsearch-js-${version}.zip`)}`
}
async function bump (args) {
assert(args.length === 1, 'Bump task expects one parameter')
const [version] = args
const packageJson = JSON.parse(await readFile(
join(import.meta.url, '..', 'package.json'),
'utf8'
))
const cleanVersion = semver.clean(version.includes('SNAPSHOT') ? version.split('-')[0] : version)
assert(semver.valid(cleanVersion))
packageJson.version = cleanVersion
packageJson.versionCanary = `${cleanVersion}-canary.0`
await writeFile(
join(import.meta.url, '..', 'package.json'),
JSON.stringify(packageJson, null, 2),
'utf8'
)
const testMatrix = await readFile(join(import.meta.url, 'test-matrix.yml'), 'utf8')
await writeFile(
join(import.meta.url, 'test-matrix.yml'),
testMatrix.replace(/STACK_VERSION:\s+\- "[0-9]+[0-9\.]*[0-9](?:\-SNAPSHOT)?"/, `STACK_VERSION:\n - "${cleanVersion}-SNAPSHOT"`), // eslint-disable-line
'utf8'
)
}
// this command can only be executed locally for now
async function codegen (args) {
assert(args.length === 1, 'Bump task expects one parameter')
const [version] = args
await $`node scripts/generate --version ${version}`
}
function onError (err) {
console.log(err)
process.exit(1)
}

178
.ci/make.sh Executable file
View File

@ -0,0 +1,178 @@
#!/usr/bin/env bash
# ------------------------------------------------------- #
#
# Skeleton for common build entry script for all elastic
# clients. Needs to be adapted to individual client usage.
#
# Must be called: ./.ci/make.sh <target> <params>
#
# Version: 1.1.0
#
# Targets:
# ---------------------------
# assemble <VERSION> : build client artefacts with version
# bump <VERSION> : bump client internals to version
# codegen <VERSION> : generate endpoints
# docsgen <VERSION> : generate documentation
# examplegen : generate the doc examples
# clean : clean workspace
#
# ------------------------------------------------------- #
# ------------------------------------------------------- #
# Bootstrap
# ------------------------------------------------------- #
script_path=$(dirname "$(realpath -s "$0")")
repo=$(realpath "$script_path/../")
# shellcheck disable=SC1090
CMD=$1
TASK=$1
TASK_ARGS=()
VERSION=$2
STACK_VERSION=$VERSION
NODE_JS_VERSION=16
WORKFLOW=${WORKFLOW-staging}
set -euo pipefail
product="elastic/elasticsearch-js"
output_folder=".ci/output"
OUTPUT_DIR="$repo/${output_folder}"
REPO_BINDING="${OUTPUT_DIR}:/sln/${output_folder}"
mkdir -p "$OUTPUT_DIR"
echo -e "\033[34;1mINFO:\033[0m PRODUCT ${product}\033[0m"
echo -e "\033[34;1mINFO:\033[0m VERSION ${STACK_VERSION}\033[0m"
echo -e "\033[34;1mINFO:\033[0m OUTPUT_DIR ${OUTPUT_DIR}\033[0m"
# ------------------------------------------------------- #
# Parse Command
# ------------------------------------------------------- #
case $CMD in
clean)
echo -e "\033[36;1mTARGET: clean workspace $output_folder\033[0m"
rm -rf "$output_folder"
echo -e "\033[32;1mdone.\033[0m"
exit 0
;;
assemble)
if [ -v $VERSION ]; then
echo -e "\033[31;1mTARGET: assemble -> missing version parameter\033[0m"
exit 1
fi
echo -e "\033[36;1mTARGET: assemble artefact $VERSION\033[0m"
TASK=release
TASK_ARGS=("$VERSION" "$output_folder")
;;
codegen)
if [ -v $VERSION ]; then
echo -e "\033[31;1mTARGET: codegen -> missing version parameter\033[0m"
exit 1
fi
echo -e "\033[36;1mTARGET: codegen API v$VERSION\033[0m"
TASK=codegen
# VERSION is BRANCH here for now
TASK_ARGS=("$VERSION")
;;
docsgen)
if [ -v $VERSION ]; then
echo -e "\033[31;1mTARGET: docsgen -> missing version parameter\033[0m"
exit 1
fi
echo -e "\033[36;1mTARGET: generate docs for $VERSION\033[0m"
TASK=codegen
# VERSION is BRANCH here for now
TASK_ARGS=("$VERSION" "$codegen_folder")
;;
examplesgen)
echo -e "\033[36;1mTARGET: generate examples\033[0m"
TASK=codegen
# VERSION is BRANCH here for now
TASK_ARGS=("$VERSION" "$codegen_folder")
;;
bump)
if [ -v $VERSION ]; then
echo -e "\033[31;1mTARGET: bump -> missing version parameter\033[0m"
exit 1
fi
echo -e "\033[36;1mTARGET: bump to version $VERSION\033[0m"
TASK=bump
# VERSION is BRANCH here for now
TASK_ARGS=("$VERSION")
;;
*)
echo -e "\nUsage:\n\t $CMD is not supported right now\n"
exit 1
esac
# ------------------------------------------------------- #
# Build Container
# ------------------------------------------------------- #
echo -e "\033[34;1mINFO: building $product container\033[0m"
docker build \
--file .ci/Dockerfile \
--tag ${product} \
--build-arg NODE_JS_VERSION=${NODE_JS_VERSION} \
--build-arg USER_ID="$(id -u)" \
--build-arg GROUP_ID="$(id -g)" \
.
# ------------------------------------------------------- #
# Run the Container
# ------------------------------------------------------- #
echo -e "\033[34;1mINFO: running $product container\033[0m"
docker run \
--volume $repo:/usr/src/app \
--volume /usr/src/app/node_modules \
--env "WORKFLOW=${WORKFLOW}" \
--name make-elasticsearch-js \
--rm \
$product \
node .ci/make.mjs --task $TASK ${TASK_ARGS[*]}
# ------------------------------------------------------- #
# Post Command tasks & checks
# ------------------------------------------------------- #
if [[ "$CMD" == "assemble" ]]; then
if compgen -G ".ci/output/*" > /dev/null; then
echo -e "\033[32;1mTARGET: successfully assembled client v$VERSION\033[0m"
else
echo -e "\033[31;1mTARGET: assemble failed, empty workspace!\033[0m"
exit 1
fi
fi
if [[ "$CMD" == "bump" ]]; then
if [ -n "$(git status --porcelain)" ]; then
echo -e "\033[32;1mTARGET: successfully bumped client v$VERSION\033[0m"
else
echo -e "\033[31;1mTARGET: failed bumped client v$VERSION\033[0m"
exit 1
fi
fi
if [[ "$CMD" == "codegen" ]]; then
if [ -n "$(git status --porcelain)" ]; then
echo -e "\033[32;1mTARGET: successfully generated client v$VERSION\033[0m"
else
echo -e "\033[31;1mTARGET: failed generating client v$VERSION\033[0m"
exit 1
fi
fi
if [[ "$CMD" == "docsgen" ]]; then
echo "TODO"
fi
if [[ "$CMD" == "examplesgen" ]]; then
echo "TODO"
fi

View File

@ -1,6 +1,6 @@
--- ---
STACK_VERSION: STACK_VERSION:
- 7.16-SNAPSHOT - "7.17.11-SNAPSHOT"
NODE_JS_VERSION: NODE_JS_VERSION:
- 16 - 16

View File

@ -23,8 +23,8 @@
/* eslint no-unused-vars: 0 */ /* eslint no-unused-vars: 0 */
const { handleError, snakeCaseKeys, normalizeArguments, kConfigurationError } = require('../utils') const { handleError, snakeCaseKeys, normalizeArguments, kConfigurationError } = require('../utils')
const acceptedQuerystring = ['master_timeout', 'timeout', 'pretty', 'human', 'error_trace', 'source', 'filter_path', 'wait_for_completion', 'verify', 'ignore_unavailable', 'index_details', 'include_repository', 'verbose', 'local', 'blob_count', 'concurrency', 'read_node_count', 'early_read_node_count', 'seed', 'rare_action_probability', 'max_blob_size', 'max_total_data_size', 'detailed', 'rarely_abort_writes'] const acceptedQuerystring = ['master_timeout', 'timeout', 'pretty', 'human', 'error_trace', 'source', 'filter_path', 'wait_for_completion', 'verify', 'ignore_unavailable', 'index_details', 'include_repository', 'sort', 'size', 'order', 'from_sort_value', 'after', 'offset', 'slm_policy_filter', 'verbose', 'local', 'blob_count', 'concurrency', 'read_node_count', 'early_read_node_count', 'seed', 'rare_action_probability', 'max_blob_size', 'max_total_data_size', 'detailed', 'rarely_abort_writes']
const snakeCase = { masterTimeout: 'master_timeout', errorTrace: 'error_trace', filterPath: 'filter_path', waitForCompletion: 'wait_for_completion', ignoreUnavailable: 'ignore_unavailable', indexDetails: 'index_details', includeRepository: 'include_repository', blobCount: 'blob_count', readNodeCount: 'read_node_count', earlyReadNodeCount: 'early_read_node_count', rareActionProbability: 'rare_action_probability', maxBlobSize: 'max_blob_size', maxTotalDataSize: 'max_total_data_size', rarelyAbortWrites: 'rarely_abort_writes' } const snakeCase = { masterTimeout: 'master_timeout', errorTrace: 'error_trace', filterPath: 'filter_path', waitForCompletion: 'wait_for_completion', ignoreUnavailable: 'ignore_unavailable', indexDetails: 'index_details', includeRepository: 'include_repository', fromSortValue: 'from_sort_value', slmPolicyFilter: 'slm_policy_filter', blobCount: 'blob_count', readNodeCount: 'read_node_count', earlyReadNodeCount: 'early_read_node_count', rareActionProbability: 'rare_action_probability', maxBlobSize: 'max_blob_size', maxTotalDataSize: 'max_total_data_size', rarelyAbortWrites: 'rarely_abort_writes' }
function SnapshotApi (transport, ConfigurationError) { function SnapshotApi (transport, ConfigurationError) {
this.transport = transport this.transport = transport

View File

@ -2628,6 +2628,13 @@ export interface SnapshotGet extends Generic {
ignore_unavailable?: boolean; ignore_unavailable?: boolean;
index_details?: boolean; index_details?: boolean;
include_repository?: boolean; include_repository?: boolean;
sort?: 'start_time' | 'duration' | 'name' | 'repository' | 'index_count' | 'shard_count' | 'failed_shard_count';
size?: number;
order?: 'asc' | 'desc';
from_sort_value?: string;
after?: string;
offset?: number;
slm_policy_filter?: string;
verbose?: boolean; verbose?: boolean;
} }

View File

@ -1,6 +1,26 @@
[[changelog-client]] [[changelog-client]]
== Release notes == Release notes
[discrete]
=== 7.17.11
[discrete]
==== Features
[discrete]
===== Support for Elasticsearch `v7.17.11`
You can find all the API changes
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/release-notes-7.17.11.html[here].
[discrete]
==== Fixes
[discrete]
===== Fix index drift bug in bulk helper https://github.com/elastic/elasticsearch-js/pull/1759[#1759]
Fixes a bug in the bulk helper that would cause `onDrop` to send back the wrong JSON document or error on a nonexistent document when an error occurred on a bulk HTTP request that contained a `delete` action.
[discrete] [discrete]
=== 7.17.0 === 7.17.0

View File

@ -1,6 +1,6 @@
= Elasticsearch JavaScript Client = Elasticsearch JavaScript Client
:branch: 7.16 include::{asciidoc-dir}/../../shared/versions/stack/{source_branch}.asciidoc[]
include::{asciidoc-dir}/../../shared/attributes.asciidoc[] include::{asciidoc-dir}/../../shared/attributes.asciidoc[]
include::introduction.asciidoc[] include::introduction.asciidoc[]

View File

@ -377,9 +377,9 @@ child.search({
To improve observability, the client offers an easy way to configure the To improve observability, the client offers an easy way to configure the
`X-Opaque-Id` header. If you set the `X-Opaque-Id` in a specific request, this `X-Opaque-Id` header. If you set the `X-Opaque-Id` in a specific request, this
allows you to discover this identifier in the allows you to discover this identifier in the
https://www.elastic.co/guide/en/elasticsearch/reference/master/logging.html#deprecation-logging[deprecation logs], https://www.elastic.co/guide/en/elasticsearch/reference/7.17/logging.html#deprecation-logging[deprecation logs],
helps you with https://www.elastic.co/guide/en/elasticsearch/reference/master/index-modules-slowlog.html#_identifying_search_slow_log_origin[identifying search slow log origin] helps you with https://www.elastic.co/guide/en/elasticsearch/reference/7.17/index-modules-slowlog.html#_identifying_search_slow_log_origin[identifying search slow log origin]
as well as https://www.elastic.co/guide/en/elasticsearch/reference/master/tasks.html#_identifying_running_tasks[identifying running tasks]. as well as https://www.elastic.co/guide/en/elasticsearch/reference/7.17/tasks.html#_identifying_running_tasks[identifying running tasks].
The `X-Opaque-Id` should be configured in each request, for doing that you can The `X-Opaque-Id` should be configured in each request, for doing that you can
use the `opaqueId` option, as you can see in the following example. The use the `opaqueId` option, as you can see in the following example. The

View File

@ -3510,7 +3510,7 @@ link:{ref}/modules-scripting.html[Documentation] +
---- ----
client.getScriptContext() client.getScriptContext()
---- ----
link:https://www.elastic.co/guide/en/elasticsearch/painless/master/painless-contexts.html[Documentation] + link:{painless}/painless-contexts.html[Documentation] +
[discrete] [discrete]
@ -9127,7 +9127,7 @@ client.scriptsPainlessExecute({
body: object body: object
}) })
---- ----
link:https://www.elastic.co/guide/en/elasticsearch/painless/master/painless-execute-api.html[Documentation] + link:{painless}/painless-execute-api.html[Documentation] +
[cols=2*] [cols=2*]
|=== |===
|`body` |`body`
@ -10860,6 +10860,13 @@ client.snapshot.get({
ignore_unavailable: boolean, ignore_unavailable: boolean,
index_details: boolean, index_details: boolean,
include_repository: boolean, include_repository: boolean,
sort: 'start_time' | 'duration' | 'name' | 'repository' | 'index_count' | 'shard_count' | 'failed_shard_count',
size: integer,
order: 'asc' | 'desc',
from_sort_value: string,
after: string,
offset: integer,
slm_policy_filter: string,
verbose: boolean verbose: boolean
}) })
---- ----
@ -10884,6 +10891,29 @@ link:{ref}/modules-snapshots.html[Documentation] +
|`include_repository` or `includeRepository` |`include_repository` or `includeRepository`
|`boolean` - Whether to include the repository name in the snapshot info. Defaults to true. |`boolean` - Whether to include the repository name in the snapshot info. Defaults to true.
|`sort`
|`'start_time' \| 'duration' \| 'name' \| 'repository' \| 'index_count' \| 'shard_count' \| 'failed_shard_count'` - Allows setting a sort order for the result. Defaults to start_time +
_Default:_ `start_time`
|`size`
|`integer` - Maximum number of snapshots to return. Defaults to 0 which means return all that match without limit.
|`order`
|`'asc' \| 'desc'` - Sort order +
_Default:_ `asc`
|`from_sort_value` or `fromSortValue`
|`string` - Value of the current sort column at which to start retrieval.
|`after`
|`string` - Offset identifier to start pagination from as returned by the 'next' field in the response body.
|`offset`
|`integer` - Numeric offset to start pagination based on the snapshots matching the request. Defaults to 0
|`slm_policy_filter` or `slmPolicyFilter`
|`string` - Filter snapshots by a comma-separated list of SLM policy names that snapshots belong to. Accepts wildcards. Use the special pattern '_none' to match snapshots without an SLM policy
|`verbose` |`verbose`
|`boolean` - Whether to show verbose snapshot info or only show the basic info found in the repository index blob |`boolean` - Whether to show verbose snapshot info or only show the basic info found in the repository index blob

View File

@ -120,15 +120,15 @@ class Client extends ESAPI {
maxCompressedResponseSize: null maxCompressedResponseSize: null
}, opts) }, opts)
if (options.maxResponseSize !== null && options.maxResponseSize > buffer.constants.MAX_STRING_LENGTH) { if (options.maxResponseSize != null && options.maxResponseSize > buffer.constants.MAX_STRING_LENGTH) {
throw new ConfigurationError(`The maxResponseSize cannot be bigger than ${buffer.constants.MAX_STRING_LENGTH}`) throw new ConfigurationError(`The maxResponseSize cannot be bigger than ${buffer.constants.MAX_STRING_LENGTH}`)
} }
if (options.maxCompressedResponseSize !== null && options.maxCompressedResponseSize > buffer.constants.MAX_LENGTH) { if (options.maxCompressedResponseSize != null && options.maxCompressedResponseSize > buffer.constants.MAX_LENGTH) {
throw new ConfigurationError(`The maxCompressedResponseSize cannot be bigger than ${buffer.constants.MAX_LENGTH}`) throw new ConfigurationError(`The maxCompressedResponseSize cannot be bigger than ${buffer.constants.MAX_LENGTH}`)
} }
if (options.caFingerprint !== null && isHttpConnection(opts.node || opts.nodes)) { if (options.caFingerprint != null && isHttpConnection(opts.node || opts.nodes)) {
throw new ConfigurationError('You can\'t configure the caFingerprint with a http connection') throw new ConfigurationError('You can\'t configure the caFingerprint with a http connection')
} }

View File

@ -705,11 +705,11 @@ class Helpers {
} }
const retry = [] const retry = []
const { items } = body const { items } = body
let indexSlice = 0
for (let i = 0, len = items.length; i < len; i++) { for (let i = 0, len = items.length; i < len; i++) {
const action = items[i] const action = items[i]
const operation = Object.keys(action)[0] const operation = Object.keys(action)[0]
const { status } = action[operation] const { status } = action[operation]
const indexSlice = operation !== 'delete' ? i * 2 : i
if (status >= 400) { if (status >= 400) {
// 429 is the only staus code where we might want to retry // 429 is the only staus code where we might want to retry
@ -736,6 +736,7 @@ class Helpers {
} else { } else {
stats.successful += 1 stats.successful += 1
} }
operation === 'delete' ? indexSlice += 1 : indexSlice += 2
} }
callback(null, retry) callback(null, retry)
}) })

View File

@ -11,8 +11,8 @@
"./*": "./*.js" "./*": "./*.js"
}, },
"homepage": "http://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/index.html", "homepage": "http://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/index.html",
"version": "7.17.0", "version": "7.17.11-patch.1",
"versionCanary": "7.16.0-canary.7", "versionCanary": "7.17.11-canary.2",
"keywords": [ "keywords": [
"elasticsearch", "elasticsearch",
"elastic", "elastic",
@ -53,6 +53,7 @@
"cross-zip": "^4.0.0", "cross-zip": "^4.0.0",
"dedent": "^0.7.0", "dedent": "^0.7.0",
"deepmerge": "^4.2.2", "deepmerge": "^4.2.2",
"desm": "^1.2.0",
"dezalgo": "^1.0.3", "dezalgo": "^1.0.3",
"fast-deep-equal": "^3.1.3", "fast-deep-equal": "^3.1.3",
"into-stream": "^6.0.0", "into-stream": "^6.0.0",
@ -73,7 +74,8 @@
"tap": "^15.0.9", "tap": "^15.0.9",
"tsd": "^0.15.1", "tsd": "^0.15.1",
"workq": "^3.0.0", "workq": "^3.0.0",
"xmlbuilder2": "^2.4.1" "xmlbuilder2": "^2.4.1",
"zx": "^6.1.0"
}, },
"dependencies": { "dependencies": {
"debug": "^4.3.1", "debug": "^4.3.1",

View File

@ -282,6 +282,7 @@ function fixLink (name, str) {
str = str.replace(/frozen\.html/, 'freeze-index-api.html') str = str.replace(/frozen\.html/, 'freeze-index-api.html')
str = str.replace(/ml-file-structure\.html/, 'ml-find-file-structure.html') str = str.replace(/ml-file-structure\.html/, 'ml-find-file-structure.html')
str = str.replace(/security-api-get-user-privileges\.html/, 'security-api-get-privileges.html') str = str.replace(/security-api-get-user-privileges\.html/, 'security-api-get-privileges.html')
str = str.replace(/^.+guide\/en\/elasticsearch\/painless\/[^/]+\/([^./]*\.html(?:#.+)?)$/, '{painless}/$1')
return str return str
} }

View File

@ -169,6 +169,7 @@ export interface ${toPascalCase(name)}${body ? `<T = ${bodyGeneric}>` : ''} exte
case 'int': case 'int':
case 'double': case 'double':
case 'long': case 'long':
case 'integer':
return 'number' return 'number'
case 'boolean|long': case 'boolean|long':
return 'boolean | number' return 'boolean | number'

View File

@ -232,7 +232,7 @@ test('Authentication', t => {
server.stop() server.stop()
}) })
}) })
}) }, { skip: true })
t.test('Node with basic auth data in the url (array of nodes)', t => { t.test('Node with basic auth data in the url (array of nodes)', t => {
t.plan(3) t.plan(3)
@ -1176,7 +1176,7 @@ test('Disable keep alive agent', t => {
server.stop() server.stop()
}) })
}) })
}) }, { skip: true })
test('name property as string', t => { test('name property as string', t => {
t.plan(1) t.plan(1)

View File

@ -237,7 +237,7 @@ test('Disable keep alive', t => {
server.stop() server.stop()
}) })
}) })
}) }, { skip: true })
test('Timeout support', t => { test('Timeout support', t => {
t.plan(1) t.plan(1)
@ -1101,7 +1101,7 @@ test('Should show local/remote socket address in case of ECONNRESET', t => {
method: 'GET' method: 'GET'
}, (err, res) => { }, (err, res) => {
t.ok(err instanceof ConnectionError) t.ok(err instanceof ConnectionError)
t.match(err.message, /socket\shang\sup\s-\sLocal:\s127.0.0.1:\d+,\sRemote:\s127.0.0.1:\d+/) t.match(err.message, /socket\shang\sup\s-\sLocal:\s(127.0.0.1|::1):\d+,\sRemote:\s(127.0.0.1|::1):\d+/)
server.stop() server.stop()
}) })
}) })

View File

@ -1082,6 +1082,70 @@ test('bulk delete', t => {
server.stop() server.stop()
}) })
t.test('Should call onDrop on the correct document when doing a mix of operations that includes deletes', async t => {
// checks to ensure onDrop doesn't provide the wrong document when some operations are deletes
// see https://github.com/elastic/elasticsearch-js/issues/1751
async function handler (req, res) {
res.setHeader('content-type', 'application/json')
res.end(JSON.stringify({
took: 0,
errors: true,
items: [
{ delete: { status: 200 } },
{ index: { status: 429 } },
{ index: { status: 200 } }
]
}))
}
const [{ port }, server] = await buildServer(handler)
const client = new Client({ node: `http://localhost:${port}` })
let counter = 0
const result = await client.helpers.bulk({
datasource: dataset.slice(),
concurrency: 1,
wait: 10,
retries: 0,
onDocument (doc) {
counter++
if (counter === 1) {
return {
delete: {
_index: 'test',
_id: String(counter)
}
}
} else {
return {
index: {
_index: 'test'
}
}
}
},
onDrop (doc) {
t.same(doc, {
status: 429,
error: null,
operation: { index: { _index: 'test' } },
document: { user: 'arya', age: 18 },
retried: false
})
}
})
t.type(result.time, 'number')
t.type(result.bytes, 'number')
t.match(result, {
total: 3,
successful: 2,
retry: 0,
failed: 1,
aborted: false
})
server.stop()
})
t.end() t.end()
}) })