Skip to content

Commit

Permalink
fs: add retryDelay option to rimraf
Browse files Browse the repository at this point in the history
This commit adds a retryDelay option to rimraf which configures
the amount of time between retry operations.

Refs: #30580
PR-URL: #30644
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
cjihrig authored and BethGriggs committed Feb 6, 2020
1 parent 7a32198 commit f9d8494
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 8 deletions.
26 changes: 19 additions & 7 deletions doc/api/fs.md
Expand Up @@ -3224,7 +3224,8 @@ changes:
pr-url: https://github.com/nodejs/node/pull/30644
description: The `maxBusyTries` option is renamed to `maxRetries`, and its
default is 0. The `emfileWait` option has been removed, and
`EMFILE` errors use the same retry logic as other errors.
`EMFILE` errors use the same retry logic as other errors. The
`retryDelay` option is now supported.
- version: v12.10.0
pr-url: https://github.com/nodejs/node/pull/29168
description: The `recursive`, `maxBusyTries`, and `emfileWait` options are
Expand All @@ -3249,12 +3250,15 @@ changes:
* `options` {Object}
* `maxRetries` {integer} If an `EBUSY`, `EMFILE`, `ENOTEMPTY`, or `EPERM`
error is encountered, Node.js will retry the operation with a linear backoff
wait of 100ms longer on each try. This option represents the number of
retries. This option is ignored if the `recursive` option is not `true`.
wait of `retryDelay` ms longer on each try. This option represents the number
of retries. This option is ignored if the `recursive` option is not `true`.
**Default:** `0`.
* `recursive` {boolean} If `true`, perform a recursive directory removal. In
recursive mode, errors are not reported if `path` does not exist, and
operations are retried on failure. **Default:** `false`.
* `retryDelay` {integer} The amount of time in milliseconds to wait between
retries. This option is ignored if the `recursive` option is not `true`.
**Default:** `100`.
* `callback` {Function}
* `err` {Error}

Expand All @@ -3272,7 +3276,8 @@ changes:
pr-url: https://github.com/nodejs/node/pull/30644
description: The `maxBusyTries` option is renamed to `maxRetries`, and its
default is 0. The `emfileWait` option has been removed, and
`EMFILE` errors use the same retry logic as other errors.
`EMFILE` errors use the same retry logic as other errors. The
`retryDelay` option is now supported.
- version: v12.10.0
pr-url: https://github.com/nodejs/node/pull/29168
description: The `recursive`, `maxBusyTries`, and `emfileWait` options are
Expand All @@ -3294,6 +3299,9 @@ changes:
* `recursive` {boolean} If `true`, perform a recursive directory removal. In
recursive mode, errors are not reported if `path` does not exist, and
operations are retried on failure. **Default:** `false`.
* `retryDelay` {integer} The amount of time in milliseconds to wait between
retries. This option is ignored if the `recursive` option is not `true`.
**Default:** `100`.

Synchronous rmdir(2). Returns `undefined`.

Expand Down Expand Up @@ -5005,7 +5013,8 @@ changes:
pr-url: https://github.com/nodejs/node/pull/30644
description: The `maxBusyTries` option is renamed to `maxRetries`, and its
default is 0. The `emfileWait` option has been removed, and
`EMFILE` errors use the same retry logic as other errors.
`EMFILE` errors use the same retry logic as other errors. The
`retryDelay` option is now supported.
- version: v12.10.0
pr-url: https://github.com/nodejs/node/pull/29168
description: The `recursive`, `maxBusyTries`, and `emfileWait` options are
Expand All @@ -5018,12 +5027,15 @@ changes:
* `options` {Object}
* `maxRetries` {integer} If an `EBUSY`, `EMFILE`, `ENOTEMPTY`, or `EPERM`
error is encountered, Node.js will retry the operation with a linear backoff
wait of 100ms longer on each try. This option represents the number of
retries. This option is ignored if the `recursive` option is not `true`.
wait of `retryDelay` ms longer on each try. This option represents the number
of retries. This option is ignored if the `recursive` option is not `true`.
**Default:** `0`.
* `recursive` {boolean} If `true`, perform a recursive directory removal. In
recursive mode, errors are not reported if `path` does not exist, and
operations are retried on failure. **Default:** `false`.
* `retryDelay` {integer} The amount of time in milliseconds to wait between
retries. This option is ignored if the `recursive` option is not `true`.
**Default:** `100`.
* Returns: {Promise}

Removes the directory identified by `path` then resolves the `Promise` with
Expand Down
3 changes: 2 additions & 1 deletion lib/internal/fs/rimraf.js
Expand Up @@ -35,7 +35,8 @@ function rimraf(path, options, callback) {
if (err) {
if (retryErrorCodes.has(err.code) && retries < options.maxRetries) {
retries++;
return setTimeout(_rimraf, retries * 100, path, options, CB);
const delay = retries * options.retryDelay;
return setTimeout(_rimraf, delay, path, options, CB);
}

// The file is already gone.
Expand Down
3 changes: 3 additions & 0 deletions lib/internal/fs/utils.js
Expand Up @@ -24,6 +24,7 @@ const {
const { once } = require('internal/util');
const { toPathIfFileURL } = require('internal/url');
const {
validateInt32,
validateUint32
} = require('internal/validators');
const pathModule = require('path');
Expand Down Expand Up @@ -562,6 +563,7 @@ function warnOnNonPortableTemplate(template) {
}

const defaultRmdirOptions = {
retryDelay: 100,
maxRetries: 0,
recursive: false,
};
Expand All @@ -577,6 +579,7 @@ const validateRmdirOptions = hideStackFrames((options) => {
if (typeof options.recursive !== 'boolean')
throw new ERR_INVALID_ARG_TYPE('recursive', 'boolean', options.recursive);

validateInt32(options.retryDelay, 'retryDelay', 0);
validateUint32(options.maxRetries, 'maxRetries');

return options;
Expand Down
11 changes: 11 additions & 0 deletions test/parallel/test-fs-rmdir-recursive.js
Expand Up @@ -155,10 +155,12 @@ function removeAsync(dir) {
// Test input validation.
{
const defaults = {
retryDelay: 100,
maxRetries: 0,
recursive: false
};
const modified = {
retryDelay: 953,
maxRetries: 5,
recursive: true
};
Expand All @@ -169,6 +171,7 @@ function removeAsync(dir) {
assert.deepStrictEqual(validateRmdirOptions({
maxRetries: 99
}), {
retryDelay: 100,
maxRetries: 99,
recursive: false
});
Expand All @@ -193,6 +196,14 @@ function removeAsync(dir) {
});
});

common.expectsError(() => {
validateRmdirOptions({ retryDelay: -1 });
}, {
code: 'ERR_OUT_OF_RANGE',
type: RangeError,
message: /^The value of "retryDelay" is out of range\./
});

common.expectsError(() => {
validateRmdirOptions({ maxRetries: -1 });
}, {
Expand Down

0 comments on commit f9d8494

Please sign in to comment.