@naturalcycles/js-lib 14.79.0 → 14.82.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/dist/decorators/retry.decorator.js +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.js +2 -2
- package/dist/json-schema/jsonSchemaBuilder.d.ts +2 -2
- package/dist/json-schema/jsonSchemaBuilder.js +4 -4
- package/dist/json-schema/jsonSchemas.d.ts +2 -2
- package/dist/promise/AggregatedError.d.ts +1 -1
- package/dist/promise/AggregatedError.js +2 -7
- package/dist/promise/pFilter.d.ts +2 -3
- package/dist/promise/pFilter.js +4 -4
- package/dist/promise/pMap.d.ts +1 -1
- package/dist/promise/pMap.js +67 -19
- package/dist/promise/pRetry.d.ts +17 -2
- package/dist/promise/pRetry.js +72 -40
- package/dist/types.d.ts +10 -10
- package/dist-esm/decorators/retry.decorator.js +2 -2
- package/dist-esm/index.js +2 -3
- package/dist-esm/json-schema/jsonSchemaBuilder.js +4 -4
- package/dist-esm/promise/AggregatedError.js +2 -7
- package/dist-esm/promise/pFilter.js +4 -4
- package/dist-esm/promise/pMap.js +79 -19
- package/dist-esm/promise/pRetry.js +70 -39
- package/package.json +1 -1
- package/src/decorators/retry.decorator.ts +2 -2
- package/src/index.ts +2 -2
- package/src/json-schema/jsonSchemaBuilder.ts +4 -4
- package/src/promise/AggregatedError.ts +3 -8
- package/src/promise/pFilter.ts +5 -14
- package/src/promise/pMap.ts +72 -21
- package/src/promise/pRetry.ts +105 -41
- package/src/types.ts +10 -10
- package/dist/promise/pBatch.d.ts +0 -7
- package/dist/promise/pBatch.js +0 -30
- package/dist-esm/promise/pBatch.js +0 -23
- package/src/promise/pBatch.ts +0 -31
|
@@ -6,7 +6,7 @@ const __1 = require("..");
|
|
|
6
6
|
function _Retry(opt = {}) {
|
|
7
7
|
return (target, key, descriptor) => {
|
|
8
8
|
const originalFn = descriptor.value;
|
|
9
|
-
descriptor.value = (0, __1.
|
|
9
|
+
descriptor.value = (0, __1.pRetryFn)(originalFn, opt);
|
|
10
10
|
return descriptor;
|
|
11
11
|
};
|
|
12
12
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -34,14 +34,13 @@ export * from './object/object.util';
|
|
|
34
34
|
export * from './object/sortObject';
|
|
35
35
|
export * from './object/sortObjectDeep';
|
|
36
36
|
import { AggregatedError } from './promise/AggregatedError';
|
|
37
|
-
export * from './promise/pBatch';
|
|
38
37
|
import { DeferredPromise, pDefer } from './promise/pDefer';
|
|
39
38
|
export * from './promise/pDelay';
|
|
40
39
|
export * from './promise/pFilter';
|
|
41
40
|
export * from './promise/pHang';
|
|
42
41
|
import { pMap, PMapOptions } from './promise/pMap';
|
|
43
42
|
export * from './promise/pProps';
|
|
44
|
-
import { pRetry, PRetryOptions } from './promise/pRetry';
|
|
43
|
+
import { pRetry, pRetryFn, PRetryOptions } from './promise/pRetry';
|
|
45
44
|
export * from './promise/pState';
|
|
46
45
|
import { pTimeout, pTimeoutFn, PTimeoutOptions } from './promise/pTimeout';
|
|
47
46
|
export * from './promise/pTuple';
|
|
@@ -60,4 +59,4 @@ import { PQueue, PQueueCfg } from './promise/pQueue';
|
|
|
60
59
|
export * from './seq/seq';
|
|
61
60
|
export * from './math/stack.util';
|
|
62
61
|
export type { AbortableMapper, AbortablePredicate, AbortableAsyncPredicate, AbortableAsyncMapper, PQueueCfg, MemoCache, PromiseDecoratorCfg, PromiseDecoratorResp, ErrorData, ErrorObject, HttpErrorData, HttpErrorResponse, Admin401ErrorData, Admin403ErrorData, StringMap, PromiseMap, AnyObject, AnyFunction, ValuesOf, ValueOf, KeyValueTuple, ObjectMapper, ObjectPredicate, InstanceId, IsoDate, IsoDateTime, Reviver, PMapOptions, Mapper, AsyncMapper, Predicate, AsyncPredicate, BatchResult, DeferredPromise, PRetryOptions, PTimeoutOptions, TryCatchOptions, StringifyAnyOptions, JsonStringifyFunction, Merge, ReadonlyDeep, Promisable, Simplify, ConditionalPick, ConditionalExcept, Class, UnixTimestamp, BaseDBEntity, SavedDBEntity, Saved, Unsaved, CreatedUpdated, CreatedUpdatedId, ObjectWithId, AnyObjectWithId, JsonSchema, JsonSchemaAny, JsonSchemaOneOf, JsonSchemaAllOf, JsonSchemaAnyOf, JsonSchemaNot, JsonSchemaRef, JsonSchemaConst, JsonSchemaEnum, JsonSchemaString, JsonSchemaNumber, JsonSchemaBoolean, JsonSchemaNull, JsonSchemaRootObject, JsonSchemaObject, JsonSchemaArray, JsonSchemaTuple, JsonSchemaBuilder, CommonLogLevel, CommonLogWithLevelFunction, CommonLogFunction, CommonLogger, };
|
|
63
|
-
export { is, _createPromiseDecorator, _stringMapValues, _stringMapEntries, _objectKeys, pMap, _passthroughMapper, _passUndefinedMapper, _passthroughPredicate, _passNothingPredicate, _noop, ErrorMode, pDefer, AggregatedError, pRetry, pTimeout, pTimeoutFn, _tryCatch, _TryCatch, _stringifyAny, jsonSchema, JsonSchemaAnyBuilder, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, commonLoggerCreate, PQueue, END, SKIP, };
|
|
62
|
+
export { is, _createPromiseDecorator, _stringMapValues, _stringMapEntries, _objectKeys, pMap, _passthroughMapper, _passUndefinedMapper, _passthroughPredicate, _passNothingPredicate, _noop, ErrorMode, pDefer, AggregatedError, pRetry, pRetryFn, pTimeout, pTimeoutFn, _tryCatch, _TryCatch, _stringifyAny, jsonSchema, JsonSchemaAnyBuilder, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, commonLoggerCreate, PQueue, END, SKIP, };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SKIP = exports.END = exports.PQueue = exports.commonLoggerCreate = exports.commonLoggerPrefix = exports.commonLoggerPipe = exports.commonLogLevelNumber = exports.commonLoggerNoop = exports.commonLoggerMinLevel = exports.JsonSchemaAnyBuilder = exports.jsonSchema = exports._stringifyAny = exports._TryCatch = exports._tryCatch = exports.pTimeoutFn = exports.pTimeout = exports.pRetry = exports.AggregatedError = exports.pDefer = exports.ErrorMode = exports._noop = exports._passNothingPredicate = exports._passthroughPredicate = exports._passUndefinedMapper = exports._passthroughMapper = exports.pMap = exports._objectKeys = exports._stringMapEntries = exports._stringMapValues = exports._createPromiseDecorator = exports.is = void 0;
|
|
3
|
+
exports.SKIP = exports.END = exports.PQueue = exports.commonLoggerCreate = exports.commonLoggerPrefix = exports.commonLoggerPipe = exports.commonLogLevelNumber = exports.commonLoggerNoop = exports.commonLoggerMinLevel = exports.JsonSchemaAnyBuilder = exports.jsonSchema = exports._stringifyAny = exports._TryCatch = exports._tryCatch = exports.pTimeoutFn = exports.pTimeout = exports.pRetryFn = exports.pRetry = exports.AggregatedError = exports.pDefer = exports.ErrorMode = exports._noop = exports._passNothingPredicate = exports._passthroughPredicate = exports._passUndefinedMapper = exports._passthroughMapper = exports.pMap = exports._objectKeys = exports._stringMapEntries = exports._stringMapValues = exports._createPromiseDecorator = exports.is = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
(0, tslib_1.__exportStar)(require("./array/array.util"), exports);
|
|
6
6
|
(0, tslib_1.__exportStar)(require("./lazy"), exports);
|
|
@@ -42,7 +42,6 @@ Object.defineProperty(exports, "JsonSchemaAnyBuilder", { enumerable: true, get:
|
|
|
42
42
|
(0, tslib_1.__exportStar)(require("./object/sortObjectDeep"), exports);
|
|
43
43
|
const AggregatedError_1 = require("./promise/AggregatedError");
|
|
44
44
|
Object.defineProperty(exports, "AggregatedError", { enumerable: true, get: function () { return AggregatedError_1.AggregatedError; } });
|
|
45
|
-
(0, tslib_1.__exportStar)(require("./promise/pBatch"), exports);
|
|
46
45
|
const pDefer_1 = require("./promise/pDefer");
|
|
47
46
|
Object.defineProperty(exports, "pDefer", { enumerable: true, get: function () { return pDefer_1.pDefer; } });
|
|
48
47
|
(0, tslib_1.__exportStar)(require("./promise/pDelay"), exports);
|
|
@@ -53,6 +52,7 @@ Object.defineProperty(exports, "pMap", { enumerable: true, get: function () { re
|
|
|
53
52
|
(0, tslib_1.__exportStar)(require("./promise/pProps"), exports);
|
|
54
53
|
const pRetry_1 = require("./promise/pRetry");
|
|
55
54
|
Object.defineProperty(exports, "pRetry", { enumerable: true, get: function () { return pRetry_1.pRetry; } });
|
|
55
|
+
Object.defineProperty(exports, "pRetryFn", { enumerable: true, get: function () { return pRetry_1.pRetryFn; } });
|
|
56
56
|
(0, tslib_1.__exportStar)(require("./promise/pState"), exports);
|
|
57
57
|
const pTimeout_1 = require("./promise/pTimeout");
|
|
58
58
|
Object.defineProperty(exports, "pTimeout", { enumerable: true, get: function () { return pTimeout_1.pTimeout; } });
|
|
@@ -113,8 +113,8 @@ export declare class JsonSchemaObjectBuilder<T extends AnyObject> extends JsonSc
|
|
|
113
113
|
minProps(minProperties: number): this;
|
|
114
114
|
maxProps(maxProperties: number): this;
|
|
115
115
|
additionalProps(additionalProperties: boolean): this;
|
|
116
|
-
baseDBEntity(): JsonSchemaObjectBuilder<T & BaseDBEntity
|
|
117
|
-
savedDBEntity(): JsonSchemaObjectBuilder<T & SavedDBEntity
|
|
116
|
+
baseDBEntity<ID = string>(idType?: string): JsonSchemaObjectBuilder<T & BaseDBEntity<ID>>;
|
|
117
|
+
savedDBEntity<ID = string>(idType?: string): JsonSchemaObjectBuilder<T & SavedDBEntity<ID>>;
|
|
118
118
|
extend<T2 extends AnyObject>(s2: JsonSchemaObjectBuilder<T2>): JsonSchemaObjectBuilder<T & T2>;
|
|
119
119
|
}
|
|
120
120
|
export declare class JsonSchemaArrayBuilder<ITEM> extends JsonSchemaAnyBuilder<ITEM[], JsonSchemaArray<ITEM>> {
|
|
@@ -306,16 +306,16 @@ class JsonSchemaObjectBuilder extends JsonSchemaAnyBuilder {
|
|
|
306
306
|
Object.assign(this.schema, { additionalProperties });
|
|
307
307
|
return this;
|
|
308
308
|
}
|
|
309
|
-
baseDBEntity() {
|
|
309
|
+
baseDBEntity(idType = 'string') {
|
|
310
310
|
Object.assign(this.schema.properties, {
|
|
311
|
-
id: { type:
|
|
311
|
+
id: { type: idType },
|
|
312
312
|
created: { type: 'number', format: 'unixTimestamp' },
|
|
313
313
|
updated: { type: 'number', format: 'unixTimestamp' },
|
|
314
314
|
});
|
|
315
315
|
return this;
|
|
316
316
|
}
|
|
317
|
-
savedDBEntity() {
|
|
318
|
-
return this.baseDBEntity().addRequired(['id', 'created', 'updated']);
|
|
317
|
+
savedDBEntity(idType = 'string') {
|
|
318
|
+
return this.baseDBEntity(idType).addRequired(['id', 'created', 'updated']);
|
|
319
319
|
}
|
|
320
320
|
extend(s2) {
|
|
321
321
|
const builder = new JsonSchemaObjectBuilder();
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { SavedDBEntity } from '../types';
|
|
2
|
-
export declare const baseDBEntityJsonSchema: import("./jsonSchemaBuilder").JsonSchemaObjectBuilder<Partial<SavedDBEntity
|
|
3
|
-
export declare const savedDBEntityJsonSchema: import("./jsonSchemaBuilder").JsonSchemaObjectBuilder<SavedDBEntity
|
|
2
|
+
export declare const baseDBEntityJsonSchema: import("./jsonSchemaBuilder").JsonSchemaObjectBuilder<Partial<SavedDBEntity<string>>>;
|
|
3
|
+
export declare const savedDBEntityJsonSchema: import("./jsonSchemaBuilder").JsonSchemaObjectBuilder<SavedDBEntity<string>>;
|
|
@@ -8,17 +8,12 @@ exports.AggregatedError = void 0;
|
|
|
8
8
|
*/
|
|
9
9
|
class AggregatedError extends Error {
|
|
10
10
|
constructor(errors, results = []) {
|
|
11
|
-
const mappedErrors = errors.map(e => {
|
|
12
|
-
if (typeof e === 'string')
|
|
13
|
-
return new Error(e);
|
|
14
|
-
return e;
|
|
15
|
-
});
|
|
16
11
|
const message = [
|
|
17
12
|
`${errors.length} errors:`,
|
|
18
|
-
...
|
|
13
|
+
...errors.map((e, i) => `${i + 1}. ${e.message}`),
|
|
19
14
|
].join('\n');
|
|
20
15
|
super(message);
|
|
21
|
-
this.errors =
|
|
16
|
+
this.errors = errors;
|
|
22
17
|
this.results = results;
|
|
23
18
|
Object.defineProperty(this, 'name', {
|
|
24
19
|
value: this.constructor.name,
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export declare function pFilter<T>(iterable: Iterable<T | PromiseLike<T>>, filterFn: AbortableAsyncPredicate<T>, opt?: PMapOptions): Promise<T[]>;
|
|
1
|
+
import { AsyncPredicate } from '../types';
|
|
2
|
+
export declare function pFilter<T>(iterable: Iterable<T>, filterFn: AsyncPredicate<T>): Promise<T[]>;
|
package/dist/promise/pFilter.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.pFilter = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
return
|
|
4
|
+
async function pFilter(iterable, filterFn) {
|
|
5
|
+
const items = [...iterable];
|
|
6
|
+
const predicates = await Promise.all(items.map((item, i) => filterFn(item, i)));
|
|
7
|
+
return items.filter((item, i) => predicates[i]);
|
|
8
8
|
}
|
|
9
9
|
exports.pFilter = pFilter;
|
package/dist/promise/pMap.d.ts
CHANGED
|
@@ -41,4 +41,4 @@ export interface PMapOptions {
|
|
|
41
41
|
* //=> ['http://ava.li/', 'http://todomvc.com/']
|
|
42
42
|
* })();
|
|
43
43
|
*/
|
|
44
|
-
export declare function pMap<IN, OUT>(iterable: Iterable<IN
|
|
44
|
+
export declare function pMap<IN, OUT>(iterable: Iterable<IN>, mapper: AbortableAsyncMapper<IN, OUT>, opt?: PMapOptions): Promise<OUT[]>;
|
package/dist/promise/pMap.js
CHANGED
|
@@ -38,28 +38,74 @@ const AggregatedError_1 = require("./AggregatedError");
|
|
|
38
38
|
* })();
|
|
39
39
|
*/
|
|
40
40
|
async function pMap(iterable, mapper, opt = {}) {
|
|
41
|
+
const ret = [];
|
|
42
|
+
// const iterator = iterable[Symbol.iterator]()
|
|
43
|
+
const items = [...iterable];
|
|
44
|
+
const itemsLength = items.length;
|
|
45
|
+
if (itemsLength === 0)
|
|
46
|
+
return []; // short circuit
|
|
47
|
+
const { concurrency = itemsLength, errorMode = __1.ErrorMode.THROW_IMMEDIATELY } = opt;
|
|
48
|
+
const errors = [];
|
|
49
|
+
let isSettled = false;
|
|
50
|
+
let resolvingCount = 0;
|
|
51
|
+
let currentIndex = 0;
|
|
52
|
+
// Special cases that are able to preserve async stack traces
|
|
53
|
+
if (concurrency === 1) {
|
|
54
|
+
// Special case for concurrency == 1
|
|
55
|
+
for await (const item of items) {
|
|
56
|
+
try {
|
|
57
|
+
const r = await mapper(item, currentIndex++);
|
|
58
|
+
if (r === __1.END)
|
|
59
|
+
break;
|
|
60
|
+
if (r !== __1.SKIP)
|
|
61
|
+
ret.push(r);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
if (errorMode === __1.ErrorMode.THROW_IMMEDIATELY)
|
|
65
|
+
throw err;
|
|
66
|
+
if (errorMode === __1.ErrorMode.THROW_AGGREGATED) {
|
|
67
|
+
errors.push(err);
|
|
68
|
+
}
|
|
69
|
+
// otherwise, suppress completely
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (errors.length) {
|
|
73
|
+
throw new AggregatedError_1.AggregatedError(errors, ret);
|
|
74
|
+
}
|
|
75
|
+
return ret;
|
|
76
|
+
}
|
|
77
|
+
else if (!opt.concurrency || items.length <= opt.concurrency) {
|
|
78
|
+
// Special case for concurrency == infinity or iterable.length < concurrency
|
|
79
|
+
if (errorMode === __1.ErrorMode.THROW_IMMEDIATELY) {
|
|
80
|
+
return (await Promise.all(items.map((item, i) => mapper(item, i)))).filter(r => r !== __1.SKIP && r !== __1.END);
|
|
81
|
+
}
|
|
82
|
+
;
|
|
83
|
+
(await Promise.allSettled(items.map((item, i) => mapper(item, i)))).forEach(r => {
|
|
84
|
+
if (r.status === 'fulfilled') {
|
|
85
|
+
if (r.value !== __1.SKIP && r.value !== __1.END)
|
|
86
|
+
ret.push(r.value);
|
|
87
|
+
}
|
|
88
|
+
else if (errorMode === __1.ErrorMode.THROW_AGGREGATED) {
|
|
89
|
+
errors.push(r.reason);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
if (errors.length) {
|
|
93
|
+
throw new AggregatedError_1.AggregatedError(errors, ret);
|
|
94
|
+
}
|
|
95
|
+
return ret;
|
|
96
|
+
}
|
|
41
97
|
return new Promise((resolve, reject) => {
|
|
42
|
-
const
|
|
43
|
-
const ret = [];
|
|
44
|
-
const iterator = iterable[Symbol.iterator]();
|
|
45
|
-
const errors = [];
|
|
46
|
-
let isSettled = false;
|
|
47
|
-
let isIterableDone = false;
|
|
48
|
-
let resolvingCount = 0;
|
|
49
|
-
let currentIndex = 0;
|
|
50
|
-
const next = (skipped = false) => {
|
|
98
|
+
const next = () => {
|
|
51
99
|
if (isSettled) {
|
|
52
100
|
return;
|
|
53
101
|
}
|
|
54
|
-
const nextItem =
|
|
55
|
-
const i = currentIndex
|
|
56
|
-
if (
|
|
57
|
-
currentIndex++;
|
|
58
|
-
if (nextItem.done) {
|
|
59
|
-
isIterableDone = true;
|
|
102
|
+
const nextItem = items[currentIndex];
|
|
103
|
+
const i = currentIndex++;
|
|
104
|
+
if (currentIndex > itemsLength) {
|
|
60
105
|
if (resolvingCount === 0) {
|
|
106
|
+
isSettled = true;
|
|
61
107
|
const r = ret.filter(r => r !== __1.SKIP);
|
|
62
|
-
if (errors.length
|
|
108
|
+
if (errors.length) {
|
|
63
109
|
reject(new AggregatedError_1.AggregatedError(errors, r));
|
|
64
110
|
}
|
|
65
111
|
else {
|
|
@@ -69,7 +115,7 @@ async function pMap(iterable, mapper, opt = {}) {
|
|
|
69
115
|
return;
|
|
70
116
|
}
|
|
71
117
|
resolvingCount++;
|
|
72
|
-
Promise.resolve(nextItem
|
|
118
|
+
Promise.resolve(nextItem)
|
|
73
119
|
.then(async (element) => await mapper(element, i))
|
|
74
120
|
.then(value => {
|
|
75
121
|
if (value === __1.END) {
|
|
@@ -85,7 +131,9 @@ async function pMap(iterable, mapper, opt = {}) {
|
|
|
85
131
|
reject(err);
|
|
86
132
|
}
|
|
87
133
|
else {
|
|
88
|
-
|
|
134
|
+
if (errorMode === __1.ErrorMode.THROW_AGGREGATED) {
|
|
135
|
+
errors.push(err);
|
|
136
|
+
}
|
|
89
137
|
resolvingCount--;
|
|
90
138
|
next();
|
|
91
139
|
}
|
|
@@ -93,7 +141,7 @@ async function pMap(iterable, mapper, opt = {}) {
|
|
|
93
141
|
};
|
|
94
142
|
for (let i = 0; i < concurrency; i++) {
|
|
95
143
|
next();
|
|
96
|
-
if (
|
|
144
|
+
if (isSettled) {
|
|
97
145
|
break;
|
|
98
146
|
}
|
|
99
147
|
}
|
package/dist/promise/pRetry.d.ts
CHANGED
|
@@ -5,6 +5,12 @@ export interface PRetryOptions {
|
|
|
5
5
|
* Can be used to identify the place in the code that failed.
|
|
6
6
|
*/
|
|
7
7
|
name?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Timeout for each Try, in milliseconds.
|
|
10
|
+
*
|
|
11
|
+
* Defaults to no timeout.
|
|
12
|
+
*/
|
|
13
|
+
timeout?: number;
|
|
8
14
|
/**
|
|
9
15
|
* How many attempts to try.
|
|
10
16
|
* First attempt is not a retry, but "initial try". It still counts.
|
|
@@ -29,7 +35,7 @@ export interface PRetryOptions {
|
|
|
29
35
|
*
|
|
30
36
|
* @default () => true
|
|
31
37
|
*/
|
|
32
|
-
predicate?: (err:
|
|
38
|
+
predicate?: (err: Error, attempt: number, maxAttempts: number) => boolean;
|
|
33
39
|
/**
|
|
34
40
|
* Log the first attempt (which is not a "retry" yet).
|
|
35
41
|
*
|
|
@@ -62,9 +68,18 @@ export interface PRetryOptions {
|
|
|
62
68
|
* Default to `console`
|
|
63
69
|
*/
|
|
64
70
|
logger?: CommonLogger;
|
|
71
|
+
/**
|
|
72
|
+
* Defaults to true.
|
|
73
|
+
* If true - preserves the stack trace in case of a Timeout (usually - very useful!).
|
|
74
|
+
* It has a certain perf cost.
|
|
75
|
+
*
|
|
76
|
+
* @experimental
|
|
77
|
+
*/
|
|
78
|
+
keepStackTrace?: boolean;
|
|
65
79
|
}
|
|
66
80
|
/**
|
|
67
81
|
* Returns a Function (!), enhanced with retry capabilities.
|
|
68
82
|
* Implements "Exponential back-off strategy" by multiplying the delay by `delayMultiplier` with each try.
|
|
69
83
|
*/
|
|
70
|
-
export declare function
|
|
84
|
+
export declare function pRetryFn<T extends AnyFunction>(fn: T, opt?: PRetryOptions): T;
|
|
85
|
+
export declare function pRetry<T>(fn: (attempt: number) => Promise<T>, opt?: PRetryOptions): Promise<T>;
|
package/dist/promise/pRetry.js
CHANGED
|
@@ -1,58 +1,90 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.pRetry = void 0;
|
|
3
|
+
exports.pRetry = exports.pRetryFn = void 0;
|
|
4
4
|
const __1 = require("..");
|
|
5
|
+
const pTimeout_1 = require("./pTimeout");
|
|
5
6
|
/**
|
|
6
7
|
* Returns a Function (!), enhanced with retry capabilities.
|
|
7
8
|
* Implements "Exponential back-off strategy" by multiplying the delay by `delayMultiplier` with each try.
|
|
8
9
|
*/
|
|
9
|
-
|
|
10
|
-
function
|
|
11
|
-
|
|
10
|
+
function pRetryFn(fn, opt = {}) {
|
|
11
|
+
return async function pRetryFunction(...args) {
|
|
12
|
+
return await pRetry(() => fn.call(this, ...args), opt);
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
exports.pRetryFn = pRetryFn;
|
|
16
|
+
async function pRetry(fn, opt = {}) {
|
|
17
|
+
const { maxAttempts = 4, delay: initialDelay = 1000, delayMultiplier = 2, predicate, logger = console, name, keepStackTrace = true, timeout, } = opt;
|
|
18
|
+
const fakeError = keepStackTrace ? new Error('RetryError') : undefined;
|
|
12
19
|
let { logFirstAttempt = false, logRetries = true, logFailures = false, logSuccess = false } = opt;
|
|
13
20
|
if (opt.logAll) {
|
|
14
|
-
logFirstAttempt = logRetries = logFailures = true;
|
|
21
|
+
logSuccess = logFirstAttempt = logRetries = logFailures = true;
|
|
15
22
|
}
|
|
16
23
|
if (opt.logNone) {
|
|
17
24
|
logSuccess = logFirstAttempt = logRetries = logFailures = false;
|
|
18
25
|
}
|
|
19
|
-
const fname =
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
26
|
+
const fname = name || fn.name || 'pRetry function';
|
|
27
|
+
let delay = initialDelay;
|
|
28
|
+
let attempt = 0;
|
|
29
|
+
let timer;
|
|
30
|
+
let timedOut = false;
|
|
31
|
+
return await new Promise((resolve, reject) => {
|
|
32
|
+
const rejectWithTimeout = () => {
|
|
33
|
+
timedOut = true; // to prevent more tries
|
|
34
|
+
const err = new pTimeout_1.TimeoutError(`"${fname}" timed out after ${timeout} ms`);
|
|
35
|
+
if (fakeError) {
|
|
36
|
+
// keep original stack
|
|
37
|
+
err.stack = fakeError.stack.replace('Error: RetryError', 'TimeoutError');
|
|
38
|
+
}
|
|
39
|
+
reject(err);
|
|
40
|
+
};
|
|
41
|
+
const next = async () => {
|
|
42
|
+
if (timedOut)
|
|
43
|
+
return;
|
|
44
|
+
if (timeout) {
|
|
45
|
+
timer = setTimeout(rejectWithTimeout, timeout);
|
|
46
|
+
}
|
|
47
|
+
const started = Date.now();
|
|
48
|
+
try {
|
|
49
|
+
attempt++;
|
|
50
|
+
if ((attempt === 1 && logFirstAttempt) || (attempt > 1 && logRetries)) {
|
|
51
|
+
logger.log(`${fname} attempt #${attempt}...`);
|
|
36
52
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
const r = await fn(attempt);
|
|
54
|
+
clearTimeout(timer);
|
|
55
|
+
if (logSuccess) {
|
|
56
|
+
logger.log(`${fname} attempt #${attempt} succeeded in ${(0, __1._since)(started)}`);
|
|
57
|
+
}
|
|
58
|
+
resolve(r);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
clearTimeout(timer);
|
|
62
|
+
if (logFailures) {
|
|
63
|
+
logger.warn(`${fname} attempt #${attempt} error in ${(0, __1._since)(started)}:`, (0, __1._stringifyAny)(err, {
|
|
64
|
+
includeErrorData: true,
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
if (attempt >= maxAttempts ||
|
|
68
|
+
(predicate && !predicate(err, attempt, maxAttempts))) {
|
|
69
|
+
// Give up
|
|
70
|
+
if (fakeError) {
|
|
71
|
+
// Preserve the original call stack
|
|
72
|
+
Object.defineProperty(err, 'stack', {
|
|
73
|
+
value: err.stack +
|
|
74
|
+
'\n --' +
|
|
75
|
+
fakeError.stack.replace('Error: RetryError', ''),
|
|
76
|
+
});
|
|
51
77
|
}
|
|
78
|
+
reject(err);
|
|
52
79
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
80
|
+
else {
|
|
81
|
+
// Retry after delay
|
|
82
|
+
delay *= delayMultiplier;
|
|
83
|
+
setTimeout(next, delay);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
void next();
|
|
88
|
+
});
|
|
57
89
|
}
|
|
58
90
|
exports.pRetry = pRetry;
|
package/dist/types.d.ts
CHANGED
|
@@ -24,13 +24,13 @@ export interface CreatedUpdated {
|
|
|
24
24
|
created: number;
|
|
25
25
|
updated: number;
|
|
26
26
|
}
|
|
27
|
-
export interface CreatedUpdatedId extends CreatedUpdated {
|
|
28
|
-
id:
|
|
27
|
+
export interface CreatedUpdatedId<ID = string> extends CreatedUpdated {
|
|
28
|
+
id: ID;
|
|
29
29
|
}
|
|
30
|
-
export interface ObjectWithId {
|
|
31
|
-
id:
|
|
30
|
+
export interface ObjectWithId<ID = string> {
|
|
31
|
+
id: ID;
|
|
32
32
|
}
|
|
33
|
-
export interface AnyObjectWithId extends AnyObject, ObjectWithId {
|
|
33
|
+
export interface AnyObjectWithId<ID = string> extends AnyObject, ObjectWithId<ID> {
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
36
|
* Convenience type shorthand.
|
|
@@ -127,8 +127,8 @@ export declare type UnixTimestamp = number;
|
|
|
127
127
|
/**
|
|
128
128
|
* Base interface for any Entity that was saved to DB.
|
|
129
129
|
*/
|
|
130
|
-
export interface SavedDBEntity {
|
|
131
|
-
id:
|
|
130
|
+
export interface SavedDBEntity<ID = string> {
|
|
131
|
+
id: ID;
|
|
132
132
|
/**
|
|
133
133
|
* unixTimestamp of when the entity was first created (in the DB).
|
|
134
134
|
*/
|
|
@@ -144,9 +144,9 @@ export interface SavedDBEntity {
|
|
|
144
144
|
* hence `id`, `created` and `updated` fields CAN BE undefined (yet).
|
|
145
145
|
* When it's known to be saved - `SavedDBEntity` interface can be used instead.
|
|
146
146
|
*/
|
|
147
|
-
export declare type BaseDBEntity = Partial<SavedDBEntity
|
|
148
|
-
export declare type Saved<E> = Merge<E, SavedDBEntity
|
|
149
|
-
export declare type Unsaved<E> = Merge<E, BaseDBEntity
|
|
147
|
+
export declare type BaseDBEntity<ID = string> = Partial<SavedDBEntity<ID>>;
|
|
148
|
+
export declare type Saved<E, ID = string> = Merge<E, SavedDBEntity<ID>>;
|
|
149
|
+
export declare type Unsaved<E, ID = string> = Merge<E, BaseDBEntity<ID>>;
|
|
150
150
|
/**
|
|
151
151
|
* Named type for JSON.parse / JSON.stringify second argument
|
|
152
152
|
*/
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { pRetryFn } from '..';
|
|
2
2
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
3
3
|
export function _Retry(opt = {}) {
|
|
4
4
|
return (target, key, descriptor) => {
|
|
5
5
|
const originalFn = descriptor.value;
|
|
6
|
-
descriptor.value =
|
|
6
|
+
descriptor.value = pRetryFn(originalFn, opt);
|
|
7
7
|
return descriptor;
|
|
8
8
|
};
|
|
9
9
|
}
|
package/dist-esm/index.js
CHANGED
|
@@ -31,14 +31,13 @@ export * from './object/object.util';
|
|
|
31
31
|
export * from './object/sortObject';
|
|
32
32
|
export * from './object/sortObjectDeep';
|
|
33
33
|
import { AggregatedError } from './promise/AggregatedError';
|
|
34
|
-
export * from './promise/pBatch';
|
|
35
34
|
import { pDefer } from './promise/pDefer';
|
|
36
35
|
export * from './promise/pDelay';
|
|
37
36
|
export * from './promise/pFilter';
|
|
38
37
|
export * from './promise/pHang';
|
|
39
38
|
import { pMap } from './promise/pMap';
|
|
40
39
|
export * from './promise/pProps';
|
|
41
|
-
import { pRetry } from './promise/pRetry';
|
|
40
|
+
import { pRetry, pRetryFn } from './promise/pRetry';
|
|
42
41
|
export * from './promise/pState';
|
|
43
42
|
import { pTimeout, pTimeoutFn } from './promise/pTimeout';
|
|
44
43
|
export * from './promise/pTuple';
|
|
@@ -55,4 +54,4 @@ export * from './string/safeJsonStringify';
|
|
|
55
54
|
import { PQueue } from './promise/pQueue';
|
|
56
55
|
export * from './seq/seq';
|
|
57
56
|
export * from './math/stack.util';
|
|
58
|
-
export { is, _createPromiseDecorator, _stringMapValues, _stringMapEntries, _objectKeys, pMap, _passthroughMapper, _passUndefinedMapper, _passthroughPredicate, _passNothingPredicate, _noop, ErrorMode, pDefer, AggregatedError, pRetry, pTimeout, pTimeoutFn, _tryCatch, _TryCatch, _stringifyAny, jsonSchema, JsonSchemaAnyBuilder, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, commonLoggerCreate, PQueue, END, SKIP, };
|
|
57
|
+
export { is, _createPromiseDecorator, _stringMapValues, _stringMapEntries, _objectKeys, pMap, _passthroughMapper, _passUndefinedMapper, _passthroughPredicate, _passNothingPredicate, _noop, ErrorMode, pDefer, AggregatedError, pRetry, pRetryFn, pTimeout, pTimeoutFn, _tryCatch, _TryCatch, _stringifyAny, jsonSchema, JsonSchemaAnyBuilder, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, commonLoggerCreate, PQueue, END, SKIP, };
|
|
@@ -301,16 +301,16 @@ export class JsonSchemaObjectBuilder extends JsonSchemaAnyBuilder {
|
|
|
301
301
|
Object.assign(this.schema, { additionalProperties });
|
|
302
302
|
return this;
|
|
303
303
|
}
|
|
304
|
-
baseDBEntity() {
|
|
304
|
+
baseDBEntity(idType = 'string') {
|
|
305
305
|
Object.assign(this.schema.properties, {
|
|
306
|
-
id: { type:
|
|
306
|
+
id: { type: idType },
|
|
307
307
|
created: { type: 'number', format: 'unixTimestamp' },
|
|
308
308
|
updated: { type: 'number', format: 'unixTimestamp' },
|
|
309
309
|
});
|
|
310
310
|
return this;
|
|
311
311
|
}
|
|
312
|
-
savedDBEntity() {
|
|
313
|
-
return this.baseDBEntity().addRequired(['id', 'created', 'updated']);
|
|
312
|
+
savedDBEntity(idType = 'string') {
|
|
313
|
+
return this.baseDBEntity(idType).addRequired(['id', 'created', 'updated']);
|
|
314
314
|
}
|
|
315
315
|
extend(s2) {
|
|
316
316
|
const builder = new JsonSchemaObjectBuilder();
|
|
@@ -5,17 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export class AggregatedError extends Error {
|
|
7
7
|
constructor(errors, results = []) {
|
|
8
|
-
const mappedErrors = errors.map(e => {
|
|
9
|
-
if (typeof e === 'string')
|
|
10
|
-
return new Error(e);
|
|
11
|
-
return e;
|
|
12
|
-
});
|
|
13
8
|
const message = [
|
|
14
9
|
`${errors.length} errors:`,
|
|
15
|
-
...
|
|
10
|
+
...errors.map((e, i) => `${i + 1}. ${e.message}`),
|
|
16
11
|
].join('\n');
|
|
17
12
|
super(message);
|
|
18
|
-
this.errors =
|
|
13
|
+
this.errors = errors;
|
|
19
14
|
this.results = results;
|
|
20
15
|
Object.defineProperty(this, 'name', {
|
|
21
16
|
value: this.constructor.name,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
return
|
|
1
|
+
export async function pFilter(iterable, filterFn) {
|
|
2
|
+
const items = [...iterable];
|
|
3
|
+
const predicates = await Promise.all(items.map((item, i) => filterFn(item, i)));
|
|
4
|
+
return items.filter((item, i) => predicates[i]);
|
|
5
5
|
}
|