@sha1n/about-time 0.0.3 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -2
- package/dist/index.js +19 -0
- package/dist/lib/retry.js +87 -0
- package/dist/lib/timeunit.js +28 -0
- package/dist/lib/utilities.js +119 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/lib/retry.d.ts +18 -0
- package/dist/types/lib/timeunit.d.ts +21 -0
- package/dist/types/lib/utilities.d.ts +49 -0
- package/index.ts +10 -3
- package/lib/utilities.ts +56 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,8 +10,10 @@
|
|
|
10
10
|
A collection of essential time related utilities.
|
|
11
11
|
|
|
12
12
|
- [About-Time](#about-time)
|
|
13
|
-
|
|
13
|
+
- [Install](#install)
|
|
14
|
+
- [Utilities & Features](#utilities--features)
|
|
14
15
|
- [Delay](#delay)
|
|
16
|
+
- [WithTimeout](#withtimeout)
|
|
15
17
|
- [Sleep](#sleep)
|
|
16
18
|
- [Stopwatch](#stopwatch)
|
|
17
19
|
- [Until / Eventually](#until--eventually)
|
|
@@ -24,17 +26,24 @@ A collection of essential time related utilities.
|
|
|
24
26
|
- [Retriable](#retriable)
|
|
25
27
|
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
# Install
|
|
28
30
|
```bash
|
|
29
31
|
npm i @sha1n/about-time
|
|
30
32
|
```
|
|
31
33
|
|
|
34
|
+
# Utilities & Features
|
|
32
35
|
## Delay
|
|
33
36
|
```ts
|
|
34
37
|
// Execute a function with delay and return it's value
|
|
35
38
|
await delay(action, 10, TimeUnit.Milliseconds);
|
|
36
39
|
```
|
|
37
40
|
|
|
41
|
+
## WithTimeout
|
|
42
|
+
```ts
|
|
43
|
+
// Execute a function and guards it with a specified timeout
|
|
44
|
+
await withTimeout(action, 10, TimeUnit.Milliseconds);
|
|
45
|
+
```
|
|
46
|
+
|
|
38
47
|
## Sleep
|
|
39
48
|
```ts
|
|
40
49
|
// Pause execution for a specified amount of time
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.exponentialBackoffRetryPolicy = exports.simpleRetryPolicy = exports.fixedRetryPolicy = exports.retriable = exports.retryAround = exports.eventually = exports.until = exports.stopwatch = exports.delay = exports.sleep = exports.withTimeout = exports.toMilliseconds = exports.TimeUnit = void 0;
|
|
4
|
+
var timeunit_1 = require("./lib/timeunit");
|
|
5
|
+
Object.defineProperty(exports, "TimeUnit", { enumerable: true, get: function () { return timeunit_1.TimeUnit; } });
|
|
6
|
+
Object.defineProperty(exports, "toMilliseconds", { enumerable: true, get: function () { return timeunit_1.toMilliseconds; } });
|
|
7
|
+
var utilities_1 = require("./lib/utilities");
|
|
8
|
+
Object.defineProperty(exports, "withTimeout", { enumerable: true, get: function () { return utilities_1.withTimeout; } });
|
|
9
|
+
Object.defineProperty(exports, "sleep", { enumerable: true, get: function () { return utilities_1.sleep; } });
|
|
10
|
+
Object.defineProperty(exports, "delay", { enumerable: true, get: function () { return utilities_1.delay; } });
|
|
11
|
+
Object.defineProperty(exports, "stopwatch", { enumerable: true, get: function () { return utilities_1.stopwatch; } });
|
|
12
|
+
Object.defineProperty(exports, "until", { enumerable: true, get: function () { return utilities_1.until; } });
|
|
13
|
+
Object.defineProperty(exports, "eventually", { enumerable: true, get: function () { return utilities_1.eventually; } });
|
|
14
|
+
var retry_1 = require("./lib/retry");
|
|
15
|
+
Object.defineProperty(exports, "retryAround", { enumerable: true, get: function () { return retry_1.retryAround; } });
|
|
16
|
+
Object.defineProperty(exports, "retriable", { enumerable: true, get: function () { return retry_1.retriable; } });
|
|
17
|
+
Object.defineProperty(exports, "fixedRetryPolicy", { enumerable: true, get: function () { return retry_1.fixedRetryPolicy; } });
|
|
18
|
+
Object.defineProperty(exports, "simpleRetryPolicy", { enumerable: true, get: function () { return retry_1.simpleRetryPolicy; } });
|
|
19
|
+
Object.defineProperty(exports, "exponentialBackoffRetryPolicy", { enumerable: true, get: function () { return retry_1.exponentialBackoffRetryPolicy; } });
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.exponentialBackoffRetryPolicy = exports.simpleRetryPolicy = exports.fixedRetryPolicy = exports.retriable = exports.retryAround = void 0;
|
|
4
|
+
const timeunit_1 = require("./timeunit");
|
|
5
|
+
const utilities_1 = require("./utilities");
|
|
6
|
+
class SimpleRetryPolicy {
|
|
7
|
+
constructor(count, interval, units) {
|
|
8
|
+
this.count = count;
|
|
9
|
+
this.interval = (0, timeunit_1.toMilliseconds)(interval, units);
|
|
10
|
+
}
|
|
11
|
+
*intervals() {
|
|
12
|
+
let count = this.count;
|
|
13
|
+
while (count > 0) {
|
|
14
|
+
count -= 1;
|
|
15
|
+
yield this.interval;
|
|
16
|
+
}
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
class ExponentialBackoffRetryPolicy {
|
|
21
|
+
constructor(count, exponential = 2, limit = Infinity, units = timeunit_1.TimeUnit.Milliseconds) {
|
|
22
|
+
this.count = count;
|
|
23
|
+
this.exponential = exponential;
|
|
24
|
+
this.limit = limit;
|
|
25
|
+
this.units = units;
|
|
26
|
+
}
|
|
27
|
+
*intervals() {
|
|
28
|
+
let index = 0;
|
|
29
|
+
while (index < this.count) {
|
|
30
|
+
const interval = Math.round((Math.pow(this.exponential, index) - 1) / 2);
|
|
31
|
+
yield Math.min(this.limit, interval) * this.units;
|
|
32
|
+
index += 1;
|
|
33
|
+
}
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
class FixedRetryPolicy {
|
|
38
|
+
constructor(intervals, units) {
|
|
39
|
+
this._intervals = intervals.reduceRight((result, v) => {
|
|
40
|
+
result.push((0, timeunit_1.toMilliseconds)(v, units));
|
|
41
|
+
return result;
|
|
42
|
+
}, []);
|
|
43
|
+
}
|
|
44
|
+
*intervals() {
|
|
45
|
+
const intervals = [...this._intervals];
|
|
46
|
+
while (intervals.length > 0) {
|
|
47
|
+
yield intervals.pop();
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function simpleRetryPolicy(count, interval, opts) {
|
|
53
|
+
return Object.freeze(new SimpleRetryPolicy(count, interval, opts === null || opts === void 0 ? void 0 : opts.units));
|
|
54
|
+
}
|
|
55
|
+
exports.simpleRetryPolicy = simpleRetryPolicy;
|
|
56
|
+
function fixedRetryPolicy(intervals, opts) {
|
|
57
|
+
return Object.freeze(new FixedRetryPolicy(intervals, opts === null || opts === void 0 ? void 0 : opts.units));
|
|
58
|
+
}
|
|
59
|
+
exports.fixedRetryPolicy = fixedRetryPolicy;
|
|
60
|
+
function exponentialBackoffRetryPolicy(count, opts) {
|
|
61
|
+
return Object.freeze(new ExponentialBackoffRetryPolicy(count, opts === null || opts === void 0 ? void 0 : opts.exponential, opts === null || opts === void 0 ? void 0 : opts.limit, opts === null || opts === void 0 ? void 0 : opts.units));
|
|
62
|
+
}
|
|
63
|
+
exports.exponentialBackoffRetryPolicy = exponentialBackoffRetryPolicy;
|
|
64
|
+
async function retryAround(action, policy, predicate = () => true) {
|
|
65
|
+
let next;
|
|
66
|
+
const intervals = policy.intervals()[Symbol.iterator]();
|
|
67
|
+
do {
|
|
68
|
+
try {
|
|
69
|
+
return await action();
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
next = intervals.next();
|
|
73
|
+
if (next.done || !predicate(e)) {
|
|
74
|
+
throw e;
|
|
75
|
+
}
|
|
76
|
+
await (0, utilities_1.sleep)(next.value);
|
|
77
|
+
}
|
|
78
|
+
} while (!next.done);
|
|
79
|
+
throw new Error('Unexpected error. This is most likely a bug.');
|
|
80
|
+
}
|
|
81
|
+
exports.retryAround = retryAround;
|
|
82
|
+
function retriable(action, policy, predicate = () => true) {
|
|
83
|
+
return () => {
|
|
84
|
+
return retryAround(action, policy, predicate);
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
exports.retriable = retriable;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toMilliseconds = exports.TimeUnit = void 0;
|
|
4
|
+
var TimeUnit;
|
|
5
|
+
(function (TimeUnit) {
|
|
6
|
+
TimeUnit[TimeUnit["Milliseconds"] = 1] = "Milliseconds";
|
|
7
|
+
TimeUnit[TimeUnit["Millisecond"] = 1] = "Millisecond";
|
|
8
|
+
TimeUnit[TimeUnit["Seconds"] = 1000] = "Seconds";
|
|
9
|
+
TimeUnit[TimeUnit["Second"] = 1000] = "Second";
|
|
10
|
+
TimeUnit[TimeUnit["Minutes"] = 60000] = "Minutes";
|
|
11
|
+
TimeUnit[TimeUnit["Minute"] = 60000] = "Minute";
|
|
12
|
+
TimeUnit[TimeUnit["Hours"] = 3600000] = "Hours";
|
|
13
|
+
TimeUnit[TimeUnit["Hour"] = 3600000] = "Hour";
|
|
14
|
+
TimeUnit[TimeUnit["Days"] = 86400000] = "Days";
|
|
15
|
+
TimeUnit[TimeUnit["Day"] = 86400000] = "Day";
|
|
16
|
+
})(TimeUnit || (TimeUnit = {}));
|
|
17
|
+
exports.TimeUnit = TimeUnit;
|
|
18
|
+
/**
|
|
19
|
+
* Converts time value in other units to milliseconds.
|
|
20
|
+
*
|
|
21
|
+
* @param time a time value to be converted
|
|
22
|
+
* @param units the units of time
|
|
23
|
+
* @returns the time value in milliseconds
|
|
24
|
+
*/
|
|
25
|
+
function toMilliseconds(time, units) {
|
|
26
|
+
return time * (units ? units : 1);
|
|
27
|
+
}
|
|
28
|
+
exports.toMilliseconds = toMilliseconds;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.eventually = exports.until = exports.stopwatch = exports.delay = exports.sleep = exports.withTimeout = void 0;
|
|
4
|
+
const timeunit_1 = require("./timeunit");
|
|
5
|
+
class TimeoutError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message || 'Timeout');
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Zzzz...
|
|
12
|
+
*
|
|
13
|
+
* @param time time to sleep
|
|
14
|
+
* @param units the units on time
|
|
15
|
+
* @returns a promise that resolves when the specified time has elapsed.
|
|
16
|
+
*/
|
|
17
|
+
function sleep(time, units) {
|
|
18
|
+
return new Promise(resolve => {
|
|
19
|
+
setTimeout(resolve, (0, timeunit_1.toMilliseconds)(time, units));
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
exports.sleep = sleep;
|
|
23
|
+
/**
|
|
24
|
+
* Delays the execution of the specified action and returns its value.
|
|
25
|
+
*
|
|
26
|
+
* @param action a function to execute with delay
|
|
27
|
+
* @param time time to sleep
|
|
28
|
+
* @param units the units on time
|
|
29
|
+
* @returns a promise that resolves when the specified time has elapsed.
|
|
30
|
+
*/
|
|
31
|
+
function delay(action, time, units) {
|
|
32
|
+
const delayMs = (0, timeunit_1.toMilliseconds)(time, units);
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
const timer = setTimeout(() => Promise.resolve(action()).then(resolve, reject), delayMs);
|
|
35
|
+
process.on('beforeExit', () => {
|
|
36
|
+
clearTimeout(timer);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
exports.delay = delay;
|
|
41
|
+
/**
|
|
42
|
+
* Return a function that returns the elapsed time relative to this call.
|
|
43
|
+
* @returns a function
|
|
44
|
+
*/
|
|
45
|
+
function stopwatch() {
|
|
46
|
+
const startTime = Date.now();
|
|
47
|
+
return (units) => {
|
|
48
|
+
return (Date.now() - startTime) / (units || timeunit_1.TimeUnit.Milliseconds);
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
exports.stopwatch = stopwatch;
|
|
52
|
+
/**
|
|
53
|
+
* Awaits a specified condition to evaluate to true with or without a timeout.
|
|
54
|
+
*
|
|
55
|
+
* @param condition the condition to wait for
|
|
56
|
+
* @param opts options that control evaluation intervals and timeout
|
|
57
|
+
* @returns a promise that resolves when the condition becomes true, or rejects when a set timeout is crossed.
|
|
58
|
+
*/
|
|
59
|
+
async function until(condition, opts) {
|
|
60
|
+
const defaultInterval = 50;
|
|
61
|
+
const deadline = opts ? Date.now() + (0, timeunit_1.toMilliseconds)(opts.timeout, opts.units) : Number.MAX_VALUE;
|
|
62
|
+
const interval = (opts === null || opts === void 0 ? void 0 : opts.interval) ? (0, timeunit_1.toMilliseconds)(opts.interval, opts.units) : defaultInterval;
|
|
63
|
+
return new Promise((resolve, reject) => {
|
|
64
|
+
const handle = setInterval(() => {
|
|
65
|
+
if (Date.now() > deadline) {
|
|
66
|
+
clearInterval(handle);
|
|
67
|
+
reject(new TimeoutError());
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
if (condition()) {
|
|
71
|
+
clearInterval(handle);
|
|
72
|
+
resolve();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch (e) {
|
|
76
|
+
clearInterval(handle);
|
|
77
|
+
reject(e);
|
|
78
|
+
}
|
|
79
|
+
}, interval);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
exports.until = until;
|
|
83
|
+
/**
|
|
84
|
+
* Alias to `until`
|
|
85
|
+
*/
|
|
86
|
+
const eventually = until;
|
|
87
|
+
exports.eventually = eventually;
|
|
88
|
+
/**
|
|
89
|
+
* Executes an action with a specified timeout. If the action times out, rejects with TimeoutError.
|
|
90
|
+
*
|
|
91
|
+
* @param action an action to execute with timeout
|
|
92
|
+
* @param timeout the timeout to set for the action
|
|
93
|
+
* @param units the time units
|
|
94
|
+
* @returns the action result
|
|
95
|
+
*/
|
|
96
|
+
async function withTimeout(action, timeout, units) {
|
|
97
|
+
const promisedAction = new Promise((resolve, reject) => {
|
|
98
|
+
try {
|
|
99
|
+
resolve(action());
|
|
100
|
+
}
|
|
101
|
+
catch (e) {
|
|
102
|
+
reject(e);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
const race = new Promise((resolve, reject) => {
|
|
106
|
+
const timer = setTimeout(() => {
|
|
107
|
+
reject(new TimeoutError());
|
|
108
|
+
}, (0, timeunit_1.toMilliseconds)(timeout, units));
|
|
109
|
+
return Promise.resolve(promisedAction).then(r => {
|
|
110
|
+
clearTimeout(timer);
|
|
111
|
+
resolve(r);
|
|
112
|
+
}, err => {
|
|
113
|
+
clearTimeout(timer);
|
|
114
|
+
reject(err);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
return race;
|
|
118
|
+
}
|
|
119
|
+
exports.withTimeout = withTimeout;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { TimeUnit, toMilliseconds } from './lib/timeunit';
|
|
2
|
+
export { withTimeout, sleep, delay, stopwatch, until, eventually } from './lib/utilities';
|
|
3
|
+
export { RetryPolicy, retryAround, retriable, fixedRetryPolicy, simpleRetryPolicy, exponentialBackoffRetryPolicy } from './lib/retry';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { TimeUnit } from './timeunit';
|
|
2
|
+
interface RetryPolicy {
|
|
3
|
+
intervals(): Iterable<number>;
|
|
4
|
+
}
|
|
5
|
+
declare function simpleRetryPolicy(count: number, interval: number, opts?: {
|
|
6
|
+
units?: TimeUnit;
|
|
7
|
+
}): RetryPolicy;
|
|
8
|
+
declare function fixedRetryPolicy(intervals: number[], opts?: {
|
|
9
|
+
units?: TimeUnit;
|
|
10
|
+
}): RetryPolicy;
|
|
11
|
+
declare function exponentialBackoffRetryPolicy(count: number, opts?: {
|
|
12
|
+
exponential?: number;
|
|
13
|
+
limit?: number;
|
|
14
|
+
units?: TimeUnit;
|
|
15
|
+
}): RetryPolicy;
|
|
16
|
+
declare function retryAround<T>(action: () => T | Promise<T>, policy: RetryPolicy, predicate?: (e: Error) => boolean): Promise<T>;
|
|
17
|
+
declare function retriable<T>(action: () => T | Promise<T>, policy: RetryPolicy, predicate?: (e: Error) => boolean): () => Promise<T>;
|
|
18
|
+
export { RetryPolicy, retryAround, retriable, fixedRetryPolicy, simpleRetryPolicy, exponentialBackoffRetryPolicy };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
declare enum TimeUnit {
|
|
2
|
+
Milliseconds = 1,
|
|
3
|
+
Millisecond = 1,
|
|
4
|
+
Seconds = 1000,
|
|
5
|
+
Second = 1000,
|
|
6
|
+
Minutes = 60000,
|
|
7
|
+
Minute = 60000,
|
|
8
|
+
Hours = 3600000,
|
|
9
|
+
Hour = 3600000,
|
|
10
|
+
Days = 86400000,
|
|
11
|
+
Day = 86400000
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Converts time value in other units to milliseconds.
|
|
15
|
+
*
|
|
16
|
+
* @param time a time value to be converted
|
|
17
|
+
* @param units the units of time
|
|
18
|
+
* @returns the time value in milliseconds
|
|
19
|
+
*/
|
|
20
|
+
declare function toMilliseconds(time: number, units?: TimeUnit): number;
|
|
21
|
+
export { TimeUnit, toMilliseconds };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { TimeUnit } from './timeunit';
|
|
2
|
+
/**
|
|
3
|
+
* Zzzz...
|
|
4
|
+
*
|
|
5
|
+
* @param time time to sleep
|
|
6
|
+
* @param units the units on time
|
|
7
|
+
* @returns a promise that resolves when the specified time has elapsed.
|
|
8
|
+
*/
|
|
9
|
+
declare function sleep(time: number, units?: TimeUnit): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Delays the execution of the specified action and returns its value.
|
|
12
|
+
*
|
|
13
|
+
* @param action a function to execute with delay
|
|
14
|
+
* @param time time to sleep
|
|
15
|
+
* @param units the units on time
|
|
16
|
+
* @returns a promise that resolves when the specified time has elapsed.
|
|
17
|
+
*/
|
|
18
|
+
declare function delay<T>(action: () => T | Promise<T>, time: number, units?: TimeUnit): Promise<T>;
|
|
19
|
+
/**
|
|
20
|
+
* Return a function that returns the elapsed time relative to this call.
|
|
21
|
+
* @returns a function
|
|
22
|
+
*/
|
|
23
|
+
declare function stopwatch(): (units?: TimeUnit) => number;
|
|
24
|
+
/**
|
|
25
|
+
* Awaits a specified condition to evaluate to true with or without a timeout.
|
|
26
|
+
*
|
|
27
|
+
* @param condition the condition to wait for
|
|
28
|
+
* @param opts options that control evaluation intervals and timeout
|
|
29
|
+
* @returns a promise that resolves when the condition becomes true, or rejects when a set timeout is crossed.
|
|
30
|
+
*/
|
|
31
|
+
declare function until(condition: () => boolean, opts?: {
|
|
32
|
+
interval?: number;
|
|
33
|
+
timeout: number;
|
|
34
|
+
units?: TimeUnit;
|
|
35
|
+
}): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Alias to `until`
|
|
38
|
+
*/
|
|
39
|
+
declare const eventually: typeof until;
|
|
40
|
+
/**
|
|
41
|
+
* Executes an action with a specified timeout. If the action times out, rejects with TimeoutError.
|
|
42
|
+
*
|
|
43
|
+
* @param action an action to execute with timeout
|
|
44
|
+
* @param timeout the timeout to set for the action
|
|
45
|
+
* @param units the time units
|
|
46
|
+
* @returns the action result
|
|
47
|
+
*/
|
|
48
|
+
declare function withTimeout<T>(action: () => T | Promise<T>, timeout: number, units?: TimeUnit): Promise<T>;
|
|
49
|
+
export { withTimeout, sleep, delay, stopwatch, until, eventually };
|
package/index.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
1
|
+
export { TimeUnit, toMilliseconds } from './lib/timeunit';
|
|
2
|
+
export { withTimeout, sleep, delay, stopwatch, until, eventually } from './lib/utilities';
|
|
3
|
+
export {
|
|
4
|
+
RetryPolicy,
|
|
5
|
+
retryAround,
|
|
6
|
+
retriable,
|
|
7
|
+
fixedRetryPolicy,
|
|
8
|
+
simpleRetryPolicy,
|
|
9
|
+
exponentialBackoffRetryPolicy
|
|
10
|
+
} from './lib/retry';
|
package/lib/utilities.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { TimeUnit, toMilliseconds } from './timeunit';
|
|
2
2
|
|
|
3
|
+
class TimeoutError extends Error {
|
|
4
|
+
constructor(message?: string) {
|
|
5
|
+
super(message || 'Timeout');
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
3
9
|
/**
|
|
4
10
|
* Zzzz...
|
|
5
11
|
*
|
|
@@ -24,7 +30,10 @@ function sleep(time: number, units?: TimeUnit): Promise<void> {
|
|
|
24
30
|
function delay<T>(action: () => T | Promise<T>, time: number, units?: TimeUnit): Promise<T> {
|
|
25
31
|
const delayMs = toMilliseconds(time, units);
|
|
26
32
|
return new Promise((resolve, reject) => {
|
|
27
|
-
setTimeout(() => Promise.resolve(action()).then(resolve, reject), delayMs);
|
|
33
|
+
const timer = setTimeout(() => Promise.resolve(action()).then(resolve, reject), delayMs);
|
|
34
|
+
process.on('beforeExit', () => {
|
|
35
|
+
clearTimeout(timer);
|
|
36
|
+
});
|
|
28
37
|
});
|
|
29
38
|
}
|
|
30
39
|
|
|
@@ -51,10 +60,6 @@ async function until(
|
|
|
51
60
|
condition: () => boolean,
|
|
52
61
|
opts?: { interval?: number; timeout: number; units?: TimeUnit }
|
|
53
62
|
): Promise<void> {
|
|
54
|
-
if (condition()) {
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
63
|
const defaultInterval = 50;
|
|
59
64
|
const deadline = opts ? Date.now() + toMilliseconds(opts.timeout, opts.units) : Number.MAX_VALUE;
|
|
60
65
|
const interval = opts?.interval ? toMilliseconds(opts.interval, opts.units) : defaultInterval;
|
|
@@ -63,12 +68,17 @@ async function until(
|
|
|
63
68
|
const handle = setInterval(() => {
|
|
64
69
|
if (Date.now() > deadline) {
|
|
65
70
|
clearInterval(handle);
|
|
66
|
-
reject(new
|
|
71
|
+
reject(new TimeoutError());
|
|
67
72
|
}
|
|
68
73
|
|
|
69
|
-
|
|
74
|
+
try {
|
|
75
|
+
if (condition()) {
|
|
76
|
+
clearInterval(handle);
|
|
77
|
+
resolve();
|
|
78
|
+
}
|
|
79
|
+
} catch (e) {
|
|
70
80
|
clearInterval(handle);
|
|
71
|
-
|
|
81
|
+
reject(e);
|
|
72
82
|
}
|
|
73
83
|
}, interval);
|
|
74
84
|
});
|
|
@@ -79,4 +89,41 @@ async function until(
|
|
|
79
89
|
*/
|
|
80
90
|
const eventually = until;
|
|
81
91
|
|
|
82
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Executes an action with a specified timeout. If the action times out, rejects with TimeoutError.
|
|
94
|
+
*
|
|
95
|
+
* @param action an action to execute with timeout
|
|
96
|
+
* @param timeout the timeout to set for the action
|
|
97
|
+
* @param units the time units
|
|
98
|
+
* @returns the action result
|
|
99
|
+
*/
|
|
100
|
+
async function withTimeout<T>(action: () => T | Promise<T>, timeout: number, units?: TimeUnit): Promise<T> {
|
|
101
|
+
const promisedAction = new Promise<T>((resolve, reject) => {
|
|
102
|
+
try {
|
|
103
|
+
resolve(action());
|
|
104
|
+
} catch (e) {
|
|
105
|
+
reject(e);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const race = new Promise<T>((resolve, reject) => {
|
|
110
|
+
const timer = setTimeout(() => {
|
|
111
|
+
reject(new TimeoutError());
|
|
112
|
+
}, toMilliseconds(timeout, units));
|
|
113
|
+
|
|
114
|
+
return Promise.resolve(promisedAction).then(
|
|
115
|
+
r => {
|
|
116
|
+
clearTimeout(timer);
|
|
117
|
+
resolve(r);
|
|
118
|
+
},
|
|
119
|
+
err => {
|
|
120
|
+
clearTimeout(timer);
|
|
121
|
+
reject(err);
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
return race;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export { withTimeout, sleep, delay, stopwatch, until, eventually };
|