@sha1n/about-time 0.0.1 → 0.0.2
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 +13 -6
- package/dist/lib/retry.js +4 -4
- package/dist/lib/utilities.js +3 -7
- package/dist/types/lib/retry.d.ts +2 -2
- package/lib/retry.ts +11 -34
- package/lib/utilities.ts +4 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
# About-Time
|
|
9
9
|
|
|
10
|
-
A
|
|
10
|
+
A collection of essential time related utilities.
|
|
11
11
|
|
|
12
12
|
- [About-Time](#about-time)
|
|
13
13
|
- [Install](#install)
|
|
@@ -78,20 +78,27 @@ const retryPolicy = fixedRetryPolicy([3, 10, 50, 100], TimeUnit.Milliseconds);
|
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
#### Exponential backoff retry policy
|
|
81
|
+
Exponential backoff formula based retry policy with optional custom exponent base and a limit.
|
|
82
|
+
The optional `limit` provides control over maximum pause intervals, so they don't soar beyond reasonable values.
|
|
83
|
+
|
|
84
|
+
**The formula used by this implementation is the following:**
|
|
85
|
+
|
|
86
|
+
interval<sub>i</sub> = min(limit, (exponential<sup>i</sup> - 1) / 2)
|
|
87
|
+
|
|
81
88
|
```ts
|
|
82
|
-
// 10 retries, starting with 10 milliseconds and then exponentially increases the delay based on the default power value without a limit.
|
|
83
89
|
const retryPolicy = exponentialBackoffRetryPolicy(/* count = */10, /* opts?: { exponential?: number, limit?: number, units?: TimeUnit }*/);
|
|
84
90
|
```
|
|
85
91
|
|
|
86
92
|
### RetryAround
|
|
87
|
-
Executes the given function with
|
|
93
|
+
Executes the given function with retries based on the specified policy and *optional* predicate.
|
|
94
|
+
The predicate provides control over which errors we want to retry on.
|
|
88
95
|
```ts
|
|
89
|
-
const result = await retryAround(action, retryPolicy);
|
|
96
|
+
const result = await retryAround(action, retryPolicy, predicate);
|
|
90
97
|
```
|
|
91
98
|
|
|
92
99
|
### Retriable
|
|
93
|
-
Wraps a given function with `retryAround` with the specified
|
|
100
|
+
Wraps a given function with `retryAround` with the specified arguments.
|
|
94
101
|
```ts
|
|
95
|
-
const retriableAction = retriable(action, retryPolicy);
|
|
102
|
+
const retriableAction = retriable(action, retryPolicy, predicate);
|
|
96
103
|
const result = await retriableAction();
|
|
97
104
|
```
|
package/dist/lib/retry.js
CHANGED
|
@@ -61,7 +61,7 @@ function exponentialBackoffRetryPolicy(count, opts) {
|
|
|
61
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
62
|
}
|
|
63
63
|
exports.exponentialBackoffRetryPolicy = exponentialBackoffRetryPolicy;
|
|
64
|
-
async function retryAround(action, policy) {
|
|
64
|
+
async function retryAround(action, policy, predicate = () => true) {
|
|
65
65
|
let next;
|
|
66
66
|
const intervals = policy.intervals()[Symbol.iterator]();
|
|
67
67
|
do {
|
|
@@ -70,7 +70,7 @@ async function retryAround(action, policy) {
|
|
|
70
70
|
}
|
|
71
71
|
catch (e) {
|
|
72
72
|
next = intervals.next();
|
|
73
|
-
if (next.done) {
|
|
73
|
+
if (next.done || !predicate(e)) {
|
|
74
74
|
throw e;
|
|
75
75
|
}
|
|
76
76
|
await (0, utilities_1.sleep)(next.value);
|
|
@@ -79,9 +79,9 @@ async function retryAround(action, policy) {
|
|
|
79
79
|
throw new Error('Unexpected error. This is most likely a bug.');
|
|
80
80
|
}
|
|
81
81
|
exports.retryAround = retryAround;
|
|
82
|
-
function retriable(action, policy) {
|
|
82
|
+
function retriable(action, policy, predicate = () => true) {
|
|
83
83
|
return () => {
|
|
84
|
-
return retryAround(action, policy);
|
|
84
|
+
return retryAround(action, policy, predicate);
|
|
85
85
|
};
|
|
86
86
|
}
|
|
87
87
|
exports.retriable = retriable;
|
package/dist/lib/utilities.js
CHANGED
|
@@ -10,7 +10,7 @@ const timeunit_1 = require("./timeunit");
|
|
|
10
10
|
* @returns a promise that resolves when the specified time has elapsed.
|
|
11
11
|
*/
|
|
12
12
|
function sleep(time, units) {
|
|
13
|
-
return new Promise(
|
|
13
|
+
return new Promise(resolve => {
|
|
14
14
|
setTimeout(resolve, (0, timeunit_1.toMilliseconds)(time, units));
|
|
15
15
|
});
|
|
16
16
|
}
|
|
@@ -53,12 +53,8 @@ async function until(condition, opts) {
|
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
55
|
const defaultInterval = 50;
|
|
56
|
-
const deadline = opts
|
|
57
|
-
|
|
58
|
-
: Number.MAX_VALUE;
|
|
59
|
-
const interval = (opts === null || opts === void 0 ? void 0 : opts.interval)
|
|
60
|
-
? (0, timeunit_1.toMilliseconds)(opts.interval, opts.units)
|
|
61
|
-
: defaultInterval;
|
|
56
|
+
const deadline = opts ? Date.now() + (0, timeunit_1.toMilliseconds)(opts.timeout, opts.units) : Number.MAX_VALUE;
|
|
57
|
+
const interval = (opts === null || opts === void 0 ? void 0 : opts.interval) ? (0, timeunit_1.toMilliseconds)(opts.interval, opts.units) : defaultInterval;
|
|
62
58
|
return new Promise((resolve, reject) => {
|
|
63
59
|
const handle = setInterval(() => {
|
|
64
60
|
if (Date.now() > deadline) {
|
|
@@ -13,6 +13,6 @@ declare function exponentialBackoffRetryPolicy(count: number, opts?: {
|
|
|
13
13
|
limit?: number;
|
|
14
14
|
units?: TimeUnit;
|
|
15
15
|
}): RetryPolicy;
|
|
16
|
-
declare function retryAround<T>(action: () => T | Promise<T>, policy: RetryPolicy): Promise<T>;
|
|
17
|
-
declare function retriable<T>(action: () => T | Promise<T>, policy: RetryPolicy): () => Promise<T>;
|
|
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
18
|
export { RetryPolicy, retryAround, retriable, fixedRetryPolicy, simpleRetryPolicy, exponentialBackoffRetryPolicy };
|
package/lib/retry.ts
CHANGED
|
@@ -8,11 +8,7 @@ interface RetryPolicy {
|
|
|
8
8
|
class SimpleRetryPolicy implements RetryPolicy {
|
|
9
9
|
private readonly interval: number;
|
|
10
10
|
|
|
11
|
-
constructor(
|
|
12
|
-
private readonly count: number,
|
|
13
|
-
interval: number,
|
|
14
|
-
units?: TimeUnit
|
|
15
|
-
) {
|
|
11
|
+
constructor(private readonly count: number, interval: number, units?: TimeUnit) {
|
|
16
12
|
this.interval = toMilliseconds(interval, units);
|
|
17
13
|
}
|
|
18
14
|
|
|
@@ -68,18 +64,11 @@ class FixedRetryPolicy implements RetryPolicy {
|
|
|
68
64
|
}
|
|
69
65
|
}
|
|
70
66
|
|
|
71
|
-
function simpleRetryPolicy(
|
|
72
|
-
count: number,
|
|
73
|
-
interval: number,
|
|
74
|
-
opts?: { units?: TimeUnit }
|
|
75
|
-
): RetryPolicy {
|
|
67
|
+
function simpleRetryPolicy(count: number, interval: number, opts?: { units?: TimeUnit }): RetryPolicy {
|
|
76
68
|
return Object.freeze(new SimpleRetryPolicy(count, interval, opts?.units));
|
|
77
69
|
}
|
|
78
70
|
|
|
79
|
-
function fixedRetryPolicy(
|
|
80
|
-
intervals: number[],
|
|
81
|
-
opts?: { units?: TimeUnit }
|
|
82
|
-
): RetryPolicy {
|
|
71
|
+
function fixedRetryPolicy(intervals: number[], opts?: { units?: TimeUnit }): RetryPolicy {
|
|
83
72
|
return Object.freeze(new FixedRetryPolicy(intervals, opts?.units));
|
|
84
73
|
}
|
|
85
74
|
|
|
@@ -87,19 +76,13 @@ function exponentialBackoffRetryPolicy(
|
|
|
87
76
|
count: number,
|
|
88
77
|
opts?: { exponential?: number; limit?: number; units?: TimeUnit }
|
|
89
78
|
): RetryPolicy {
|
|
90
|
-
return Object.freeze(
|
|
91
|
-
new ExponentialBackoffRetryPolicy(
|
|
92
|
-
count,
|
|
93
|
-
opts?.exponential,
|
|
94
|
-
opts?.limit,
|
|
95
|
-
opts?.units
|
|
96
|
-
)
|
|
97
|
-
);
|
|
79
|
+
return Object.freeze(new ExponentialBackoffRetryPolicy(count, opts?.exponential, opts?.limit, opts?.units));
|
|
98
80
|
}
|
|
99
81
|
|
|
100
82
|
async function retryAround<T>(
|
|
101
83
|
action: () => T | Promise<T>,
|
|
102
|
-
policy: RetryPolicy
|
|
84
|
+
policy: RetryPolicy,
|
|
85
|
+
predicate: (e: Error) => boolean = () => true
|
|
103
86
|
): Promise<T> {
|
|
104
87
|
let next: IteratorResult<number, undefined>;
|
|
105
88
|
const intervals = policy.intervals()[Symbol.iterator]();
|
|
@@ -109,7 +92,7 @@ async function retryAround<T>(
|
|
|
109
92
|
} catch (e) {
|
|
110
93
|
next = intervals.next();
|
|
111
94
|
|
|
112
|
-
if (next.done) {
|
|
95
|
+
if (next.done || !predicate(e)) {
|
|
113
96
|
throw e;
|
|
114
97
|
}
|
|
115
98
|
|
|
@@ -122,18 +105,12 @@ async function retryAround<T>(
|
|
|
122
105
|
|
|
123
106
|
function retriable<T>(
|
|
124
107
|
action: () => T | Promise<T>,
|
|
125
|
-
policy: RetryPolicy
|
|
108
|
+
policy: RetryPolicy,
|
|
109
|
+
predicate: (e: Error) => boolean = () => true
|
|
126
110
|
): () => Promise<T> {
|
|
127
111
|
return () => {
|
|
128
|
-
return retryAround(action, policy);
|
|
112
|
+
return retryAround(action, policy, predicate);
|
|
129
113
|
};
|
|
130
114
|
}
|
|
131
115
|
|
|
132
|
-
export {
|
|
133
|
-
RetryPolicy,
|
|
134
|
-
retryAround,
|
|
135
|
-
retriable,
|
|
136
|
-
fixedRetryPolicy,
|
|
137
|
-
simpleRetryPolicy,
|
|
138
|
-
exponentialBackoffRetryPolicy
|
|
139
|
-
};
|
|
116
|
+
export { RetryPolicy, retryAround, retriable, fixedRetryPolicy, simpleRetryPolicy, exponentialBackoffRetryPolicy };
|
package/lib/utilities.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { TimeUnit, toMilliseconds } from './timeunit';
|
|
|
8
8
|
* @returns a promise that resolves when the specified time has elapsed.
|
|
9
9
|
*/
|
|
10
10
|
function sleep(time: number, units?: TimeUnit): Promise<void> {
|
|
11
|
-
return new Promise(
|
|
11
|
+
return new Promise(resolve => {
|
|
12
12
|
setTimeout(resolve, toMilliseconds(time, units));
|
|
13
13
|
});
|
|
14
14
|
}
|
|
@@ -21,11 +21,7 @@ function sleep(time: number, units?: TimeUnit): Promise<void> {
|
|
|
21
21
|
* @param units the units on time
|
|
22
22
|
* @returns a promise that resolves when the specified time has elapsed.
|
|
23
23
|
*/
|
|
24
|
-
function delay<T>(
|
|
25
|
-
action: () => T | Promise<T>,
|
|
26
|
-
time: number,
|
|
27
|
-
units?: TimeUnit
|
|
28
|
-
): Promise<T> {
|
|
24
|
+
function delay<T>(action: () => T | Promise<T>, time: number, units?: TimeUnit): Promise<T> {
|
|
29
25
|
const delayMs = toMilliseconds(time, units);
|
|
30
26
|
return new Promise((resolve, reject) => {
|
|
31
27
|
setTimeout(() => Promise.resolve(action()).then(resolve, reject), delayMs);
|
|
@@ -60,12 +56,8 @@ async function until(
|
|
|
60
56
|
}
|
|
61
57
|
|
|
62
58
|
const defaultInterval = 50;
|
|
63
|
-
const deadline = opts
|
|
64
|
-
|
|
65
|
-
: Number.MAX_VALUE;
|
|
66
|
-
const interval = opts?.interval
|
|
67
|
-
? toMilliseconds(opts.interval, opts.units)
|
|
68
|
-
: defaultInterval;
|
|
59
|
+
const deadline = opts ? Date.now() + toMilliseconds(opts.timeout, opts.units) : Number.MAX_VALUE;
|
|
60
|
+
const interval = opts?.interval ? toMilliseconds(opts.interval, opts.units) : defaultInterval;
|
|
69
61
|
|
|
70
62
|
return new Promise<void>((resolve, reject) => {
|
|
71
63
|
const handle = setInterval(() => {
|