@naturalcycles/js-lib 14.65.0 → 14.69.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/index.d.ts +4 -3
- package/dist/index.js +8 -3
- package/dist/log/commonLogger.d.ts +11 -12
- package/dist/log/commonLogger.js +64 -18
- package/dist/promise/pQueue.d.ts +43 -0
- package/dist/promise/pQueue.js +79 -0
- package/dist/promise/pTimeout.d.ts +2 -1
- package/dist/promise/pTimeout.js +0 -1
- package/dist-esm/index.js +3 -2
- package/dist-esm/log/commonLogger.js +60 -16
- package/dist-esm/promise/pQueue.js +72 -0
- package/dist-esm/promise/pTimeout.js +0 -1
- package/package.json +1 -1
- package/src/index.ts +13 -6
- package/src/log/commonLogger.ts +67 -21
- package/src/promise/pQueue.ts +117 -0
- package/src/promise/pTimeout.ts +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -54,7 +54,8 @@ import { Class, ConditionalExcept, ConditionalPick, Merge, Promisable, PromiseVa
|
|
|
54
54
|
import { AsyncMapper, AsyncPredicate, BaseDBEntity, CreatedUpdated, CreatedUpdatedId, ObjectWithId, AnyObjectWithId, Saved, Unsaved, BatchResult, InstanceId, IsoDate, IsoDateTime, KeyValueTuple, Mapper, ObjectMapper, ObjectPredicate, Predicate, PromiseMap, AnyObject, AnyFunction, Reviver, SavedDBEntity, StringMap, UnixTimestamp, ValueOf, ValuesOf, _noop, _objectKeys, _passNothingPredicate, _passthroughMapper, _passthroughPredicate, _passUndefinedMapper, _stringMapEntries, _stringMapValues } from './types';
|
|
55
55
|
import { _gb, _hb, _kb, _mb } from './unit/size.util';
|
|
56
56
|
import { is } from './vendor/is';
|
|
57
|
-
import { CommonLogLevel, CommonLogFunction, CommonLogger,
|
|
57
|
+
import { CommonLogLevel, CommonLogFunction, CommonLogger, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix } from './log/commonLogger';
|
|
58
58
|
import { _safeJsonStringify } from './string/safeJsonStringify';
|
|
59
|
-
|
|
60
|
-
export {
|
|
59
|
+
import { PQueue, PQueueCfg } from './promise/pQueue';
|
|
60
|
+
export type { 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, PromiseValue, 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, CommonLogFunction, CommonLogger, };
|
|
61
|
+
export { is, _Memo, _memoFn, _LogMethod, _getArgsSignature, _createPromiseDecorator, AppError, HttpError, AssertionError, _isErrorObject, _isHttpErrorObject, _isHttpErrorResponse, _assert, _assertEquals, _assertDeepEquals, _assertIsError, _assertIsString, _assertIsNumber, _assertTypeOf, _randomInt, _randomArrayItem, _createDeterministicRandom, _inRange, _stringMapValues, _stringMapEntries, _objectKeys, _capitalize, _upperFirst, _lowerFirst, _split, _removeWhitespace, _substringBefore, _substringBeforeLast, _substringAfter, _substringAfterLast, _substringBetweenLast, _replaceAll, _nl2br, _truncate, _truncateMiddle, _pick, _omit, _filterFalsyValues, _filterUndefinedValues, _filterNullishValues, _filterEmptyArrays, _filterEmptyValues, _filterObject, _undefinedIfEmpty, _isObject, _isPrimitive, _mapKeys, _mapValues, _mapObject, _objectNullValuesToUndefined, _deepEquals, _deepCopy, _isEmptyObject, _isEmpty, _merge, _deepTrim, _sortObjectDeep, _sortObject, _get, _set, _has, _unset, _mask, _invert, _invertMap, _by, _groupBy, _sortBy, _sortNumbers, _toFixed, _toPrecision, _round, _findLast, _takeWhile, _takeRightWhile, _dropWhile, _dropRightWhile, _countBy, _intersection, _difference, _shuffle, _mapToObject, _findKeyByValue, _anyToError, _anyToErrorObject, _errorToErrorObject, _errorObjectToAppError, _range, _uniq, _uniqBy, _flatten, _flattenDeep, _chunk, SimpleMovingAverage, _average, _averageWeighted, _percentile, _median, _debounce, _throttle, _Debounce, _Throttle, pMap, _passthroughMapper, _passUndefinedMapper, _passthroughPredicate, _passNothingPredicate, _noop, pBatch, ErrorMode, pFilter, pProps, pDelay, pDefer, pHang, pState, AggregatedError, pRetry, pTimeout, pTuple, _Retry, _Timeout, _tryCatch, _TryCatch, _try, pTry, _jsonParseIfPossible, _stringifyAny, _ms, _since, _hb, _gb, _mb, _kb, _snakeCase, _camelCase, _kebabCase, _sum, _sumBy, _clamp, _last, mergeJsonSchemaObjects, jsonSchema, JsonSchemaAnyBuilder, JSON_SCHEMA_ORDER, generateJsonSchemaFromData, _parseQueryString, _defineLazyProperty, _defineLazyProps, _lazyValue, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, _safeJsonStringify, PQueue, };
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports._isObject = exports._undefinedIfEmpty = exports._filterObject = exports._filterEmptyValues = exports._filterEmptyArrays = exports._filterNullishValues = exports._filterUndefinedValues = exports._filterFalsyValues = exports._omit = exports._pick = exports._truncateMiddle = exports._truncate = exports._nl2br = exports._replaceAll = exports._substringBetweenLast = exports._substringAfterLast = exports._substringAfter = exports._substringBeforeLast = exports._substringBefore = exports._removeWhitespace = exports._split = exports._lowerFirst = exports._upperFirst = exports._capitalize = exports._objectKeys = exports._stringMapEntries = exports._stringMapValues = exports._inRange = exports._createDeterministicRandom = exports._randomArrayItem = exports._randomInt = exports._assertTypeOf = exports._assertIsNumber = exports._assertIsString = exports._assertIsError = exports._assertDeepEquals = exports._assertEquals = exports._assert = exports._isHttpErrorResponse = exports._isHttpErrorObject = exports._isErrorObject = exports.AssertionError = exports.HttpError = exports.AppError = exports._createPromiseDecorator = exports._getArgsSignature = exports._LogMethod = exports._memoFn = exports._Memo = exports.is = void 0;
|
|
4
4
|
exports._average = exports.SimpleMovingAverage = exports._chunk = exports._flattenDeep = exports._flatten = exports._uniqBy = exports._uniq = exports._range = exports._errorObjectToAppError = exports._errorToErrorObject = exports._anyToErrorObject = exports._anyToError = exports._findKeyByValue = exports._mapToObject = exports._shuffle = exports._difference = exports._intersection = exports._countBy = exports._dropRightWhile = exports._dropWhile = exports._takeRightWhile = exports._takeWhile = exports._findLast = exports._round = exports._toPrecision = exports._toFixed = exports._sortNumbers = exports._sortBy = exports._groupBy = exports._by = exports._invertMap = exports._invert = exports._mask = exports._unset = exports._has = exports._set = exports._get = exports._sortObject = exports._sortObjectDeep = exports._deepTrim = exports._merge = exports._isEmpty = exports._isEmptyObject = exports._deepCopy = exports._deepEquals = exports._objectNullValuesToUndefined = exports._mapObject = exports._mapValues = exports._mapKeys = exports._isPrimitive = void 0;
|
|
5
5
|
exports.JSON_SCHEMA_ORDER = exports.JsonSchemaAnyBuilder = exports.jsonSchema = exports.mergeJsonSchemaObjects = exports._last = exports._clamp = exports._sumBy = exports._sum = exports._kebabCase = exports._camelCase = exports._snakeCase = exports._kb = exports._mb = exports._gb = exports._hb = exports._since = exports._ms = exports._stringifyAny = exports._jsonParseIfPossible = exports.pTry = exports._try = exports._TryCatch = exports._tryCatch = exports._Timeout = exports._Retry = exports.pTuple = exports.pTimeout = exports.pRetry = exports.AggregatedError = exports.pState = exports.pHang = exports.pDefer = exports.pDelay = exports.pProps = exports.pFilter = exports.ErrorMode = exports.pBatch = exports._noop = exports._passNothingPredicate = exports._passthroughPredicate = exports._passUndefinedMapper = exports._passthroughMapper = exports.pMap = exports._Throttle = exports._Debounce = exports._throttle = exports._debounce = exports._median = exports._percentile = exports._averageWeighted = void 0;
|
|
6
|
-
exports._safeJsonStringify = exports.
|
|
6
|
+
exports.PQueue = exports._safeJsonStringify = exports.commonLoggerPrefix = exports.commonLoggerPipe = exports.commonLogLevelNumber = exports.commonLoggerNoop = exports.commonLoggerMinLevel = exports._lazyValue = exports._defineLazyProps = exports._defineLazyProperty = exports._parseQueryString = exports.generateJsonSchemaFromData = void 0;
|
|
7
7
|
const array_util_1 = require("./array/array.util");
|
|
8
8
|
Object.defineProperty(exports, "_by", { enumerable: true, get: function () { return array_util_1._by; } });
|
|
9
9
|
Object.defineProperty(exports, "_chunk", { enumerable: true, get: function () { return array_util_1._chunk; } });
|
|
@@ -212,7 +212,12 @@ Object.defineProperty(exports, "_mb", { enumerable: true, get: function () { ret
|
|
|
212
212
|
const is_1 = require("./vendor/is");
|
|
213
213
|
Object.defineProperty(exports, "is", { enumerable: true, get: function () { return is_1.is; } });
|
|
214
214
|
const commonLogger_1 = require("./log/commonLogger");
|
|
215
|
-
Object.defineProperty(exports, "
|
|
216
|
-
Object.defineProperty(exports, "
|
|
215
|
+
Object.defineProperty(exports, "commonLoggerMinLevel", { enumerable: true, get: function () { return commonLogger_1.commonLoggerMinLevel; } });
|
|
216
|
+
Object.defineProperty(exports, "commonLoggerNoop", { enumerable: true, get: function () { return commonLogger_1.commonLoggerNoop; } });
|
|
217
|
+
Object.defineProperty(exports, "commonLogLevelNumber", { enumerable: true, get: function () { return commonLogger_1.commonLogLevelNumber; } });
|
|
218
|
+
Object.defineProperty(exports, "commonLoggerPipe", { enumerable: true, get: function () { return commonLogger_1.commonLoggerPipe; } });
|
|
219
|
+
Object.defineProperty(exports, "commonLoggerPrefix", { enumerable: true, get: function () { return commonLogger_1.commonLoggerPrefix; } });
|
|
217
220
|
const safeJsonStringify_1 = require("./string/safeJsonStringify");
|
|
218
221
|
Object.defineProperty(exports, "_safeJsonStringify", { enumerable: true, get: function () { return safeJsonStringify_1._safeJsonStringify; } });
|
|
222
|
+
const pQueue_1 = require("./promise/pQueue");
|
|
223
|
+
Object.defineProperty(exports, "PQueue", { enumerable: true, get: function () { return pQueue_1.PQueue; } });
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* @experimental
|
|
10
10
|
*/
|
|
11
11
|
export declare type CommonLogLevel = 'log' | 'warn' | 'error';
|
|
12
|
+
export declare const commonLogLevelNumber: Record<CommonLogLevel, number>;
|
|
12
13
|
/**
|
|
13
14
|
* Function that takes any number of arguments and logs them all.
|
|
14
15
|
* It is expected that logged arguments are separated by "space", like console.log does.
|
|
@@ -28,22 +29,20 @@ export interface CommonLogger {
|
|
|
28
29
|
error: CommonLogFunction;
|
|
29
30
|
}
|
|
30
31
|
/**
|
|
31
|
-
*
|
|
32
|
-
* So you can do `logger('hey')` which is the same as `logger.log('hey')`
|
|
32
|
+
* SimpleLogger that does nothing (noop).
|
|
33
33
|
*
|
|
34
34
|
* @experimental
|
|
35
35
|
*/
|
|
36
|
-
export
|
|
37
|
-
}
|
|
36
|
+
export declare const commonLoggerNoop: CommonLogger;
|
|
38
37
|
/**
|
|
39
|
-
* Creates a
|
|
40
|
-
*
|
|
41
|
-
* @experimental
|
|
38
|
+
* Creates a "child" logger that is "limited" to the specified CommonLogLevel.
|
|
42
39
|
*/
|
|
43
|
-
export declare function
|
|
40
|
+
export declare function commonLoggerMinLevel(logger: CommonLogger, minLevel: CommonLogLevel, mutate?: boolean): CommonLogger;
|
|
44
41
|
/**
|
|
45
|
-
*
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
* Creates a "proxy" CommonLogger that pipes log messages to all provided sub-loggers.
|
|
43
|
+
*/
|
|
44
|
+
export declare function commonLoggerPipe(loggers: CommonLogger[]): CommonLogger;
|
|
45
|
+
/**
|
|
46
|
+
* Creates a "child" CommonLogger with prefix (one or multiple).
|
|
48
47
|
*/
|
|
49
|
-
export declare
|
|
48
|
+
export declare function commonLoggerPrefix(logger: CommonLogger, ...prefixes: any[]): CommonLogger;
|
package/dist/log/commonLogger.js
CHANGED
|
@@ -1,27 +1,73 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.commonLoggerPrefix = exports.commonLoggerPipe = exports.commonLoggerMinLevel = exports.commonLoggerNoop = exports.commonLogLevelNumber = void 0;
|
|
4
|
+
const index_1 = require("../index");
|
|
5
|
+
exports.commonLogLevelNumber = {
|
|
6
|
+
log: 10,
|
|
7
|
+
warn: 20,
|
|
8
|
+
error: 30,
|
|
9
|
+
};
|
|
4
10
|
/**
|
|
5
|
-
*
|
|
11
|
+
* SimpleLogger that does nothing (noop).
|
|
6
12
|
*
|
|
7
13
|
* @experimental
|
|
8
14
|
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
exports.commonLoggerNoop = {
|
|
16
|
+
log: index_1._noop,
|
|
17
|
+
warn: index_1._noop,
|
|
18
|
+
error: index_1._noop,
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Creates a "child" logger that is "limited" to the specified CommonLogLevel.
|
|
22
|
+
*/
|
|
23
|
+
function commonLoggerMinLevel(logger, minLevel, mutate = false) {
|
|
24
|
+
const level = exports.commonLogLevelNumber[minLevel];
|
|
25
|
+
if (mutate) {
|
|
26
|
+
if (level > exports.commonLogLevelNumber['log']) {
|
|
27
|
+
logger.log = index_1._noop;
|
|
28
|
+
if (level > exports.commonLogLevelNumber['warn']) {
|
|
29
|
+
logger.warn = index_1._noop;
|
|
30
|
+
if (level > exports.commonLogLevelNumber['error']) {
|
|
31
|
+
logger.error = index_1._noop;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return logger;
|
|
36
|
+
}
|
|
37
|
+
if (level <= exports.commonLogLevelNumber['log']) {
|
|
38
|
+
// All levels are kept
|
|
39
|
+
return logger;
|
|
40
|
+
}
|
|
41
|
+
if (level > exports.commonLogLevelNumber['error']) {
|
|
42
|
+
// "Log nothing" logger
|
|
43
|
+
return exports.commonLoggerNoop;
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
log: index_1._noop,
|
|
47
|
+
warn: level <= exports.commonLogLevelNumber['warn'] ? logger.warn.bind(logger) : index_1._noop,
|
|
48
|
+
error: logger.error.bind(logger), // otherwise it's "log nothing" logger (same as noopLogger)
|
|
49
|
+
};
|
|
15
50
|
}
|
|
16
|
-
exports.
|
|
17
|
-
const noop = () => { };
|
|
51
|
+
exports.commonLoggerMinLevel = commonLoggerMinLevel;
|
|
18
52
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* @experimental
|
|
53
|
+
* Creates a "proxy" CommonLogger that pipes log messages to all provided sub-loggers.
|
|
22
54
|
*/
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
55
|
+
function commonLoggerPipe(loggers) {
|
|
56
|
+
return {
|
|
57
|
+
log: (...args) => loggers.forEach(logger => logger.log(...args)),
|
|
58
|
+
warn: (...args) => loggers.forEach(logger => logger.warn(...args)),
|
|
59
|
+
error: (...args) => loggers.forEach(logger => logger.error(...args)),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
exports.commonLoggerPipe = commonLoggerPipe;
|
|
63
|
+
/**
|
|
64
|
+
* Creates a "child" CommonLogger with prefix (one or multiple).
|
|
65
|
+
*/
|
|
66
|
+
function commonLoggerPrefix(logger, ...prefixes) {
|
|
67
|
+
return {
|
|
68
|
+
log: (...args) => logger.log(...prefixes, ...args),
|
|
69
|
+
warn: (...args) => logger.warn(...prefixes, ...args),
|
|
70
|
+
error: (...args) => logger.error(...prefixes, ...args),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
exports.commonLoggerPrefix = commonLoggerPrefix;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { CommonLogger } from '../log/commonLogger';
|
|
2
|
+
export interface PQueueCfg {
|
|
3
|
+
concurrency: number;
|
|
4
|
+
/**
|
|
5
|
+
* Default: THROW_IMMEDIATELY
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* @default true
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Default to `console`
|
|
12
|
+
*/
|
|
13
|
+
logger?: CommonLogger;
|
|
14
|
+
/**
|
|
15
|
+
* If true - will LOG EVERYTHING:)
|
|
16
|
+
*/
|
|
17
|
+
debug?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare type PromiseReturningFunction = () => Promise<any>;
|
|
20
|
+
/**
|
|
21
|
+
* Inspired by: https://github.com/sindresorhus/p-queue
|
|
22
|
+
*
|
|
23
|
+
* Allows to push "jobs" to the queue and control its concurrency.
|
|
24
|
+
* Jobs are "promise-returning functions".
|
|
25
|
+
*
|
|
26
|
+
* API is @experimental
|
|
27
|
+
*/
|
|
28
|
+
export declare class PQueue {
|
|
29
|
+
constructor(cfg: PQueueCfg);
|
|
30
|
+
private readonly cfg;
|
|
31
|
+
private debug;
|
|
32
|
+
inFlight: number;
|
|
33
|
+
private queue;
|
|
34
|
+
private onIdleListeners;
|
|
35
|
+
get queueSize(): number;
|
|
36
|
+
/**
|
|
37
|
+
* Returns a Promise that resolves when the queue is Idle (next time, since the call).
|
|
38
|
+
* Resolves immediately in case the queue is Idle.
|
|
39
|
+
* Idle means 0 queue and 0 inFlight.
|
|
40
|
+
*/
|
|
41
|
+
onIdle(): Promise<void>;
|
|
42
|
+
push(fn: PromiseReturningFunction): void;
|
|
43
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PQueue = void 0;
|
|
4
|
+
const pDefer_1 = require("./pDefer");
|
|
5
|
+
/**
|
|
6
|
+
* Inspired by: https://github.com/sindresorhus/p-queue
|
|
7
|
+
*
|
|
8
|
+
* Allows to push "jobs" to the queue and control its concurrency.
|
|
9
|
+
* Jobs are "promise-returning functions".
|
|
10
|
+
*
|
|
11
|
+
* API is @experimental
|
|
12
|
+
*/
|
|
13
|
+
class PQueue {
|
|
14
|
+
constructor(cfg) {
|
|
15
|
+
this.inFlight = 0;
|
|
16
|
+
this.queue = [];
|
|
17
|
+
this.onIdleListeners = [];
|
|
18
|
+
this.cfg = {
|
|
19
|
+
// concurrency: Number.MAX_SAFE_INTEGER,
|
|
20
|
+
logger: console,
|
|
21
|
+
debug: false,
|
|
22
|
+
...cfg,
|
|
23
|
+
};
|
|
24
|
+
if (!cfg.debug) {
|
|
25
|
+
this.debug = () => { };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
debug(...args) {
|
|
29
|
+
this.cfg.logger.log(...args);
|
|
30
|
+
}
|
|
31
|
+
get queueSize() {
|
|
32
|
+
return this.queue.length;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Returns a Promise that resolves when the queue is Idle (next time, since the call).
|
|
36
|
+
* Resolves immediately in case the queue is Idle.
|
|
37
|
+
* Idle means 0 queue and 0 inFlight.
|
|
38
|
+
*/
|
|
39
|
+
onIdle() {
|
|
40
|
+
if (this.queue.length === 0)
|
|
41
|
+
return Promise.resolve();
|
|
42
|
+
const listener = (0, pDefer_1.pDefer)();
|
|
43
|
+
this.onIdleListeners.push(listener);
|
|
44
|
+
return listener;
|
|
45
|
+
}
|
|
46
|
+
push(fn) {
|
|
47
|
+
const { concurrency } = this.cfg;
|
|
48
|
+
if (this.inFlight < concurrency) {
|
|
49
|
+
// There is room for more jobs. Can start immediately
|
|
50
|
+
this.inFlight++;
|
|
51
|
+
this.debug(`inFlight++ ${this.inFlight}/${concurrency}, queue ${this.queue.length}`);
|
|
52
|
+
fn()
|
|
53
|
+
.catch(err => {
|
|
54
|
+
this.cfg.logger.error(err);
|
|
55
|
+
})
|
|
56
|
+
.finally(() => {
|
|
57
|
+
this.inFlight--;
|
|
58
|
+
this.debug(`inFlight-- ${this.inFlight}/${concurrency}, queue ${this.queue.length}`);
|
|
59
|
+
// check if there's room to start next job
|
|
60
|
+
if (this.queue.length && this.inFlight <= concurrency) {
|
|
61
|
+
const nextFn = this.queue.shift();
|
|
62
|
+
this.push(nextFn);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
if (this.inFlight === 0) {
|
|
66
|
+
this.debug('onIdle');
|
|
67
|
+
this.onIdleListeners.forEach(defer => defer.resolve());
|
|
68
|
+
this.onIdleListeners.length = 0; // empty the array
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
this.queue.push(fn);
|
|
75
|
+
this.debug(`inFlight ${this.inFlight}/${concurrency}, queue++ ${this.queue.length}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.PQueue = PQueue;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AnyFunction } from '../types';
|
|
1
2
|
export interface PTimeoutOptions {
|
|
2
3
|
/**
|
|
3
4
|
* Timeout in milliseconds.
|
|
@@ -19,4 +20,4 @@ export interface PTimeoutOptions {
|
|
|
19
20
|
* Throws an Error if the Function is not resolved in a certain time.
|
|
20
21
|
* If the Function rejects - passes this rejection further.
|
|
21
22
|
*/
|
|
22
|
-
export declare function pTimeout<T extends
|
|
23
|
+
export declare function pTimeout<T extends AnyFunction>(fn: T, opt: PTimeoutOptions): T;
|
package/dist/promise/pTimeout.js
CHANGED
|
@@ -6,7 +6,6 @@ exports.pTimeout = void 0;
|
|
|
6
6
|
* Throws an Error if the Function is not resolved in a certain time.
|
|
7
7
|
* If the Function rejects - passes this rejection further.
|
|
8
8
|
*/
|
|
9
|
-
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
10
9
|
function pTimeout(fn, opt) {
|
|
11
10
|
// const fname = fn.name || 'function'
|
|
12
11
|
const { timeout, name, onTimeout } = opt;
|
package/dist-esm/index.js
CHANGED
|
@@ -50,6 +50,7 @@ import { _ms, _since } from './time/time.util';
|
|
|
50
50
|
import { _noop, _objectKeys, _passNothingPredicate, _passthroughMapper, _passthroughPredicate, _passUndefinedMapper, _stringMapEntries, _stringMapValues, } from './types';
|
|
51
51
|
import { _gb, _hb, _kb, _mb } from './unit/size.util';
|
|
52
52
|
import { is } from './vendor/is';
|
|
53
|
-
import {
|
|
53
|
+
import { commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, } from './log/commonLogger';
|
|
54
54
|
import { _safeJsonStringify } from './string/safeJsonStringify';
|
|
55
|
-
|
|
55
|
+
import { PQueue } from './promise/pQueue';
|
|
56
|
+
export { is, _Memo, _memoFn, _LogMethod, _getArgsSignature, _createPromiseDecorator, AppError, HttpError, AssertionError, _isErrorObject, _isHttpErrorObject, _isHttpErrorResponse, _assert, _assertEquals, _assertDeepEquals, _assertIsError, _assertIsString, _assertIsNumber, _assertTypeOf, _randomInt, _randomArrayItem, _createDeterministicRandom, _inRange, _stringMapValues, _stringMapEntries, _objectKeys, _capitalize, _upperFirst, _lowerFirst, _split, _removeWhitespace, _substringBefore, _substringBeforeLast, _substringAfter, _substringAfterLast, _substringBetweenLast, _replaceAll, _nl2br, _truncate, _truncateMiddle, _pick, _omit, _filterFalsyValues, _filterUndefinedValues, _filterNullishValues, _filterEmptyArrays, _filterEmptyValues, _filterObject, _undefinedIfEmpty, _isObject, _isPrimitive, _mapKeys, _mapValues, _mapObject, _objectNullValuesToUndefined, _deepEquals, _deepCopy, _isEmptyObject, _isEmpty, _merge, _deepTrim, _sortObjectDeep, _sortObject, _get, _set, _has, _unset, _mask, _invert, _invertMap, _by, _groupBy, _sortBy, _sortNumbers, _toFixed, _toPrecision, _round, _findLast, _takeWhile, _takeRightWhile, _dropWhile, _dropRightWhile, _countBy, _intersection, _difference, _shuffle, _mapToObject, _findKeyByValue, _anyToError, _anyToErrorObject, _errorToErrorObject, _errorObjectToAppError, _range, _uniq, _uniqBy, _flatten, _flattenDeep, _chunk, SimpleMovingAverage, _average, _averageWeighted, _percentile, _median, _debounce, _throttle, _Debounce, _Throttle, pMap, _passthroughMapper, _passUndefinedMapper, _passthroughPredicate, _passNothingPredicate, _noop, pBatch, ErrorMode, pFilter, pProps, pDelay, pDefer, pHang, pState, AggregatedError, pRetry, pTimeout, pTuple, _Retry, _Timeout, _tryCatch, _TryCatch, _try, pTry, _jsonParseIfPossible, _stringifyAny, _ms, _since, _hb, _gb, _mb, _kb, _snakeCase, _camelCase, _kebabCase, _sum, _sumBy, _clamp, _last, mergeJsonSchemaObjects, jsonSchema, JsonSchemaAnyBuilder, JSON_SCHEMA_ORDER, generateJsonSchemaFromData, _parseQueryString, _defineLazyProperty, _defineLazyProps, _lazyValue, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, _safeJsonStringify, PQueue, };
|
|
@@ -1,23 +1,67 @@
|
|
|
1
|
+
import { _noop } from '../index';
|
|
2
|
+
export const commonLogLevelNumber = {
|
|
3
|
+
log: 10,
|
|
4
|
+
warn: 20,
|
|
5
|
+
error: 30,
|
|
6
|
+
};
|
|
1
7
|
/**
|
|
2
|
-
*
|
|
8
|
+
* SimpleLogger that does nothing (noop).
|
|
3
9
|
*
|
|
4
10
|
* @experimental
|
|
5
11
|
*/
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
export const commonLoggerNoop = {
|
|
13
|
+
log: _noop,
|
|
14
|
+
warn: _noop,
|
|
15
|
+
error: _noop,
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Creates a "child" logger that is "limited" to the specified CommonLogLevel.
|
|
19
|
+
*/
|
|
20
|
+
export function commonLoggerMinLevel(logger, minLevel, mutate = false) {
|
|
21
|
+
const level = commonLogLevelNumber[minLevel];
|
|
22
|
+
if (mutate) {
|
|
23
|
+
if (level > commonLogLevelNumber['log']) {
|
|
24
|
+
logger.log = _noop;
|
|
25
|
+
if (level > commonLogLevelNumber['warn']) {
|
|
26
|
+
logger.warn = _noop;
|
|
27
|
+
if (level > commonLogLevelNumber['error']) {
|
|
28
|
+
logger.error = _noop;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return logger;
|
|
33
|
+
}
|
|
34
|
+
if (level <= commonLogLevelNumber['log']) {
|
|
35
|
+
// All levels are kept
|
|
36
|
+
return logger;
|
|
37
|
+
}
|
|
38
|
+
if (level > commonLogLevelNumber['error']) {
|
|
39
|
+
// "Log nothing" logger
|
|
40
|
+
return commonLoggerNoop;
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
log: _noop,
|
|
44
|
+
warn: level <= commonLogLevelNumber['warn'] ? logger.warn.bind(logger) : _noop,
|
|
45
|
+
error: logger.error.bind(logger), // otherwise it's "log nothing" logger (same as noopLogger)
|
|
46
|
+
};
|
|
12
47
|
}
|
|
13
|
-
const noop = () => { };
|
|
14
48
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* @experimental
|
|
49
|
+
* Creates a "proxy" CommonLogger that pipes log messages to all provided sub-loggers.
|
|
18
50
|
*/
|
|
19
|
-
export
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
51
|
+
export function commonLoggerPipe(loggers) {
|
|
52
|
+
return {
|
|
53
|
+
log: (...args) => loggers.forEach(logger => logger.log(...args)),
|
|
54
|
+
warn: (...args) => loggers.forEach(logger => logger.warn(...args)),
|
|
55
|
+
error: (...args) => loggers.forEach(logger => logger.error(...args)),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Creates a "child" CommonLogger with prefix (one or multiple).
|
|
60
|
+
*/
|
|
61
|
+
export function commonLoggerPrefix(logger, ...prefixes) {
|
|
62
|
+
return {
|
|
63
|
+
log: (...args) => logger.log(...prefixes, ...args),
|
|
64
|
+
warn: (...args) => logger.warn(...prefixes, ...args),
|
|
65
|
+
error: (...args) => logger.error(...prefixes, ...args),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { pDefer } from './pDefer';
|
|
2
|
+
/**
|
|
3
|
+
* Inspired by: https://github.com/sindresorhus/p-queue
|
|
4
|
+
*
|
|
5
|
+
* Allows to push "jobs" to the queue and control its concurrency.
|
|
6
|
+
* Jobs are "promise-returning functions".
|
|
7
|
+
*
|
|
8
|
+
* API is @experimental
|
|
9
|
+
*/
|
|
10
|
+
export class PQueue {
|
|
11
|
+
constructor(cfg) {
|
|
12
|
+
this.inFlight = 0;
|
|
13
|
+
this.queue = [];
|
|
14
|
+
this.onIdleListeners = [];
|
|
15
|
+
this.cfg = Object.assign({
|
|
16
|
+
// concurrency: Number.MAX_SAFE_INTEGER,
|
|
17
|
+
logger: console, debug: false }, cfg);
|
|
18
|
+
if (!cfg.debug) {
|
|
19
|
+
this.debug = () => { };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
debug(...args) {
|
|
23
|
+
this.cfg.logger.log(...args);
|
|
24
|
+
}
|
|
25
|
+
get queueSize() {
|
|
26
|
+
return this.queue.length;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Returns a Promise that resolves when the queue is Idle (next time, since the call).
|
|
30
|
+
* Resolves immediately in case the queue is Idle.
|
|
31
|
+
* Idle means 0 queue and 0 inFlight.
|
|
32
|
+
*/
|
|
33
|
+
onIdle() {
|
|
34
|
+
if (this.queue.length === 0)
|
|
35
|
+
return Promise.resolve();
|
|
36
|
+
const listener = pDefer();
|
|
37
|
+
this.onIdleListeners.push(listener);
|
|
38
|
+
return listener;
|
|
39
|
+
}
|
|
40
|
+
push(fn) {
|
|
41
|
+
const { concurrency } = this.cfg;
|
|
42
|
+
if (this.inFlight < concurrency) {
|
|
43
|
+
// There is room for more jobs. Can start immediately
|
|
44
|
+
this.inFlight++;
|
|
45
|
+
this.debug(`inFlight++ ${this.inFlight}/${concurrency}, queue ${this.queue.length}`);
|
|
46
|
+
fn()
|
|
47
|
+
.catch(err => {
|
|
48
|
+
this.cfg.logger.error(err);
|
|
49
|
+
})
|
|
50
|
+
.finally(() => {
|
|
51
|
+
this.inFlight--;
|
|
52
|
+
this.debug(`inFlight-- ${this.inFlight}/${concurrency}, queue ${this.queue.length}`);
|
|
53
|
+
// check if there's room to start next job
|
|
54
|
+
if (this.queue.length && this.inFlight <= concurrency) {
|
|
55
|
+
const nextFn = this.queue.shift();
|
|
56
|
+
this.push(nextFn);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
if (this.inFlight === 0) {
|
|
60
|
+
this.debug('onIdle');
|
|
61
|
+
this.onIdleListeners.forEach(defer => defer.resolve());
|
|
62
|
+
this.onIdleListeners.length = 0; // empty the array
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
this.queue.push(fn);
|
|
69
|
+
this.debug(`inFlight ${this.inFlight}/${concurrency}, queue++ ${this.queue.length}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* Throws an Error if the Function is not resolved in a certain time.
|
|
4
4
|
* If the Function rejects - passes this rejection further.
|
|
5
5
|
*/
|
|
6
|
-
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
7
6
|
export function pTimeout(fn, opt) {
|
|
8
7
|
// const fname = fn.name || 'function'
|
|
9
8
|
const { timeout, name, onTimeout } = opt;
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -228,13 +228,17 @@ import {
|
|
|
228
228
|
CommonLogLevel,
|
|
229
229
|
CommonLogFunction,
|
|
230
230
|
CommonLogger,
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
231
|
+
commonLoggerMinLevel,
|
|
232
|
+
commonLoggerNoop,
|
|
233
|
+
commonLogLevelNumber,
|
|
234
|
+
commonLoggerPipe,
|
|
235
|
+
commonLoggerPrefix,
|
|
234
236
|
} from './log/commonLogger'
|
|
235
237
|
import { _safeJsonStringify } from './string/safeJsonStringify'
|
|
238
|
+
import { PQueue, PQueueCfg } from './promise/pQueue'
|
|
236
239
|
|
|
237
240
|
export type {
|
|
241
|
+
PQueueCfg,
|
|
238
242
|
MemoCache,
|
|
239
243
|
PromiseDecoratorCfg,
|
|
240
244
|
PromiseDecoratorResp,
|
|
@@ -307,7 +311,6 @@ export type {
|
|
|
307
311
|
CommonLogLevel,
|
|
308
312
|
CommonLogFunction,
|
|
309
313
|
CommonLogger,
|
|
310
|
-
SimpleLogger,
|
|
311
314
|
}
|
|
312
315
|
|
|
313
316
|
export {
|
|
@@ -466,7 +469,11 @@ export {
|
|
|
466
469
|
_defineLazyProperty,
|
|
467
470
|
_defineLazyProps,
|
|
468
471
|
_lazyValue,
|
|
469
|
-
|
|
470
|
-
|
|
472
|
+
commonLoggerMinLevel,
|
|
473
|
+
commonLoggerNoop,
|
|
474
|
+
commonLogLevelNumber,
|
|
475
|
+
commonLoggerPipe,
|
|
476
|
+
commonLoggerPrefix,
|
|
471
477
|
_safeJsonStringify,
|
|
478
|
+
PQueue,
|
|
472
479
|
}
|
package/src/log/commonLogger.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { _noop } from '../index'
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* These levels follow console.* naming,
|
|
3
5
|
* so you can use console[level] safely.
|
|
@@ -10,6 +12,12 @@
|
|
|
10
12
|
*/
|
|
11
13
|
export type CommonLogLevel = 'log' | 'warn' | 'error'
|
|
12
14
|
|
|
15
|
+
export const commonLogLevelNumber: Record<CommonLogLevel, number> = {
|
|
16
|
+
log: 10,
|
|
17
|
+
warn: 20,
|
|
18
|
+
error: 30,
|
|
19
|
+
}
|
|
20
|
+
|
|
13
21
|
/**
|
|
14
22
|
* Function that takes any number of arguments and logs them all.
|
|
15
23
|
* It is expected that logged arguments are separated by "space", like console.log does.
|
|
@@ -31,35 +39,73 @@ export interface CommonLogger {
|
|
|
31
39
|
}
|
|
32
40
|
|
|
33
41
|
/**
|
|
34
|
-
*
|
|
35
|
-
* So you can do `logger('hey')` which is the same as `logger.log('hey')`
|
|
42
|
+
* SimpleLogger that does nothing (noop).
|
|
36
43
|
*
|
|
37
44
|
* @experimental
|
|
38
45
|
*/
|
|
39
|
-
export
|
|
46
|
+
export const commonLoggerNoop: CommonLogger = {
|
|
47
|
+
log: _noop,
|
|
48
|
+
warn: _noop,
|
|
49
|
+
error: _noop,
|
|
50
|
+
}
|
|
40
51
|
|
|
41
52
|
/**
|
|
42
|
-
* Creates a
|
|
43
|
-
*
|
|
44
|
-
* @experimental
|
|
53
|
+
* Creates a "child" logger that is "limited" to the specified CommonLogLevel.
|
|
45
54
|
*/
|
|
46
|
-
export function
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
55
|
+
export function commonLoggerMinLevel(
|
|
56
|
+
logger: CommonLogger,
|
|
57
|
+
minLevel: CommonLogLevel,
|
|
58
|
+
mutate = false,
|
|
59
|
+
): CommonLogger {
|
|
60
|
+
const level = commonLogLevelNumber[minLevel]
|
|
61
|
+
if (mutate) {
|
|
62
|
+
if (level > commonLogLevelNumber['log']) {
|
|
63
|
+
logger.log = _noop
|
|
64
|
+
if (level > commonLogLevelNumber['warn']) {
|
|
65
|
+
logger.warn = _noop
|
|
66
|
+
if (level > commonLogLevelNumber['error']) {
|
|
67
|
+
logger.error = _noop
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return logger
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (level <= commonLogLevelNumber['log']) {
|
|
75
|
+
// All levels are kept
|
|
76
|
+
return logger
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (level > commonLogLevelNumber['error']) {
|
|
80
|
+
// "Log nothing" logger
|
|
81
|
+
return commonLoggerNoop
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
log: _noop, // otherwise it is "log everything" logger (same logger as input)
|
|
86
|
+
warn: level <= commonLogLevelNumber['warn'] ? logger.warn.bind(logger) : _noop,
|
|
87
|
+
error: logger.error.bind(logger), // otherwise it's "log nothing" logger (same as noopLogger)
|
|
88
|
+
}
|
|
52
89
|
}
|
|
53
90
|
|
|
54
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Creates a "proxy" CommonLogger that pipes log messages to all provided sub-loggers.
|
|
93
|
+
*/
|
|
94
|
+
export function commonLoggerPipe(loggers: CommonLogger[]): CommonLogger {
|
|
95
|
+
return {
|
|
96
|
+
log: (...args) => loggers.forEach(logger => logger.log(...args)),
|
|
97
|
+
warn: (...args) => loggers.forEach(logger => logger.warn(...args)),
|
|
98
|
+
error: (...args) => loggers.forEach(logger => logger.error(...args)),
|
|
99
|
+
}
|
|
100
|
+
}
|
|
55
101
|
|
|
56
102
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* @experimental
|
|
103
|
+
* Creates a "child" CommonLogger with prefix (one or multiple).
|
|
60
104
|
*/
|
|
61
|
-
export
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
105
|
+
export function commonLoggerPrefix(logger: CommonLogger, ...prefixes: any[]): CommonLogger {
|
|
106
|
+
return {
|
|
107
|
+
log: (...args) => logger.log(...prefixes, ...args),
|
|
108
|
+
warn: (...args) => logger.warn(...prefixes, ...args),
|
|
109
|
+
error: (...args) => logger.error(...prefixes, ...args),
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { CommonLogger } from '../log/commonLogger'
|
|
2
|
+
import { DeferredPromise, pDefer } from './pDefer'
|
|
3
|
+
|
|
4
|
+
export interface PQueueCfg {
|
|
5
|
+
concurrency: number
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Default: THROW_IMMEDIATELY
|
|
9
|
+
*/
|
|
10
|
+
// errorMode?: ErrorMode
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @default true
|
|
14
|
+
*/
|
|
15
|
+
// autoStart?: boolean
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Default to `console`
|
|
19
|
+
*/
|
|
20
|
+
logger?: CommonLogger
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* If true - will LOG EVERYTHING:)
|
|
24
|
+
*/
|
|
25
|
+
debug?: boolean
|
|
26
|
+
|
|
27
|
+
// logStatusChange?: boolean
|
|
28
|
+
// logSizeChange?: boolean
|
|
29
|
+
|
|
30
|
+
// timeout
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type PromiseReturningFunction = () => Promise<any>
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Inspired by: https://github.com/sindresorhus/p-queue
|
|
37
|
+
*
|
|
38
|
+
* Allows to push "jobs" to the queue and control its concurrency.
|
|
39
|
+
* Jobs are "promise-returning functions".
|
|
40
|
+
*
|
|
41
|
+
* API is @experimental
|
|
42
|
+
*/
|
|
43
|
+
export class PQueue {
|
|
44
|
+
constructor(cfg: PQueueCfg) {
|
|
45
|
+
this.cfg = {
|
|
46
|
+
// concurrency: Number.MAX_SAFE_INTEGER,
|
|
47
|
+
logger: console,
|
|
48
|
+
debug: false,
|
|
49
|
+
...cfg,
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!cfg.debug) {
|
|
53
|
+
this.debug = () => {}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private readonly cfg: Required<PQueueCfg>
|
|
58
|
+
|
|
59
|
+
private debug(...args: any[]): void {
|
|
60
|
+
this.cfg.logger.log(...args)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
inFlight = 0
|
|
64
|
+
private queue: PromiseReturningFunction[] = []
|
|
65
|
+
private onIdleListeners: DeferredPromise[] = []
|
|
66
|
+
|
|
67
|
+
get queueSize(): number {
|
|
68
|
+
return this.queue.length
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Returns a Promise that resolves when the queue is Idle (next time, since the call).
|
|
73
|
+
* Resolves immediately in case the queue is Idle.
|
|
74
|
+
* Idle means 0 queue and 0 inFlight.
|
|
75
|
+
*/
|
|
76
|
+
onIdle(): Promise<void> {
|
|
77
|
+
if (this.queue.length === 0) return Promise.resolve()
|
|
78
|
+
|
|
79
|
+
const listener = pDefer()
|
|
80
|
+
this.onIdleListeners.push(listener)
|
|
81
|
+
return listener
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
push(fn: PromiseReturningFunction): void {
|
|
85
|
+
const { concurrency } = this.cfg
|
|
86
|
+
|
|
87
|
+
if (this.inFlight < concurrency) {
|
|
88
|
+
// There is room for more jobs. Can start immediately
|
|
89
|
+
this.inFlight++
|
|
90
|
+
this.debug(`inFlight++ ${this.inFlight}/${concurrency}, queue ${this.queue.length}`)
|
|
91
|
+
|
|
92
|
+
fn()
|
|
93
|
+
.catch(err => {
|
|
94
|
+
this.cfg.logger.error(err)
|
|
95
|
+
})
|
|
96
|
+
.finally(() => {
|
|
97
|
+
this.inFlight--
|
|
98
|
+
this.debug(`inFlight-- ${this.inFlight}/${concurrency}, queue ${this.queue.length}`)
|
|
99
|
+
|
|
100
|
+
// check if there's room to start next job
|
|
101
|
+
if (this.queue.length && this.inFlight <= concurrency) {
|
|
102
|
+
const nextFn = this.queue.shift()!
|
|
103
|
+
this.push(nextFn)
|
|
104
|
+
} else {
|
|
105
|
+
if (this.inFlight === 0) {
|
|
106
|
+
this.debug('onIdle')
|
|
107
|
+
this.onIdleListeners.forEach(defer => defer.resolve())
|
|
108
|
+
this.onIdleListeners.length = 0 // empty the array
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
} else {
|
|
113
|
+
this.queue.push(fn)
|
|
114
|
+
this.debug(`inFlight ${this.inFlight}/${concurrency}, queue++ ${this.queue.length}`)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
package/src/promise/pTimeout.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { AnyFunction } from '../types'
|
|
2
|
+
|
|
1
3
|
export interface PTimeoutOptions {
|
|
2
4
|
/**
|
|
3
5
|
* Timeout in milliseconds.
|
|
@@ -22,8 +24,7 @@ export interface PTimeoutOptions {
|
|
|
22
24
|
* Throws an Error if the Function is not resolved in a certain time.
|
|
23
25
|
* If the Function rejects - passes this rejection further.
|
|
24
26
|
*/
|
|
25
|
-
|
|
26
|
-
export function pTimeout<T extends Function>(fn: T, opt: PTimeoutOptions): T {
|
|
27
|
+
export function pTimeout<T extends AnyFunction>(fn: T, opt: PTimeoutOptions): T {
|
|
27
28
|
// const fname = fn.name || 'function'
|
|
28
29
|
const { timeout, name, onTimeout } = opt
|
|
29
30
|
|