@infra-blocks/retry 0.2.0 → 0.3.0-alpha.0

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 CHANGED
@@ -3,5 +3,65 @@
3
3
  [![Release](https://github.com/infra-blocks/ts-retry/actions/workflows/release.yml/badge.svg)](https://github.com/infra-blocks/ts-retry/actions/workflows/release.yml)
4
4
  [![Update From Template](https://github.com/infra-blocks/ts-retry/actions/workflows/update-from-template.yml/badge.svg)](https://github.com/infra-blocks/ts-retry/actions/workflows/update-from-template.yml)
5
5
 
6
- This repository exports generic retry utilities. The main function returns a `PromiseLike` object that also has a small `Emitter` API, allowing client code to
7
- be notified every time their function is attempted.
6
+ This repository exports generic retry utilities. It leverages the [promise-retry](https://www.npmjs.com/package/promise-retry) library under the hood.
7
+ It extends it with an event emitter API and renames some of its configuration variables.
8
+
9
+ # Retry configuration
10
+
11
+ The retry configuration uses the following values:
12
+ - `minIntervalMs`. The minimum wait time between attempts. Defaults to `1000`.
13
+ - `maxIntervalMs`. The maximum wait time between attempts. Defaults to `Infinity`.
14
+ - `factor`. The exponential factor to use. See LINK. Defaults to `1`.
15
+ - `retries`. The amount of *retries* made (not including the first call). Defaults to `60`.
16
+ - `isRetryableError`. A predicate function that determines whether an error should trigger a retry. Defaults to `() => true`.
17
+
18
+ You invoke it as such with the default configuration:
19
+ ```ts
20
+ import {retry} from "@infra-blocks/retry";
21
+
22
+ // This promise resolves when `myFunc` resolves, or rejects with the last error returned
23
+ // by `myFunc` on that last retry.
24
+ await retry(myFunc);
25
+ ```
26
+
27
+ To tweak its behaviors, simply pass the desired modifications as the second argument to the retry
28
+ invocation:
29
+ ```ts
30
+ await retry(
31
+ myFunc,
32
+ {
33
+ retries: 9,
34
+ factor: 2,
35
+ minIntervalMs: 150,
36
+ maxIntervalMs: 20_000,
37
+ isRetryableError: (err) => err.name === "RetryableError"
38
+ }
39
+ );
40
+ ```
41
+
42
+ # Event emitter API
43
+
44
+ The API also allows caller code to subscribe to `attempt` and `retry` events. `attempt` events are emitted on *every* attempt, including
45
+ the first. `retry` events only start being emitted on the *second* attempt, meaning an error always occurred before a `retry` event.
46
+
47
+ The `attempt` event handler has the following call signature:
48
+ ```ts
49
+ (params: {
50
+ attempt: number; // Starts at 1.
51
+ retryConfig: Required<RetryConfig<E>>; // This is the effective retry configuration used.
52
+ }) => void;`
53
+ ```
54
+ And the `retry` event handler has the following call signature:
55
+ ```ts
56
+ (params: {
57
+ retry: number; // Starts at 1.
58
+ retryConfig: Required<RetryConfig<E>>;
59
+ }) => void;
60
+ ```
61
+
62
+ Example:
63
+ ```ts
64
+ await retry(startMongoDbContainer)
65
+ .once("attempt", () => logger.info("starting MongoDB container"))
66
+ .on("retry", ({retry}) => logger.debug(`polling MongoDB for health check, retry: ${retry}`));
67
+ ```
@@ -55,12 +55,29 @@ export type RetryEvents<E = Error> = {
55
55
  /**
56
56
  * This event is emitted at the beginning of every attempt.
57
57
  *
58
- * @param attempt - The attempt number. Starts with 1, and the first attempt does not count as a retry.
58
+ * Note that it is emitted regardless of whether this is the first attempt or it corresponds to a retry.
59
+ *
60
+ * @param params.attempt - The attempt number. Starts with 1, and the first attempt does not count as a retry.
61
+ * @param params.retryConfig - The full effective retry configuration used for this retry process.
59
62
  */
60
63
  attempt: (params: {
61
64
  attempt: number;
62
65
  retryConfig: Required<RetryConfig<E>>;
63
66
  }) => void;
67
+ /**
68
+ * This event is emitted when a retry is about to be performed.
69
+ *
70
+ * Unlike the `attempt` event, it is only emitted after a failure has occurred. However,
71
+ * for every emitted `retry` event, there is a corresponding `attempt`. `attempt` is called
72
+ * first.
73
+ *
74
+ * @param params.retry - The retry number. Starts with 1, which equates to attempt number 2.
75
+ * @param params.retryConfig - The full effective retry configuration used for this retry process.
76
+ */
77
+ retry: (params: {
78
+ retry: number;
79
+ retryConfig: Required<RetryConfig<E>>;
80
+ }) => void;
64
81
  };
65
82
  /**
66
83
  * Type returned by the {@link retry} function.
package/lib/cjs/index.js CHANGED
@@ -31,6 +31,12 @@ class RetryImpl extends emitter_1.EmitterLikeBase {
31
31
  attempt,
32
32
  retryConfig: { ...this.retryConfig },
33
33
  });
34
+ if (attempt > 1) {
35
+ this.emit("retry", {
36
+ retry: attempt - 1,
37
+ retryConfig: { ...this.retryConfig },
38
+ });
39
+ }
34
40
  return fn();
35
41
  };
36
42
  this.promise = retryPromise(wrapper, this.retryConfig);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,8CAA+C;AAC/C,mDAAqE;AAGrE;;;;;;;;;GASG;AACU,QAAA,oBAAoB,GAAmC;IAClE,OAAO,EAAE,EAAE;IACX,MAAM,EAAE,CAAC;IACT,aAAa,EAAE,IAAI;IACnB,aAAa,EAAE,QAAQ;IACvB,gBAAgB,EAAE,GAAY,EAAE,CAAC,IAAI;CACtC,CAAC;AAsEF,MAAM,SACJ,SAAQ,yBAA+B;IAGpB,OAAO,CAAiB;IACxB,WAAW,CAA2B;IAEzD,YAAY,EAAoB,EAAE,OAAwB;QACxD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,WAAW,GAAG,EAAE,GAAG,4BAAoB,EAAE,GAAG,OAAO,EAAE,CAAC;QAE3D,MAAM,OAAO,GAAG,CAAC,OAAe,EAAE,EAAE;YAClC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;gBACnB,OAAO;gBACP,WAAW,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE;aACrC,CAAC,CAAC;YACH,OAAO,EAAE,EAAE,CAAC;QACd,CAAC,CAAC;QACF,IAAI,CAAC,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,CACF,WAGQ,EACR,UAGQ;QAER,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;CACF;AAED;;;;;;;GAOG;AACH,SAAgB,KAAK,CACnB,EAAoB,EACpB,OAAwB;IAExB,OAAO,IAAI,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;AACpC,CAAC;AALD,sBAKC;AAED;;;;;;;;;;;GAWG;AACH,KAAK,UAAU,YAAY,CACzB,EAAmC,EACnC,OAAwB;IAExB,MAAM,EACJ,OAAO,GAAG,4BAAoB,CAAC,OAAO,EACtC,MAAM,GAAG,4BAAoB,CAAC,MAAM,EACpC,aAAa,GAAG,4BAAoB,CAAC,aAAa,EAClD,aAAa,GAAG,4BAAoB,CAAC,aAAa,EAClD,gBAAgB,GAAG,4BAAoB,CAAC,gBAAgB,GACzD,GAAG,OAAO,IAAI,EAAE,CAAC;IAElB,OAAO,MAAM,YAAY,CACvB,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,EACzE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE;QAC5B,IAAI;YACF,OAAO,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC;SAC1B;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,gBAAgB,CAAC,GAAQ,CAAC,EAAE;gBAC9B,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC;aACxB;YACD,MAAM,GAAG,CAAC;SACX;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,8CAA+C;AAC/C,mDAAqE;AAGrE;;;;;;;;;GASG;AACU,QAAA,oBAAoB,GAAmC;IAClE,OAAO,EAAE,EAAE;IACX,MAAM,EAAE,CAAC;IACT,aAAa,EAAE,IAAI;IACnB,aAAa,EAAE,QAAQ;IACvB,gBAAgB,EAAE,GAAY,EAAE,CAAC,IAAI;CACtC,CAAC;AAwFF,MAAM,SACJ,SAAQ,yBAA+B;IAGpB,OAAO,CAAiB;IACxB,WAAW,CAA2B;IAEzD,YAAY,EAAoB,EAAE,OAAwB;QACxD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,WAAW,GAAG,EAAE,GAAG,4BAAoB,EAAE,GAAG,OAAO,EAAE,CAAC;QAE3D,MAAM,OAAO,GAAG,CAAC,OAAe,EAAE,EAAE;YAClC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;gBACnB,OAAO;gBACP,WAAW,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE;aACrC,CAAC,CAAC;YACH,IAAI,OAAO,GAAG,CAAC,EAAE;gBACf,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;oBACjB,KAAK,EAAE,OAAO,GAAG,CAAC;oBAClB,WAAW,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE;iBACrC,CAAC,CAAC;aACJ;YACD,OAAO,EAAE,EAAE,CAAC;QACd,CAAC,CAAC;QACF,IAAI,CAAC,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,CACF,WAGQ,EACR,UAGQ;QAER,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;CACF;AAED;;;;;;;GAOG;AACH,SAAgB,KAAK,CACnB,EAAoB,EACpB,OAAwB;IAExB,OAAO,IAAI,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;AACpC,CAAC;AALD,sBAKC;AAED;;;;;;;;;;;GAWG;AACH,KAAK,UAAU,YAAY,CACzB,EAAmC,EACnC,OAAwB;IAExB,MAAM,EACJ,OAAO,GAAG,4BAAoB,CAAC,OAAO,EACtC,MAAM,GAAG,4BAAoB,CAAC,MAAM,EACpC,aAAa,GAAG,4BAAoB,CAAC,aAAa,EAClD,aAAa,GAAG,4BAAoB,CAAC,aAAa,EAClD,gBAAgB,GAAG,4BAAoB,CAAC,gBAAgB,GACzD,GAAG,OAAO,IAAI,EAAE,CAAC;IAElB,OAAO,MAAM,YAAY,CACvB,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,EACzE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE;QAC5B,IAAI;YACF,OAAO,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC;SAC1B;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,gBAAgB,CAAC,GAAQ,CAAC,EAAE;gBAC9B,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC;aACxB;YACD,MAAM,GAAG,CAAC;SACX;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -55,12 +55,29 @@ export type RetryEvents<E = Error> = {
55
55
  /**
56
56
  * This event is emitted at the beginning of every attempt.
57
57
  *
58
- * @param attempt - The attempt number. Starts with 1, and the first attempt does not count as a retry.
58
+ * Note that it is emitted regardless of whether this is the first attempt or it corresponds to a retry.
59
+ *
60
+ * @param params.attempt - The attempt number. Starts with 1, and the first attempt does not count as a retry.
61
+ * @param params.retryConfig - The full effective retry configuration used for this retry process.
59
62
  */
60
63
  attempt: (params: {
61
64
  attempt: number;
62
65
  retryConfig: Required<RetryConfig<E>>;
63
66
  }) => void;
67
+ /**
68
+ * This event is emitted when a retry is about to be performed.
69
+ *
70
+ * Unlike the `attempt` event, it is only emitted after a failure has occurred. However,
71
+ * for every emitted `retry` event, there is a corresponding `attempt`. `attempt` is called
72
+ * first.
73
+ *
74
+ * @param params.retry - The retry number. Starts with 1, which equates to attempt number 2.
75
+ * @param params.retryConfig - The full effective retry configuration used for this retry process.
76
+ */
77
+ retry: (params: {
78
+ retry: number;
79
+ retryConfig: Required<RetryConfig<E>>;
80
+ }) => void;
64
81
  };
65
82
  /**
66
83
  * Type returned by the {@link retry} function.
package/lib/esm/index.js CHANGED
@@ -30,6 +30,12 @@ class RetryImpl extends EmitterLikeBase {
30
30
  attempt,
31
31
  retryConfig: { ...this.retryConfig },
32
32
  });
33
+ if (attempt > 1) {
34
+ this.emit("retry", {
35
+ retry: attempt - 1,
36
+ retryConfig: { ...this.retryConfig },
37
+ });
38
+ }
33
39
  return fn();
34
40
  };
35
41
  this.promise = retryPromise(wrapper, this.retryConfig);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;AAAA,gDAA+C;AAC/C,OAAO,EAAe,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGrE;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAmC;IAClE,OAAO,EAAE,EAAE;IACX,MAAM,EAAE,CAAC;IACT,aAAa,EAAE,IAAI;IACnB,aAAa,EAAE,QAAQ;IACvB,gBAAgB,EAAE,GAAY,EAAE,CAAC,IAAI;CACtC,CAAC;AAsEF,MAAM,SACJ,SAAQ,eAA+B;IAGpB,OAAO,CAAiB;IACxB,WAAW,CAA2B;IAEzD,YAAY,EAAoB,EAAE,OAAwB;QACxD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,WAAW,GAAG,EAAE,GAAG,oBAAoB,EAAE,GAAG,OAAO,EAAE,CAAC;QAE3D,MAAM,OAAO,GAAG,CAAC,OAAe,EAAE,EAAE;YAClC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;gBACnB,OAAO;gBACP,WAAW,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE;aACrC,CAAC,CAAC;YACH,OAAO,EAAE,EAAE,CAAC;QACd,CAAC,CAAC;QACF,IAAI,CAAC,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,CACF,WAGQ,EACR,UAGQ;QAER,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,KAAK,CACnB,EAAoB,EACpB,OAAwB;IAExB,OAAO,IAAI,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,KAAK,UAAU,YAAY,CACzB,EAAmC,EACnC,OAAwB;IAExB,MAAM,EACJ,OAAO,GAAG,oBAAoB,CAAC,OAAO,EACtC,MAAM,GAAG,oBAAoB,CAAC,MAAM,EACpC,aAAa,GAAG,oBAAoB,CAAC,aAAa,EAClD,aAAa,GAAG,oBAAoB,CAAC,aAAa,EAClD,gBAAgB,GAAG,oBAAoB,CAAC,gBAAgB,GACzD,GAAG,OAAO,IAAI,EAAE,CAAC;IAElB,OAAO,MAAM,YAAY,CACvB,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,EACzE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE;QAC5B,IAAI;YACF,OAAO,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC;SAC1B;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,gBAAgB,CAAC,GAAQ,CAAC,EAAE;gBAC9B,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC;aACxB;YACD,MAAM,GAAG,CAAC;SACX;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;AAAA,gDAA+C;AAC/C,OAAO,EAAe,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGrE;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAmC;IAClE,OAAO,EAAE,EAAE;IACX,MAAM,EAAE,CAAC;IACT,aAAa,EAAE,IAAI;IACnB,aAAa,EAAE,QAAQ;IACvB,gBAAgB,EAAE,GAAY,EAAE,CAAC,IAAI;CACtC,CAAC;AAwFF,MAAM,SACJ,SAAQ,eAA+B;IAGpB,OAAO,CAAiB;IACxB,WAAW,CAA2B;IAEzD,YAAY,EAAoB,EAAE,OAAwB;QACxD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,WAAW,GAAG,EAAE,GAAG,oBAAoB,EAAE,GAAG,OAAO,EAAE,CAAC;QAE3D,MAAM,OAAO,GAAG,CAAC,OAAe,EAAE,EAAE;YAClC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;gBACnB,OAAO;gBACP,WAAW,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE;aACrC,CAAC,CAAC;YACH,IAAI,OAAO,GAAG,CAAC,EAAE;gBACf,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;oBACjB,KAAK,EAAE,OAAO,GAAG,CAAC;oBAClB,WAAW,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE;iBACrC,CAAC,CAAC;aACJ;YACD,OAAO,EAAE,EAAE,CAAC;QACd,CAAC,CAAC;QACF,IAAI,CAAC,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,CACF,WAGQ,EACR,UAGQ;QAER,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,KAAK,CACnB,EAAoB,EACpB,OAAwB;IAExB,OAAO,IAAI,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,KAAK,UAAU,YAAY,CACzB,EAAmC,EACnC,OAAwB;IAExB,MAAM,EACJ,OAAO,GAAG,oBAAoB,CAAC,OAAO,EACtC,MAAM,GAAG,oBAAoB,CAAC,MAAM,EACpC,aAAa,GAAG,oBAAoB,CAAC,aAAa,EAClD,aAAa,GAAG,oBAAoB,CAAC,aAAa,EAClD,gBAAgB,GAAG,oBAAoB,CAAC,gBAAgB,GACzD,GAAG,OAAO,IAAI,EAAE,CAAC;IAElB,OAAO,MAAM,YAAY,CACvB,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,EACzE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE;QAC5B,IAAI;YACF,OAAO,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC;SAC1B;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,gBAAgB,CAAC,GAAQ,CAAC,EAAE;gBAC9B,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC;aACxB;YACD,MAAM,GAAG,CAAC;SACX;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@infra-blocks/retry",
3
- "version": "0.2.0",
3
+ "version": "0.3.0-alpha.0",
4
4
  "description": "This repository exports utilities for generic retry logic.",
5
5
  "keywords": [
6
6
  "retry",