镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Commit 8e714f7

Browse files
nodejs-github-botaduh95
authored andcommitted
deps: update undici to 8.12.4
PR-URL: #67272 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Jake Yuesong Li <jake.yuesong@gmail.com>
1 parent 7b77766 commit 8e714f7

25 files changed

Lines changed: 912 additions & 399 deletions

‎deps/undici/src/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ const response = await fetch('https://api.example.com/data');
171171
- Building isomorphic code that runs in browsers and Node.js
172172
- Publishing to npm and want to maximize compatibility with JS runtimes
173173
- Simple HTTP requests without advanced configuration
174-
- You're publishing to npm and you want to maximize compatiblity
174+
- You're publishing to npm and you want to maximize compatibility
175175
- You don't depend on features from a specific version of undici
176176

177177
#### Use Undici Module When:

‎deps/undici/src/docs/docs/api/Dispatcher.md‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,10 @@ added: v4.0.0
205205
-->
206206

207207
* `options` {Object}
208-
* `origin` {string|URL} (optional) The origin to dispatch the request to.
208+
* `origin` {string|URL} The origin to dispatch the request to. Optional for a
209+
dispatcher that is already bound to a single origin, such as `Client` or
210+
`Pool`, which then use their own origin. Required on `Agent`, which is not
211+
bound to one origin and throws an `InvalidArgumentError` when it is missing.
209212
* `path` {string} The request path.
210213
* `method` {string} The HTTP method, e.g. `'GET'` or `'POST'`.
211214
* `body` {string|Buffer|Uint8Array|Readable|FormData|null} The request body.

‎deps/undici/src/docs/docs/api/RetryAgent.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ added: v6.7.0
6060
* `retryAfter` {boolean} When `true`, the delay between retries is inferred from
6161
the `Retry-After` response header when present. **Default:** `true`.
6262
* `methods` {string[]} HTTP methods that are eligible for retry.
63-
**Default:** `['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE']`.
63+
**Default:** `['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE', 'QUERY']`.
6464
* `statusCodes` {number[]} HTTP status codes that trigger a retry.
6565
**Default:** `[500, 502, 503, 504, 429]`.
6666
* `errorCodes` {string[]} Transport error codes that trigger a retry.

‎deps/undici/src/docs/docs/api/RetryHandler.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ changes:
8585
* `retryAfter` {boolean} When `true`, the delay before the next retry is inferred
8686
from the `Retry-After` response header when present. **Default:** `true`.
8787
* `methods` {string[]} HTTP methods that are eligible for retrying. **Default:**
88-
`['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE']`.
88+
`['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE', 'QUERY']`.
8989
* `statusCodes` {number[]} HTTP status codes that trigger a retry. **Default:**
9090
`[500, 502, 503, 504, 429]`.
9191
* `errorCodes` {string[]} Network error codes that trigger a retry. **Default:**

‎deps/undici/src/docs/docs/index.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ const response = await fetch('https://api.example.com/data');
155155
- Building isomorphic code that runs in browsers and Node.js
156156
- Publishing to npm and want to maximize compatibility with JS runtimes
157157
- Simple HTTP requests without advanced configuration
158-
- You're publishing to npm and you want to maximize compatiblity
158+
- You're publishing to npm and you want to maximize compatibility
159159
- You don't depend on features from a specific version of undici
160160

161161
#### Use Undici Module When:

‎deps/undici/src/lib/cache/sqlite-cache-store.js‎

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ const { zstdCompressSync, zstdDecompressSync } = require('node:zlib')
66

77
let DatabaseSync
88

9-
const VERSION = 4
9+
// Bump when entries written by an older cache policy are unsafe to reuse.
10+
// Version 5 invalidates entries that may have been poisoned through redirects.
11+
const VERSION = 5
1012

1113
// 2gb
1214
const MAX_ENTRY_SIZE = 2 * 1000 * 1000 * 1000
@@ -18,6 +20,20 @@ const COMPRESS_THRESHOLD = 1024 * 1024
1820
// node:sqlite is available.
1921
const hasZstd = typeof zstdCompressSync === 'function' && typeof zstdDecompressSync === 'function'
2022

