This repository has been archived by the owner on Feb 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: move withTimeoutOption to core-utils (#3407)
Pulls non-grpc changes out of #3403 to ease the continued merging of master into that branch. - Moves withTimeoutOption into core-utils - Moves TimeoutError into core-utils - Adds missing ts project links - Adds more add-all tests to interface suite - Ignores unpassable tests for non-grpc or core implementations - Normalises mode and mtime in normalise-input function - Dedupes mtime normalisation between core and http client
- Loading branch information
1 parent
d38b0ab
commit 288a259
Showing
98 changed files
with
425 additions
and
281 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
'use strict' | ||
|
||
class TimeoutError extends Error { | ||
constructor (message = 'request timed out') { | ||
super(message) | ||
this.name = 'TimeoutError' | ||
this.code = TimeoutError.code | ||
} | ||
} | ||
|
||
TimeoutError.code = 'ERR_TIMEOUT' | ||
exports.TimeoutError = TimeoutError |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,7 @@ | ||
'use strict' | ||
|
||
/** | ||
* @template {any[]} ARGS | ||
* @template R | ||
* @typedef {(...args: ARGS) => R} Fn | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* eslint-disable no-unreachable */ | ||
'use strict' | ||
|
||
const TimeoutController = require('timeout-abort-controller') | ||
const { anySignal } = require('any-signal') | ||
const parseDuration = require('parse-duration').default | ||
const { TimeoutError } = require('./errors') | ||
|
||
/** | ||
* @template {any[]} ARGS | ||
* @template {Promise<any> | AsyncIterable<any>} R - The return type of `fn` | ||
* @param {Fn<ARGS, R>} fn | ||
* @param {number} [optionsArgIndex] | ||
* @returns {Fn<ARGS, R>} | ||
*/ | ||
function withTimeoutOption (fn, optionsArgIndex) { | ||
// eslint-disable-next-line | ||
return /** @returns {R} */(/** @type {ARGS} */...args) => { | ||
const options = args[optionsArgIndex == null ? args.length - 1 : optionsArgIndex] | ||
if (!options || !options.timeout) return fn(...args) | ||
|
||
const timeout = typeof options.timeout === 'string' | ||
? parseDuration(options.timeout) | ||
: options.timeout | ||
|
||
const controller = new TimeoutController(timeout) | ||
|
||
options.signal = anySignal([options.signal, controller.signal]) | ||
|
||
const fnRes = fn(...args) | ||
// eslint-disable-next-line promise/param-names | ||
const timeoutPromise = new Promise((_resolve, reject) => { | ||
controller.signal.addEventListener('abort', () => { | ||
reject(new TimeoutError()) | ||
}) | ||
}) | ||
|
||
const start = Date.now() | ||
|
||
const maybeThrowTimeoutError = () => { | ||
if (controller.signal.aborted) { | ||
throw new TimeoutError() | ||
} | ||
|
||
const timeTaken = Date.now() - start | ||
|
||
// if we have starved the event loop by adding microtasks, we could have | ||
// timed out already but the TimeoutController will never know because it's | ||
// setTimeout will not fire until we stop adding microtasks | ||
if (timeTaken > timeout) { | ||
controller.abort() | ||
throw new TimeoutError() | ||
} | ||
} | ||
|
||
if (fnRes[Symbol.asyncIterator]) { | ||
// @ts-ignore | ||
return (async function * () { | ||
const it = fnRes[Symbol.asyncIterator]() | ||
|
||
try { | ||
while (true) { | ||
const { value, done } = await Promise.race([it.next(), timeoutPromise]) | ||
|
||
if (done) { | ||
break | ||
} | ||
|
||
maybeThrowTimeoutError() | ||
|
||
yield value | ||
} | ||
} catch (err) { | ||
maybeThrowTimeoutError() | ||
|
||
throw err | ||
} finally { | ||
controller.clear() | ||
|
||
if (it.return) { | ||
it.return() | ||
} | ||
} | ||
})() | ||
} | ||
|
||
// @ts-ignore | ||
return (async () => { | ||
try { | ||
const res = await Promise.race([fnRes, timeoutPromise]) | ||
|
||
maybeThrowTimeoutError() | ||
|
||
return res | ||
} catch (err) { | ||
maybeThrowTimeoutError() | ||
|
||
throw err | ||
} finally { | ||
controller.clear() | ||
} | ||
})() | ||
} | ||
} | ||
|
||
module.exports = withTimeoutOption |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.