@naturalcycles/js-lib 14.69.0 → 14.69.1

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.
@@ -1,9 +1,15 @@
1
+ import { ErrorMode } from '../error/errorMode';
1
2
  import { CommonLogger } from '../log/commonLogger';
2
3
  export interface PQueueCfg {
3
4
  concurrency: number;
4
5
  /**
5
6
  * Default: THROW_IMMEDIATELY
7
+ *
8
+ * THROW_AGGREGATED is not supported.
9
+ *
10
+ * SUPPRESS_ERRORS will still log errors via logger. It will resolve the `.push` promise with void.
6
11
  */
12
+ errorMode?: ErrorMode;
7
13
  /**
8
14
  * @default true
9
15
  */
@@ -16,7 +22,7 @@ export interface PQueueCfg {
16
22
  */
17
23
  debug?: boolean;
18
24
  }
19
- export declare type PromiseReturningFunction = () => Promise<any>;
25
+ export declare type PromiseReturningFunction<R> = () => Promise<R>;
20
26
  /**
21
27
  * Inspired by: https://github.com/sindresorhus/p-queue
22
28
  *
@@ -39,5 +45,9 @@ export declare class PQueue {
39
45
  * Idle means 0 queue and 0 inFlight.
40
46
  */
41
47
  onIdle(): Promise<void>;
42
- push(fn: PromiseReturningFunction): void;
48
+ /**
49
+ * Push PromiseReturningFunction to the Queue.
50
+ * Returns a Promise that resolves (or rejects) with the return value from the Promise.
51
+ */
52
+ push<R>(fn_: PromiseReturningFunction<R>): Promise<R>;
43
53
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PQueue = void 0;
4
+ const errorMode_1 = require("../error/errorMode");
4
5
  const pDefer_1 = require("./pDefer");
5
6
  /**
6
7
  * Inspired by: https://github.com/sindresorhus/p-queue
@@ -17,6 +18,7 @@ class PQueue {
17
18
  this.onIdleListeners = [];
18
19
  this.cfg = {
19
20
  // concurrency: Number.MAX_SAFE_INTEGER,
21
+ errorMode: errorMode_1.ErrorMode.THROW_IMMEDIATELY,
20
22
  logger: console,
21
23
  debug: false,
22
24
  ...cfg,
@@ -43,15 +45,29 @@ class PQueue {
43
45
  this.onIdleListeners.push(listener);
44
46
  return listener;
45
47
  }
46
- push(fn) {
48
+ /**
49
+ * Push PromiseReturningFunction to the Queue.
50
+ * Returns a Promise that resolves (or rejects) with the return value from the Promise.
51
+ */
52
+ push(fn_) {
47
53
  const { concurrency } = this.cfg;
54
+ const fn = fn_;
55
+ fn.defer || (fn.defer = (0, pDefer_1.pDefer)());
48
56
  if (this.inFlight < concurrency) {
49
57
  // There is room for more jobs. Can start immediately
50
58
  this.inFlight++;
51
59
  this.debug(`inFlight++ ${this.inFlight}/${concurrency}, queue ${this.queue.length}`);
52
60
  fn()
61
+ .then(result => fn.defer.resolve(result))
53
62
  .catch(err => {
54
63
  this.cfg.logger.error(err);
64
+ if (this.cfg.errorMode === errorMode_1.ErrorMode.SUPPRESS) {
65
+ fn.defer.resolve(); // resolve with `void`
66
+ }
67
+ else {
68
+ // Should be handled on the outside, otherwise it'll cause UnhandledRejection
69
+ fn.defer.reject(err);
70
+ }
55
71
  })
56
72
  .finally(() => {
57
73
  this.inFlight--;
@@ -59,7 +75,7 @@ class PQueue {
59
75
  // check if there's room to start next job
60
76
  if (this.queue.length && this.inFlight <= concurrency) {
61
77
  const nextFn = this.queue.shift();
62
- this.push(nextFn);
78
+ void this.push(nextFn);
63
79
  }
64
80
  else {
65
81
  if (this.inFlight === 0) {
@@ -74,6 +90,7 @@ class PQueue {
74
90
  this.queue.push(fn);
75
91
  this.debug(`inFlight ${this.inFlight}/${concurrency}, queue++ ${this.queue.length}`);
76
92
  }
93
+ return fn.defer;
77
94
  }
78
95
  }
79
96
  exports.PQueue = PQueue;
@@ -1,3 +1,4 @@
1
+ import { ErrorMode } from '../error/errorMode';
1
2
  import { pDefer } from './pDefer';
2
3
  /**
3
4
  * Inspired by: https://github.com/sindresorhus/p-queue
@@ -14,7 +15,7 @@ export class PQueue {
14
15
  this.onIdleListeners = [];
15
16
  this.cfg = Object.assign({
16
17
  // concurrency: Number.MAX_SAFE_INTEGER,
17
- logger: console, debug: false }, cfg);
18
+ errorMode: ErrorMode.THROW_IMMEDIATELY, logger: console, debug: false }, cfg);
18
19
  if (!cfg.debug) {
19
20
  this.debug = () => { };
20
21
  }
@@ -37,15 +38,29 @@ export class PQueue {
37
38
  this.onIdleListeners.push(listener);
38
39
  return listener;
39
40
  }
40
- push(fn) {
41
+ /**
42
+ * Push PromiseReturningFunction to the Queue.
43
+ * Returns a Promise that resolves (or rejects) with the return value from the Promise.
44
+ */
45
+ push(fn_) {
41
46
  const { concurrency } = this.cfg;
47
+ const fn = fn_;
48
+ fn.defer || (fn.defer = pDefer());
42
49
  if (this.inFlight < concurrency) {
43
50
  // There is room for more jobs. Can start immediately
44
51
  this.inFlight++;
45
52
  this.debug(`inFlight++ ${this.inFlight}/${concurrency}, queue ${this.queue.length}`);
46
53
  fn()
54
+ .then(result => fn.defer.resolve(result))
47
55
  .catch(err => {
48
56
  this.cfg.logger.error(err);
57
+ if (this.cfg.errorMode === ErrorMode.SUPPRESS) {
58
+ fn.defer.resolve(); // resolve with `void`
59
+ }
60
+ else {
61
+ // Should be handled on the outside, otherwise it'll cause UnhandledRejection
62
+ fn.defer.reject(err);
63
+ }
49
64
  })
50
65
  .finally(() => {
51
66
  this.inFlight--;
@@ -53,7 +68,7 @@ export class PQueue {
53
68
  // check if there's room to start next job
54
69
  if (this.queue.length && this.inFlight <= concurrency) {
55
70
  const nextFn = this.queue.shift();
56
- this.push(nextFn);
71
+ void this.push(nextFn);
57
72
  }
58
73
  else {
59
74
  if (this.inFlight === 0) {
@@ -68,5 +83,6 @@ export class PQueue {
68
83
  this.queue.push(fn);
69
84
  this.debug(`inFlight ${this.inFlight}/${concurrency}, queue++ ${this.queue.length}`);
70
85
  }
86
+ return fn.defer;
71
87
  }
72
88
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
- "version": "14.69.0",
3
+ "version": "14.69.1",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "build-prod": "build-prod-esm-cjs",
@@ -1,3 +1,4 @@
1
+ import { ErrorMode } from '../error/errorMode'
1
2
  import { CommonLogger } from '../log/commonLogger'
2
3
  import { DeferredPromise, pDefer } from './pDefer'
3
4
 
@@ -6,8 +7,12 @@ export interface PQueueCfg {
6
7
 
7
8
  /**
8
9
  * Default: THROW_IMMEDIATELY
10
+ *
11
+ * THROW_AGGREGATED is not supported.
12
+ *
13
+ * SUPPRESS_ERRORS will still log errors via logger. It will resolve the `.push` promise with void.
9
14
  */
10
- // errorMode?: ErrorMode
15
+ errorMode?: ErrorMode
11
16
 
12
17
  /**
13
18
  * @default true
@@ -30,7 +35,11 @@ export interface PQueueCfg {
30
35
  // timeout
31
36
  }
32
37
 
33
- export type PromiseReturningFunction = () => Promise<any>
38
+ export type PromiseReturningFunction<R> = () => Promise<R>
39
+
40
+ interface PromiseReturningFunctionWithDefer<R> extends PromiseReturningFunction<R> {
41
+ defer: DeferredPromise<R>
42
+ }
34
43
 
35
44
  /**
36
45
  * Inspired by: https://github.com/sindresorhus/p-queue
@@ -44,6 +53,7 @@ export class PQueue {
44
53
  constructor(cfg: PQueueCfg) {
45
54
  this.cfg = {
46
55
  // concurrency: Number.MAX_SAFE_INTEGER,
56
+ errorMode: ErrorMode.THROW_IMMEDIATELY,
47
57
  logger: console,
48
58
  debug: false,
49
59
  ...cfg,
@@ -61,7 +71,7 @@ export class PQueue {
61
71
  }
62
72
 
63
73
  inFlight = 0
64
- private queue: PromiseReturningFunction[] = []
74
+ private queue: PromiseReturningFunction<any>[] = []
65
75
  private onIdleListeners: DeferredPromise[] = []
66
76
 
67
77
  get queueSize(): number {
@@ -81,17 +91,31 @@ export class PQueue {
81
91
  return listener
82
92
  }
83
93
 
84
- push(fn: PromiseReturningFunction): void {
94
+ /**
95
+ * Push PromiseReturningFunction to the Queue.
96
+ * Returns a Promise that resolves (or rejects) with the return value from the Promise.
97
+ */
98
+ push<R>(fn_: PromiseReturningFunction<R>): Promise<R> {
85
99
  const { concurrency } = this.cfg
86
100
 
101
+ const fn = fn_ as PromiseReturningFunctionWithDefer<R>
102
+ fn.defer ||= pDefer<R>()
103
+
87
104
  if (this.inFlight < concurrency) {
88
105
  // There is room for more jobs. Can start immediately
89
106
  this.inFlight++
90
107
  this.debug(`inFlight++ ${this.inFlight}/${concurrency}, queue ${this.queue.length}`)
91
108
 
92
109
  fn()
110
+ .then(result => fn.defer.resolve(result))
93
111
  .catch(err => {
94
112
  this.cfg.logger.error(err)
113
+ if (this.cfg.errorMode === ErrorMode.SUPPRESS) {
114
+ fn.defer.resolve() // resolve with `void`
115
+ } else {
116
+ // Should be handled on the outside, otherwise it'll cause UnhandledRejection
117
+ fn.defer.reject(err)
118
+ }
95
119
  })
96
120
  .finally(() => {
97
121
  this.inFlight--
@@ -100,7 +124,7 @@ export class PQueue {
100
124
  // check if there's room to start next job
101
125
  if (this.queue.length && this.inFlight <= concurrency) {
102
126
  const nextFn = this.queue.shift()!
103
- this.push(nextFn)
127
+ void this.push(nextFn)
104
128
  } else {
105
129
  if (this.inFlight === 0) {
106
130
  this.debug('onIdle')
@@ -113,5 +137,7 @@ export class PQueue {
113
137
  this.queue.push(fn)
114
138
  this.debug(`inFlight ${this.inFlight}/${concurrency}, queue++ ${this.queue.length}`)
115
139
  }
140
+
141
+ return fn.defer
116
142
  }
117
143
  }