23+
// SQLite reports a database that another connection is writing as SQLITE_BUSY
24+
// (5) or SQLITE_LOCKED (6).
25+
// https://www.sqlite.org/rescode.html#busy
26+
const SQLITE_BUSY = 5
27+
const SQLITE_LOCKED = 6
28+
29+
/**
30+
* @param {Error & { errcode?: number }} err
31+
* @returns {boolean}
32+
*/
33+
function isLockedError (err) {
34+
return err?.errcode === SQLITE_BUSY || err?.errcode === SQLITE_LOCKED
35+
}
36+
2137
/**
2238
* @typedef {import('../../types/cache-interceptor.d.ts').default.CacheStore} CacheStore
2339
* @implements {CacheStore}
@@ -259,7 +275,7 @@ module.exports = class SqliteCacheStore {
259275
get (key) {
260276
assertCacheKey(key)
261277

262-
const value = this.#findValue(key)
278+
const value = this.#lockSafe(() => this.#findValue(key))
263279
return value
264280
? {
265281
body: value.body
@@ -307,10 +323,10 @@ module.exports = class SqliteCacheStore {
307323
}
308324
}
309325

310-
const existingValue = this.#findValue(key, true)
326+
const existingValue = this.#lockSafe(() => this.#findValue(key, true))
311327
if (existingValue) {
312328
// Updating an existing response, let's overwrite it
313-
this.#updateValueQuery.run(
329+
this.#lockSafe(() => this.#updateValueQuery.run(
314330
storedBody,
315331
compressed,
316332
value.deleteAt,
@@ -323,10 +339,10 @@ module.exports = class SqliteCacheStore {
323339
value.cachedAt,
324340
value.staleAt,
325341
existingValue.id
326-
)
342+
))
327343
} else {
328344
// New response, let's insert it
329-
this.#insertValueQuery.run(
345+
this.#lockSafe(() => this.#insertValueQuery.run(
330346
url,
331347
key.method,
332348
storedBody,
@@ -340,7 +356,7 @@ module.exports = class SqliteCacheStore {
340356
value.vary ? JSON.stringify(value.vary) : null,
341357
value.cachedAt,
342358
value.staleAt
343-
)
359+
))
344360
this.#prune()
345361
}
346362
}
@@ -389,23 +405,53 @@ module.exports = class SqliteCacheStore {
389405
throw new TypeError(`expected key to be object, got ${typeof key}`)
390406
}
391407

392-
this.#deleteByUrlQuery.run(this.#makeValueUrl(key))
408+
this.#lockSafe(() => this.#deleteByUrlQuery.run(this.#makeValueUrl(key)))
409+
}
410+
411+
/**
412+
* Runs a database operation, skipping it when another connection holds the
413+
* database lock.
414+
*
415+
* The cache store is meant to be shared between processes, and SQLite reports
416+
* a concurrent writer as SQLITE_BUSY/SQLITE_LOCKED. Those errors are
417+
* transient, and caching is best effort: the entry is skipped and the next
418+
* request retries, rather than failing the request that triggered the write.
419+
*
420+
* @template T
421+
* @param {() => T} fn
422+
* @returns {T | undefined}
423+
*/
424+
#lockSafe (fn) {
425+
try {
426+
return fn()
427+
} catch (err) {
428+
if (!isLockedError(err)) {
429+
throw err
430+
}
431+
432+
return undefined
433+
}
393434
}
394435

395436
#prune () {
396-
if (Number.isFinite(this.#maxCount) && this.size <= this.#maxCount) {
397-
return 0
437+
if (Number.isFinite(this.#maxCount)) {
438+
// A locked database cannot be measured, so skip pruning instead of
439+
// failing the write that triggered it.
440+
const size = this.#lockSafe(() => this.size)
441+
if (size === undefined || size <= this.#maxCount) {
442+
return 0
443+
}
398444
}
399445

400446
{
401-
const removed = this.#deleteExpiredValuesQuery.run(Date.now()).changes
447+
const removed = this.#lockSafe(() => this.#deleteExpiredValuesQuery.run(Date.now()).changes)
402448
if (removed) {
403449
return removed
404450
}
405451
}
406452

407453
{
408-
const removed = this.#deleteOldValuesQuery?.run(Math.max(Math.floor(this.#maxCount * 0.1), 1)).changes
454+
const removed = this.#lockSafe(() => this.#deleteOldValuesQuery?.run(Math.max(Math.floor(this.#maxCount * 0.1), 1)).changes)
409455
if (removed) {
410456
return removed
411457
}

‎deps/undici/src/lib/dispatcher/client-h1.js‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ function lazyllhttp () {
8383

8484
// We disable wasm SIMD on older versions of Node.js on ppc64 that are broken on Power >=9 architectures.
8585
let useWasmSIMD = true
86-
if (process.arch === 'ppc64') {
86+
if (process.arch === 'riscv64') {
87+
useWasmSIMD = false
88+
} else if (process.arch === 'ppc64') {
8789
const [major, minor] = process.versions.node.split('.').map(n => parseInt(n, 10))
8890
if (major < 24 || (major === 24 && minor < 12)) {
8991
useWasmSIMD = false

0 commit comments

Comments
 (0)