Compare commits

...

4 Commits

Author SHA1 Message Date
d2c63b4c5f bump 9.0.0 alpha.3 (#2591) 2025-01-30 11:45:47 -06:00
0ad42ff1a2 Drop default 30-second timeout (#2573) 2025-01-30 10:37:53 -06:00
6dbf91a9c3 github-action: Add AsciiDoc freeze warning (#2589)
* github-action: Add AsciiDoc freeze warning

* github-action: Add AsciiDoc freeze warning
2025-01-29 16:51:52 -08:00
39b2700add github-action: Add AsciiDoc freeze warning (#2588) 2025-01-28 15:55:26 -06:00
18 changed files with 101 additions and 71 deletions

View File

@ -0,0 +1,21 @@
---
name: Comment on PR for .asciidoc changes
on:
# We need to use pull_request_target to be able to comment on PRs from forks
pull_request_target:
types:
- synchronize
- opened
- reopened
branches:
- main
- master
- "9.0"
jobs:
comment-on-asciidoc-change:
permissions:
contents: read
pull-requests: write
uses: elastic/docs-builder/.github/workflows/comment-on-asciidoc-changes.yml@main

View File

@ -13,7 +13,6 @@ const client = new Client({
cloud: { id: '<cloud-id>' },
auth: { apiKey: 'base64EncodedKey' },
maxRetries: 5,
requestTimeout: 60000,
sniffOnStart: true
})
----
@ -82,7 +81,7 @@ _Default:_ `3`
|`requestTimeout`
|`number` - Max request timeout in milliseconds for each request. +
_Default:_ `30000`
_Default:_ No value
|`pingTimeout`
|`number` - Max ping request timeout in milliseconds for each request. +

View File

@ -12,6 +12,11 @@
In 8.0, the top-level `body` parameter that was available on all API functions <<remove-body-key,was deprecated>>. In 9.0 this property is completely removed.
[discrete]
===== Remove the default 30-second timeout on all requests sent to Elasticsearch
Setting HTTP timeouts on Elasticsearch requests goes against Elastic's recommendations. See <<timeout-best-practices>> for more information.
[discrete]
=== 8.17.0

View File

@ -28,7 +28,6 @@ const client = new Client({
})
const child = client.child({
headers: { 'x-foo': 'bar' },
requestTimeout: 1000
})
client.info().then(console.log, console.log)

View File

@ -414,8 +414,8 @@ The supported request specific options are:
_Default:_ `null`
|`requestTimeout`
|`number | string` - Max request timeout for the request in milliseconds, it overrides the client default. +
_Default:_ `30000`
|`number | string | null` - Max request timeout for the request in milliseconds. This overrides the client default, which is to not time out at all. See https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-network.html#_http_client_configuration[Elasticsearch best practices for HTML clients] for more info. +
_Default:_ No timeout
|`retryOnTimeout`
|`boolean` - Retry requests that have timed out.

View File

@ -4,7 +4,7 @@
With the {jsclient}/api-reference.html#_bulk[`bulk` API], you can perform multiple index/delete operations in a
single API call. The `bulk` API significantly increases indexing speed.
NOTE: You can also use the {jsclient}/client-helpers.html[bulk helper].
NOTE: You can also use the <<bulk-helper,bulk helper>>.
[source,js]
----

View File

@ -6,7 +6,7 @@ Check that the document `/game-of-thrones/1` exists.
NOTE: Since this API uses the `HEAD` method, the body value will be boolean.
[source,js]
---------
----
'use strict'
const { Client } = require('@elastic/elasticsearch')
@ -34,4 +34,4 @@ async function run () {
}
run().catch(console.log)
---------
----

View File

@ -6,7 +6,7 @@ The following example gets a JSON document from an index called
`game-of-thrones`, under a type called `_doc`, with id valued `'1'`.
[source,js]
---------
----
'use strict'
const { Client } = require('@elastic/elasticsearch')
@ -34,4 +34,4 @@ async function run () {
}
run().catch(console.log)
---------
----

View File

@ -19,7 +19,7 @@ In order to use scrolling, the initial search request should specify the scroll
parameter in the query string, which tells {es} how long it should keep the
“search context” alive.
NOTE: Did you know that we provide an helper for sending scroll requests? You can find it {jsclient}/client-helpers.html[here].
NOTE: Did you know that we provide an helper for sending scroll requests? You can find it <<scroll-search-helper,here>>.
[source,js]
----

View File

@ -6,7 +6,7 @@ the following example, we will index a document that also tracks how many times
a character has said the given quote, and then we will update the `times` field.
[source,js]
---------
----
'use strict'
const { Client } = require('@elastic/elasticsearch')
@ -48,12 +48,12 @@ async function run () {
run().catch(console.log)
---------
----
With the update API, you can also run a partial update of a document.
[source,js]
---------
----
'use strict'
const { Client } = require('@elastic/elasticsearch')
@ -92,4 +92,4 @@ async function run () {
run().catch(console.log)
---------
----

View File

@ -6,7 +6,7 @@ in the index without changing the source. This is useful to pick up a new
property or some other online mapping change.
[source,js]
---------
----
'use strict'
const { Client } = require('@elastic/elasticsearch')
@ -57,4 +57,4 @@ async function run () {
run().catch(console.log)
---------
----

View File

@ -1,10 +1,8 @@
[[timeout-best-practices]]
=== Timeout best practices
This client is configured by default to operate like many HTTP client libraries do, by using a relatively short (30 second) timeout on all requests sent to {es}, raising a `TimeoutError` when that time period has elapsed without receiving a response. However, {es} will always eventually respond to any request, even if it takes several minutes. The {ref}/modules-network.html#_http_client_configuration[official {es} recommendation] is to disable response timeouts entirely by default.
Starting in 9.0.0, this client is configured to not time out any HTTP request by default. {es} will always eventually respond to any request, even if it takes several minutes. Reissuing a request that it has not responded to yet can cause performance side effects. See the {ref}/modules-network.html#_http_client_configuration[official {es} recommendations for HTTP clients] for more information.
Since changing this default would be a breaking change, we won't do that until the next major release. In the meantime, here is our recommendation for properly configuring your client:
Prior to 9.0, this client was configured by default to operate like many HTTP client libraries do, by using a relatively short (30 second) timeout on all requests sent to {es}, raising a `TimeoutError` when that time period elapsed without receiving a response.
* Ensure keep-alive is enabled; this is the default, so no settings need to be changed, unless you have set `agent` to `false` or provided an alternate `agent` that disables keep-alive
* If using the default `UndiciConnection`, disable request timeouts by setting `timeout` to `0`
* If using the legacy `HttpConnection`, set `timeout` to a very large number (e.g. `86400000`, or one day)
If your circumstances require you to set timeouts on Elasticsearch requests, setting the `requestTimeout` value to a millisecond value will cause this client to operate as it did prior to 9.0.

View File

@ -1,6 +1,6 @@
{
"name": "@elastic/elasticsearch",
"version": "9.0.0-alpha.2",
"version": "9.0.0-alpha.3",
"versionCanary": "9.0.0-canary.0",
"description": "The official Elasticsearch client for Node.js",
"main": "./index.js",
@ -57,7 +57,7 @@
},
"devDependencies": {
"@elastic/request-converter": "8.17.0",
"@sinonjs/fake-timers": "github:sinonjs/fake-timers#48f089f",
"@sinonjs/fake-timers": "14.0.0",
"@types/debug": "4.1.12",
"@types/ms": "0.7.34",
"@types/node": "22.10.7",
@ -89,7 +89,7 @@
"zx": "7.2.3"
},
"dependencies": {
"@elastic/transport": "^8.9.1",
"@elastic/transport": "9.0.0-alpha.1",
"apache-arrow": "^18.0.0",
"tslib": "^2.4.0"
},

View File

@ -108,14 +108,15 @@ export interface ClientOptions {
* @defaultValue 3 */
maxRetries?: number
/** @property requestTimeout Max request timeout in milliseconds for each request
* @defaultValue 30000 */
* @defaultValue No timeout
* @remarks Read [the Elasticsearch docs](https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-network.html#_http_client_configuration) about HTTP client configuration for details. */
requestTimeout?: number
/** @property pingTimeout Max number of milliseconds a `ClusterConnectionPool` will wait when pinging nodes before marking them dead
* @defaultValue 3000 */
pingTimeout?: number
/** @property sniffInterval Perform a sniff operation every `n` milliseconds
* @remarks Sniffing might not be the best solution for you. Read https://www.elastic.co/blog/elasticsearch-sniffing-best-practices-what-when-why-how to learn more.
* @defaultValue */
* @defaultValue false */
sniffInterval?: number | boolean
/** @property sniffOnStart Perform a sniff once the client is started
* @remarks Sniffing might not be the best solution for you. Read https://www.elastic.co/blog/elasticsearch-sniffing-best-practices-what-when-why-how to learn more.
@ -244,7 +245,6 @@ export default class Client extends API {
Serializer,
ConnectionPool: (opts.cloud != null) ? CloudConnectionPool : WeightedConnectionPool,
maxRetries: 3,
requestTimeout: 30000,
pingTimeout: 3000,
sniffInterval: false,
sniffOnStart: false,

View File

@ -17,9 +17,10 @@
* under the License.
*/
import * as http from 'http'
import * as http from 'node:http'
import { URL } from 'node:url'
import { setTimeout } from 'node:timers/promises'
import { test } from 'tap'
import { URL } from 'url'
import FakeTimers from '@sinonjs/fake-timers'
import { buildServer, connection } from '../utils'
import { Client, errors } from '../..'
@ -451,30 +452,37 @@ test('Ensure new client instance stores requestTimeout for each connection', t =
t.end()
})
test('Ensure new client does not time out at default (30s) when client sets requestTimeout', async t => {
const clock = FakeTimers.install({ toFake: ['setTimeout', 'clearTimeout'] })
test('No request timeout is set by default', t => {
const client = new Client({
node: { url: new URL('http://localhost:9200') },
})
t.equal(client.connectionPool.connections[0].timeout, null)
t.end()
})
test('Ensure new client does not time out if requestTimeout is not set', async t => {
const clock = FakeTimers.install({ toFake: ['setTimeout'] })
t.teardown(() => clock.uninstall())
function handler (_req: http.IncomingMessage, res: http.ServerResponse) {
setTimeout(() => {
t.pass('timeout ended')
setTimeout(1000 * 60 * 60).then(() => {
t.ok('timeout ended')
res.setHeader('content-type', 'application/json')
res.end(JSON.stringify({ success: true }))
}, 31000) // default is 30000
clock.runToLast()
})
clock.tick(1000 * 60 * 60)
}
const [{ port }, server] = await buildServer(handler)
const client = new Client({
node: `http://localhost:${port}`,
requestTimeout: 60000
})
try {
await client.transport.request({ method: 'GET', path: '/' })
} catch (error) {
t.fail('timeout error hit')
t.fail('Error should not be thrown', error)
} finally {
server.stop()
t.end()

View File

@ -1611,7 +1611,7 @@ test('errors', t => {
test('Flush interval', t => {
t.test('Slow producer', async t => {
const clock = FakeTimers.install({ toFake: ['setTimeout', 'clearTimeout'] })
const clock = FakeTimers.install({ toFake: ['setTimeout', 'clearTimeout'], shouldClearNativeTimers: true })
t.teardown(() => clock.uninstall())
let count = 0
@ -1663,7 +1663,7 @@ test('Flush interval', t => {
})
t.test('Abort operation', async t => {
const clock = FakeTimers.install({ toFake: ['setTimeout', 'clearTimeout'] })
const clock = FakeTimers.install({ toFake: ['setTimeout', 'clearTimeout'], shouldClearNativeTimers: true })
t.teardown(() => clock.uninstall())
let count = 0

View File

@ -583,7 +583,7 @@ test('Multiple searches (concurrency = 1)', t => {
test('Flush interval', t => {
t.plan(2)
const clock = FakeTimers.install({ toFake: ['setTimeout', 'clearTimeout'] })
const clock = FakeTimers.install({ toFake: ['setTimeout', 'clearTimeout'], shouldClearNativeTimers: true })
t.teardown(() => clock.uninstall())
const MockConnection = connection.buildMockConnection({