@naturalcycles/js-lib 14.68.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 +3 -2
- package/dist/index.js +3 -1
- 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 +2 -1
- 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 +3 -0
- package/src/promise/pQueue.ts +117 -0
- package/src/promise/pTimeout.ts +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -56,5 +56,6 @@ import { _gb, _hb, _kb, _mb } from './unit/size.util';
|
|
|
56
56
|
import { is } from './vendor/is';
|
|
57
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.commonLoggerPrefix = exports.commonLoggerPipe = exports.commonLogLevelNumber = exports.commonLoggerNoop = exports.commonLoggerMinLevel = exports._lazyValue = exports._defineLazyProps = exports._defineLazyProperty = exports._parseQueryString = exports.generateJsonSchemaFromData = void 0;
|
|
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; } });
|
|
@@ -219,3 +219,5 @@ Object.defineProperty(exports, "commonLoggerPipe", { enumerable: true, get: func
|
|
|
219
219
|
Object.defineProperty(exports, "commonLoggerPrefix", { enumerable: true, get: function () { return commonLogger_1.commonLoggerPrefix; } });
|
|
220
220
|
const safeJsonStringify_1 = require("./string/safeJsonStringify");
|
|
221
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; } });
|
|
@@ -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
|
@@ -52,4 +52,5 @@ import { _gb, _hb, _kb, _mb } from './unit/size.util';
|
|
|
52
52
|
import { is } from './vendor/is';
|
|
53
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, };
|
|
@@ -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
|
@@ -235,8 +235,10 @@ import {
|
|
|
235
235
|
commonLoggerPrefix,
|
|
236
236
|
} from './log/commonLogger'
|
|
237
237
|
import { _safeJsonStringify } from './string/safeJsonStringify'
|
|
238
|
+
import { PQueue, PQueueCfg } from './promise/pQueue'
|
|
238
239
|
|
|
239
240
|
export type {
|
|
241
|
+
PQueueCfg,
|
|
240
242
|
MemoCache,
|
|
241
243
|
PromiseDecoratorCfg,
|
|
242
244
|
PromiseDecoratorResp,
|
|
@@ -473,4 +475,5 @@ export {
|
|
|
473
475
|
commonLoggerPipe,
|
|
474
476
|
commonLoggerPrefix,
|
|
475
477
|
_safeJsonStringify,
|
|
478
|
+
PQueue,
|
|
476
479
|
}
|
|
@@ -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
|
|