@crawlee/core 4.0.0-beta.98 → 4.0.0-rc.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.
Files changed (109) hide show
  1. package/autoscaling/autoscaled_pool.d.ts +3 -21
  2. package/autoscaling/autoscaled_pool.js +105 -97
  3. package/autoscaling/concurrency_system.d.ts +7 -22
  4. package/autoscaling/concurrency_system.js +112 -100
  5. package/autoscaling/cpu_load_signal.d.ts +1 -2
  6. package/autoscaling/cpu_load_signal.js +11 -10
  7. package/autoscaling/event_loop_load_signal.d.ts +1 -4
  8. package/autoscaling/event_loop_load_signal.js +18 -18
  9. package/autoscaling/index.d.ts +1 -1
  10. package/autoscaling/index.js +1 -1
  11. package/autoscaling/load_signal.d.ts +8 -7
  12. package/autoscaling/load_signal.js +14 -12
  13. package/autoscaling/memory_load_signal.d.ts +3 -12
  14. package/autoscaling/memory_load_signal.js +41 -41
  15. package/autoscaling/snapshotter.d.ts +7 -10
  16. package/autoscaling/snapshotter.js +18 -18
  17. package/autoscaling/{client_load_signal.d.ts → storage_backend_load_signal.d.ts} +14 -17
  18. package/autoscaling/{client_load_signal.js → storage_backend_load_signal.js} +27 -27
  19. package/autoscaling/system_status.d.ts +9 -11
  20. package/autoscaling/system_status.js +13 -13
  21. package/configuration.d.ts +16 -16
  22. package/configuration.js +6 -6
  23. package/crawlers/context_pipeline.js +6 -6
  24. package/crawlers/crawler_commons.d.ts +14 -116
  25. package/crawlers/crawler_commons.js +1 -107
  26. package/crawlers/error_snapshotter.d.ts +2 -4
  27. package/crawlers/error_snapshotter.js +5 -5
  28. package/crawlers/index.d.ts +1 -1
  29. package/crawlers/index.js +0 -1
  30. package/crawlers/statistics.d.ts +164 -45
  31. package/crawlers/statistics.js +339 -153
  32. package/debug.js +4 -4
  33. package/enqueue_links/enqueue_links.d.ts +51 -159
  34. package/enqueue_links/enqueue_links.js +38 -231
  35. package/enqueue_links/shared.d.ts +34 -24
  36. package/enqueue_links/shared.js +54 -36
  37. package/errors.d.ts +43 -12
  38. package/errors.js +48 -9
  39. package/events/event_manager.d.ts +2 -2
  40. package/events/event_manager.js +7 -6
  41. package/events/local_event_manager.d.ts +1 -1
  42. package/events/local_event_manager.js +5 -5
  43. package/http.d.ts +9 -0
  44. package/http.js +28 -0
  45. package/index.d.ts +1 -1
  46. package/index.js +1 -1
  47. package/log.js +5 -1
  48. package/memory-storage/memory-storage.d.ts +3 -11
  49. package/memory-storage/memory-storage.js +42 -48
  50. package/memory-storage/resource-clients/dataset.d.ts +1 -1
  51. package/memory-storage/resource-clients/dataset.js +8 -13
  52. package/memory-storage/resource-clients/key-value-store.d.ts +1 -1
  53. package/memory-storage/resource-clients/key-value-store.js +36 -38
  54. package/memory-storage/resource-clients/request-queue.d.ts +4 -23
  55. package/memory-storage/resource-clients/request-queue.js +68 -80
  56. package/owned_or_injected.d.ts +1 -3
  57. package/owned_or_injected.js +17 -17
  58. package/package.json +8 -9
  59. package/proxy_configuration.d.ts +1 -3
  60. package/proxy_configuration.js +18 -14
  61. package/recoverable_state.d.ts +80 -45
  62. package/recoverable_state.js +163 -75
  63. package/request.d.ts +3 -4
  64. package/request.js +57 -44
  65. package/router.d.ts +6 -10
  66. package/router.js +23 -23
  67. package/serialization.js +14 -13
  68. package/service_locator.d.ts +19 -10
  69. package/service_locator.js +57 -48
  70. package/session_pool/session.d.ts +3 -14
  71. package/session_pool/session.js +76 -74
  72. package/session_pool/session_pool.d.ts +6 -12
  73. package/session_pool/session_pool.js +85 -77
  74. package/storages/batched_adds.d.ts +37 -0
  75. package/storages/batched_adds.js +73 -0
  76. package/storages/dataset.d.ts +12 -1
  77. package/storages/dataset.js +133 -32
  78. package/storages/index.d.ts +2 -1
  79. package/storages/index.js +2 -1
  80. package/storages/key_value_store.d.ts +19 -4
  81. package/storages/key_value_store.js +204 -75
  82. package/storages/request_dedup_cache.d.ts +1 -2
  83. package/storages/request_dedup_cache.js +9 -9
  84. package/storages/request_list.d.ts +4 -23
  85. package/storages/request_list.js +103 -96
  86. package/storages/request_loader.d.ts +5 -0
  87. package/storages/request_manager_tandem.d.ts +1 -10
  88. package/storages/request_manager_tandem.js +27 -27
  89. package/storages/request_queue.d.ts +21 -21
  90. package/storages/request_queue.js +318 -177
  91. package/storages/sitemap_request_loader.d.ts +22 -70
  92. package/storages/sitemap_request_loader.js +122 -116
  93. package/storages/storage_instance_manager.d.ts +1 -4
  94. package/storages/storage_instance_manager.js +17 -19
  95. package/storages/storage_stats.d.ts +1 -1
  96. package/storages/storage_stats.js +4 -4
  97. package/storages/throttling_request_manager.d.ts +239 -0
  98. package/storages/throttling_request_manager.js +646 -0
  99. package/storages/transaction.d.ts +252 -0
  100. package/storages/transaction.js +251 -0
  101. package/storages/utils.d.ts +6 -3
  102. package/storages/utils.js +11 -2
  103. package/system-info/runtime.js +7 -7
  104. package/url.d.ts +9 -0
  105. package/url.js +11 -0
  106. package/validators.d.ts +22 -25
  107. package/validators.js +13 -25
  108. package/storages/access_checking.d.ts +0 -12
  109. package/storages/access_checking.js +0 -17
@@ -107,25 +107,7 @@ export interface AutoscaledPoolOptions extends TaskLoopPredicates {
107
107
  * @internal
108
108
  */
109
109
  export declare class AutoscaledPool {
110
- private readonly log;
111
- private readonly maybeRunIntervalMillis;
112
- private readonly taskTimeoutMillis;
113
- private readonly runTaskFunction;
114
- private readonly isFinishedFunction;
115
- private readonly isTaskReadyFunction;
116
- private readonly concurrencySystem;
117
- private readonly consumer;
118
- private isStopped;
119
- private resolve;
120
- private reject;
121
- private maybeRunInterval;
122
- private queryingIsTaskReady;
123
- private queryingIsFinished;
124
- /**
125
- * This pool's *own* in-flight task count, as opposed to {@link AutoscaledPool.currentConcurrency}, which is the
126
- * (possibly shared) governor's total. `pause()` and `maybeFinish()` care only about this pool draining.
127
- */
128
- private ownConcurrency;
110
+ #private;
129
111
  constructor(options: AutoscaledPoolOptions);
130
112
  /**
131
113
  * The governor backing this pool, as supplied to the constructor — exposed as the read-only
@@ -194,13 +176,13 @@ export declare class AutoscaledPool {
194
176
  * Starts a new task
195
177
  * if the number of running tasks (current concurrency) is lower than desired concurrency
196
178
  * and the system is not currently overloaded
197
- * and this.isTaskReadyFunction() returns true.
179
+ * and `isTaskReadyFunction()` returns true.
198
180
  *
199
181
  * It doesn't allow multiple concurrent runs of this method.
200
182
  */
201
183
  private maybeRunTask;
202
184
  /**
203
- * If there are no running tasks and this.isFinishedFunction() returns true then closes
185
+ * If there are no running tasks and `isFinishedFunction()` returns true then closes
204
186
  * the pool and resolves the pool's promise returned by the run() method.
205
187
  *
206
188
  * It doesn't allow multiple concurrent runs of this method.
@@ -1,8 +1,26 @@
1
- import ow from 'ow';
1
+ import { z } from 'zod';
2
2
  import { addTimeoutToPromise } from '@apify/timeout';
3
3
  import { betterClearInterval, betterSetInterval } from '@apify/utilities';
4
4
  import { CriticalError } from '../errors.js';
5
5
  import { serviceLocator } from '../service_locator.js';
6
+ import { parseArgument, schemas, validators } from '../validators.js';
7
+ // `schemas.anyObject` and `objectWithKeys`-based validators pass values through by reference
8
+ // (object schemas return a pruned plain copy), so class instances like loggers and the
9
+ // concurrency system keep their prototype.
10
+ const autoscaledPoolOptionsSchema = z.strictObject({
11
+ runTaskFunction: schemas.anyFunction,
12
+ isFinishedFunction: schemas.anyFunction,
13
+ isTaskReadyFunction: schemas.anyFunction,
14
+ maybeRunIntervalSecs: schemas.anyNumber
15
+ .refine((value) => value > 0, 'Expected a number greater than 0')
16
+ .default(0.5),
17
+ taskTimeoutSecs: schemas.anyNumber
18
+ .refine((value) => value >= 0, 'Expected a number greater than or equal to 0')
19
+ .default(0),
20
+ log: validators.logger.default(() => serviceLocator.getLogger()),
21
+ concurrencySystem: schemas.anyObject,
22
+ consumer: schemas.anyObject.refine((value) => typeof value.id === 'string' && value.id.length > 0, "Expected an object with a non-empty string 'id'"),
23
+ });
6
24
  /**
7
25
  * Manages a pool of asynchronous resource-intensive tasks that are executed in parallel.
8
26
  * The pool only starts new tasks while its {@link IConcurrencySystem|concurrency system} reports free capacity —
@@ -56,52 +74,42 @@ import { serviceLocator } from '../service_locator.js';
56
74
  * @internal
57
75
  */
58
76
  export class AutoscaledPool {
59
- log;
77
+ #log;
60
78
  // Configurable properties.
61
- maybeRunIntervalMillis;
62
- taskTimeoutMillis;
63
- runTaskFunction;
64
- isFinishedFunction;
65
- isTaskReadyFunction;
66
- concurrencySystem;
67
- consumer;
79
+ #maybeRunIntervalMillis;
80
+ #taskTimeoutMillis;
81
+ #runTaskFunction;
82
+ #isFinishedFunction;
83
+ #isTaskReadyFunction;
84
+ #concurrencySystem;
85
+ #consumer;
68
86
  // Internal properties.
69
- isStopped = false;
70
- resolve = null;
71
- reject = null;
72
- maybeRunInterval;
73
- queryingIsTaskReady;
74
- queryingIsFinished;
87
+ #isStopped = false;
88
+ #resolve = null;
89
+ #reject = null;
90
+ #maybeRunInterval;
91
+ #queryingIsTaskReady;
92
+ #queryingIsFinished;
75
93
  /**
76
94
  * This pool's *own* in-flight task count, as opposed to {@link AutoscaledPool.currentConcurrency}, which is the
77
95
  * (possibly shared) governor's total. `pause()` and `maybeFinish()` care only about this pool draining.
78
96
  */
79
- ownConcurrency = 0;
97
+ #ownConcurrency = 0;
80
98
  constructor(options) {
81
- ow(options, ow.object.exactShape({
82
- runTaskFunction: ow.function,
83
- isFinishedFunction: ow.function,
84
- isTaskReadyFunction: ow.function,
85
- maybeRunIntervalSecs: ow.optional.number.greaterThan(0),
86
- taskTimeoutSecs: ow.optional.number.greaterThanOrEqual(0),
87
- log: ow.optional.object,
88
- concurrencySystem: ow.object,
89
- consumer: ow.object.partialShape({ id: ow.string.nonEmpty }),
90
- }));
91
- const { runTaskFunction, isFinishedFunction, isTaskReadyFunction, maybeRunIntervalSecs = 0.5, taskTimeoutSecs = 0, log = serviceLocator.getLogger(), concurrencySystem, consumer, } = options;
92
- this.log = log.child({ prefix: 'AutoscaledPool' });
99
+ const { runTaskFunction, isFinishedFunction, isTaskReadyFunction, maybeRunIntervalSecs, taskTimeoutSecs, log, concurrencySystem, consumer, } = parseArgument(options, autoscaledPoolOptionsSchema, 'AutoscaledPoolOptions');
100
+ this.#log = log.child({ prefix: 'AutoscaledPool' });
93
101
  // Configurable properties.
94
- this.maybeRunIntervalMillis = maybeRunIntervalSecs * 1000;
95
- this.taskTimeoutMillis = taskTimeoutSecs * 1000;
96
- this.runTaskFunction = runTaskFunction;
97
- this.isFinishedFunction = isFinishedFunction;
98
- this.isTaskReadyFunction = isTaskReadyFunction;
99
- this.concurrencySystem = concurrencySystem;
100
- this.consumer = consumer;
102
+ this.#maybeRunIntervalMillis = maybeRunIntervalSecs * 1000;
103
+ this.#taskTimeoutMillis = taskTimeoutSecs * 1000;
104
+ this.#runTaskFunction = runTaskFunction;
105
+ this.#isFinishedFunction = isFinishedFunction;
106
+ this.#isTaskReadyFunction = isTaskReadyFunction;
107
+ this.#concurrencySystem = concurrencySystem;
108
+ this.#consumer = consumer;
101
109
  // Internal properties.
102
- this.isStopped = false;
103
- this.resolve = null;
104
- this.reject = null;
110
+ this.#isStopped = false;
111
+ this.#resolve = null;
112
+ this.#reject = null;
105
113
  this.maybeRunTask = this.maybeRunTask.bind(this);
106
114
  }
107
115
  /**
@@ -112,18 +120,18 @@ export class AutoscaledPool {
112
120
  * {@link ConcurrencySystem} its owner holds, never through the pool.
113
121
  */
114
122
  get system() {
115
- return this.concurrencySystem;
123
+ return this.#concurrencySystem;
116
124
  }
117
125
  /** The estimated number of parallel tasks the governor can currently support. */
118
126
  get desiredConcurrency() {
119
- return this.concurrencySystem.desiredConcurrency;
127
+ return this.#concurrencySystem.desiredConcurrency;
120
128
  }
121
129
  /**
122
130
  * The number of parallel tasks currently booked against the governor. When it is shared, this counts every
123
131
  * borrowing pool's tasks, not just this one's.
124
132
  */
125
133
  get currentConcurrency() {
126
- return this.concurrencySystem.currentConcurrency;
134
+ return this.#concurrencySystem.currentConcurrency;
127
135
  }
128
136
  /**
129
137
  * Runs the auto-scaled pool. Returns a promise that gets resolved or rejected once
@@ -135,26 +143,26 @@ export class AutoscaledPool {
135
143
  async run() {
136
144
  // Checked here, on an awaited path — the capacity queries inside the task loop run from intervals and
137
145
  // `setImmediate`, where a throw would become an unhandled rejection and hang `run()` forever.
138
- if (!this.concurrencySystem.isRunning) {
146
+ if (!this.#concurrencySystem.isRunning) {
139
147
  throw new CriticalError('The ConcurrencySystem this AutoscaledPool borrows has not been started, so system load would not be ' +
140
148
  'monitored and the concurrency would never be adjusted. Whoever creates a ConcurrencySystem owns ' +
141
149
  'its lifecycle: call `await concurrencySystem.start()` before running the pools or crawlers that ' +
142
150
  'use it, and `await concurrencySystem.stop()` once they are all done.');
143
151
  }
144
152
  const poolPromise = new Promise((resolve, reject) => {
145
- this.resolve = resolve;
146
- this.reject = reject;
153
+ this.#resolve = resolve;
154
+ this.#reject = reject;
147
155
  });
148
156
  // This is here because if we scale down to let's say 1, then after each promise is finished
149
157
  // this.maybeRunTask() doesn't trigger another one. So if that 1 instance gets stuck it results
150
158
  // in the crawler getting stuck and even after scaling up it never triggers another promise.
151
- this.maybeRunInterval = betterSetInterval(this.maybeRunTask, this.maybeRunIntervalMillis);
159
+ this.#maybeRunInterval = betterSetInterval(this.maybeRunTask, this.#maybeRunIntervalMillis);
152
160
  try {
153
161
  await poolPromise;
154
162
  }
155
163
  finally {
156
164
  // If resolve is null, the pool is already destroyed.
157
- if (this.resolve)
165
+ if (this.#resolve)
158
166
  await this.destroy();
159
167
  }
160
168
  }
@@ -170,9 +178,9 @@ export class AutoscaledPool {
170
178
  * parts of their asynchronous chains of commands will not execute.
171
179
  */
172
180
  async abort() {
173
- this.isStopped = true;
174
- if (this.resolve) {
175
- this.resolve();
181
+ this.#isStopped = true;
182
+ if (this.#resolve) {
183
+ this.#resolve();
176
184
  await this.destroy();
177
185
  }
178
186
  }
@@ -192,9 +200,9 @@ export class AutoscaledPool {
192
200
  * it during a long pause, its owner can `stop()` and `start()` it again.
193
201
  */
194
202
  async pause(timeoutSecs) {
195
- if (this.isStopped)
203
+ if (this.#isStopped)
196
204
  return;
197
- this.isStopped = true;
205
+ this.#isStopped = true;
198
206
  await new Promise((resolve, reject) => {
199
207
  let timeout;
200
208
  let interval;
@@ -208,14 +216,14 @@ export class AutoscaledPool {
208
216
  }, timeoutSecs);
209
217
  }
210
218
  interval = setInterval(() => {
211
- if (this.ownConcurrency <= 0) {
219
+ if (this.#ownConcurrency <= 0) {
212
220
  // Clean up timeout and interval to prevent process hanging.
213
221
  if (timeout)
214
222
  clearTimeout(timeout);
215
223
  clearInterval(interval);
216
224
  resolve();
217
225
  }
218
- }, this.maybeRunIntervalMillis);
226
+ }, this.#maybeRunIntervalMillis);
219
227
  });
220
228
  }
221
229
  /**
@@ -225,7 +233,7 @@ export class AutoscaledPool {
225
233
  * Tasks will automatically start running again in `options.maybeRunIntervalSecs`.
226
234
  */
227
235
  resume() {
228
- this.isStopped = false;
236
+ this.#isStopped = false;
229
237
  }
230
238
  /**
231
239
  * Explicitly check the queue for new tasks. The AutoscaledPool checks the queue for new tasks periodically,
@@ -238,27 +246,27 @@ export class AutoscaledPool {
238
246
  * Starts a new task
239
247
  * if the number of running tasks (current concurrency) is lower than desired concurrency
240
248
  * and the system is not currently overloaded
241
- * and this.isTaskReadyFunction() returns true.
249
+ * and `isTaskReadyFunction()` returns true.
242
250
  *
243
251
  * It doesn't allow multiple concurrent runs of this method.
244
252
  */
245
253
  async maybeRunTask(intervalCallback) {
246
- this.log.perf('Attempting to run a task.');
254
+ this.#log.perf('Attempting to run a task.');
247
255
  // Check if the function was invoked by the maybeRunInterval and use an empty function if not.
248
256
  const done = intervalCallback || (() => { });
249
257
  // Prevent starting a new task if:
250
258
  // - the pool is paused or aborted
251
- if (this.isStopped) {
252
- this.log.perf('Task will not run. AutoscaledPool is stopped.');
259
+ if (this.#isStopped) {
260
+ this.#log.perf('Task will not run. AutoscaledPool is stopped.');
253
261
  return done();
254
262
  }
255
263
  // - we are already querying for a task.
256
- if (this.queryingIsTaskReady) {
257
- this.log.perf('Task will not run. Waiting for a ready task.');
264
+ if (this.#queryingIsTaskReady) {
265
+ this.#log.perf('Task will not run. Waiting for a ready task.');
258
266
  return done();
259
267
  }
260
268
  // - the budget has room for us.
261
- if (!this.concurrencySystem.hasCapacityForTask(this.consumer)) {
269
+ if (!this.#concurrencySystem.hasCapacityForTask(this.#consumer)) {
262
270
  done();
263
271
  // A shared governor's budget can stay saturated by another pool indefinitely, so we still have to be able
264
272
  // to notice that *this* pool has run out of work — `maybeFinish()` is the only thing that ever resolves
@@ -267,37 +275,37 @@ export class AutoscaledPool {
267
275
  return this.maybeFinish();
268
276
  }
269
277
  // - a task is ready.
270
- this.queryingIsTaskReady = true;
278
+ this.#queryingIsTaskReady = true;
271
279
  let isTaskReady;
272
280
  try {
273
- this.log.perf('Checking for ready tasks.');
274
- isTaskReady = await this.isTaskReadyFunction();
281
+ this.#log.perf('Checking for ready tasks.');
282
+ isTaskReady = await this.#isTaskReadyFunction();
275
283
  }
276
284
  catch (e) {
277
285
  const err = e;
278
- this.log.perf('Checking for ready tasks failed.');
286
+ this.#log.perf('Checking for ready tasks failed.');
279
287
  // We might have already rejected this promise.
280
- if (this.reject) {
288
+ if (this.#reject) {
281
289
  // No need to log all concurrent errors.
282
- this.log.exception(err, 'isTaskReadyFunction failed');
283
- this.reject(err);
290
+ this.#log.exception(err, 'isTaskReadyFunction failed');
291
+ this.#reject(err);
284
292
  }
285
293
  }
286
294
  finally {
287
- this.queryingIsTaskReady = false;
295
+ this.#queryingIsTaskReady = false;
288
296
  }
289
297
  if (!isTaskReady) {
290
- this.log.perf('Task will not run. No tasks are ready.');
298
+ this.#log.perf('Task will not run. No tasks are ready.');
291
299
  done();
292
300
  // No tasks could mean that we're finished with all tasks.
293
301
  return this.maybeFinish();
294
302
  }
295
303
  // - the budget still has room. Re-checked atomically, because another pool sharing the governor may have taken
296
304
  // the last free slot while we awaited `isTaskReadyFunction` above.
297
- if (!this.concurrencySystem.tryRegisterTaskStart(this.consumer)) {
305
+ if (!this.#concurrencySystem.tryRegisterTaskStart(this.#consumer)) {
298
306
  return done();
299
307
  }
300
- this.ownConcurrency++;
308
+ this.#ownConcurrency++;
301
309
  try {
302
310
  // Everything's fine. Run task.
303
311
  // Try to run next task to build up concurrency,
@@ -306,73 +314,73 @@ export class AutoscaledPool {
306
314
  // We need to restart interval here, so that it doesn't get blocked by a stalled task.
307
315
  done();
308
316
  // Execute the current task.
309
- this.log.perf('Running a task.');
310
- if (this.taskTimeoutMillis > 0) {
311
- await addTimeoutToPromise(async () => this.runTaskFunction(), this.taskTimeoutMillis, `runTaskFunction timed out after ${this.taskTimeoutMillis / 1000} seconds.`);
317
+ this.#log.perf('Running a task.');
318
+ if (this.#taskTimeoutMillis > 0) {
319
+ await addTimeoutToPromise(async () => this.#runTaskFunction(), this.#taskTimeoutMillis, `runTaskFunction timed out after ${this.#taskTimeoutMillis / 1000} seconds.`);
312
320
  }
313
321
  else {
314
- await this.runTaskFunction();
322
+ await this.#runTaskFunction();
315
323
  }
316
- this.log.perf('Task finished.');
324
+ this.#log.perf('Task finished.');
317
325
  // Run task after the previous one finished. Only on success: a failed task rejects the pool, and
318
326
  // nudging the loop afterwards could start work on an already destroyed pool.
319
327
  setImmediate(this.maybeRunTask);
320
328
  }
321
329
  catch (e) {
322
330
  const err = e;
323
- this.log.perf('Running a task failed.');
331
+ this.#log.perf('Running a task failed.');
324
332
  // We might have already rejected this promise.
325
- if (this.reject) {
333
+ if (this.#reject) {
326
334
  // No need to log all concurrent errors.
327
335
  if (
328
336
  // avoid reprinting the same critical error multiple times, as it will be printed by Nodejs at the end anyway
329
337
  !(e instanceof CriticalError)) {
330
- this.log.exception(err, 'runTaskFunction failed.');
338
+ this.#log.exception(err, 'runTaskFunction failed.');
331
339
  }
332
- this.reject(err);
340
+ this.#reject(err);
333
341
  }
334
342
  }
335
343
  finally {
336
- this.concurrencySystem.registerTaskEnd(this.consumer);
337
- this.ownConcurrency--;
344
+ this.#concurrencySystem.registerTaskEnd(this.#consumer);
345
+ this.#ownConcurrency--;
338
346
  }
339
347
  return undefined;
340
348
  }
341
349
  /**
342
- * If there are no running tasks and this.isFinishedFunction() returns true then closes
350
+ * If there are no running tasks and `isFinishedFunction()` returns true then closes
343
351
  * the pool and resolves the pool's promise returned by the run() method.
344
352
  *
345
353
  * It doesn't allow multiple concurrent runs of this method.
346
354
  */
347
355
  async maybeFinish() {
348
- if (this.queryingIsFinished)
356
+ if (this.#queryingIsFinished)
349
357
  return;
350
- if (this.ownConcurrency > 0)
358
+ if (this.#ownConcurrency > 0)
351
359
  return;
352
- this.queryingIsFinished = true;
360
+ this.#queryingIsFinished = true;
353
361
  try {
354
- const isFinished = await this.isFinishedFunction();
355
- if (isFinished && this.resolve)
356
- this.resolve();
362
+ const isFinished = await this.#isFinishedFunction();
363
+ if (isFinished && this.#resolve)
364
+ this.#resolve();
357
365
  }
358
366
  catch (e) {
359
367
  const err = e;
360
- if (this.reject) {
368
+ if (this.#reject) {
361
369
  // No need to log all concurrent errors.
362
- this.log.exception(err, 'isFinishedFunction failed.');
363
- this.reject(err);
370
+ this.#log.exception(err, 'isFinishedFunction failed.');
371
+ this.#reject(err);
364
372
  }
365
373
  }
366
374
  finally {
367
- this.queryingIsFinished = false;
375
+ this.#queryingIsFinished = false;
368
376
  }
369
377
  }
370
378
  /**
371
379
  * Cleans up resources.
372
380
  */
373
381
  async destroy() {
374
- this.resolve = null;
375
- this.reject = null;
376
- betterClearInterval(this.maybeRunInterval);
382
+ this.#resolve = null;
383
+ this.#reject = null;
384
+ betterClearInterval(this.#maybeRunInterval);
377
385
  }
378
386
  }
@@ -53,8 +53,8 @@ export interface ConcurrencySystemOptions {
53
53
  autoscaleIntervalSecs?: number;
54
54
  /**
55
55
  * The signals that tell the system whether the machine is overloaded: per-resource tuning for the built-in four
56
- * (memory, event loop, CPU, client) plus any {@link LoadSignalsOptions.custom|`custom`} implementations of
57
- * your own. See {@link LoadSignalsOptions}.
56
+ * (memory, event loop, CPU, storage backend) plus any {@link LoadSignalsOptions.custom|`custom`}
57
+ * implementations of your own. See {@link LoadSignalsOptions}.
58
58
  */
59
59
  loadSignals?: LoadSignalsOptions;
60
60
  /**
@@ -152,30 +152,15 @@ export interface IConcurrencySystem {
152
152
  * @category Scaling
153
153
  */
154
154
  export declare class ConcurrencySystem implements IConcurrencySystem {
155
+ #private;
155
156
  private readonly log;
156
157
  private readonly desiredConcurrencyRatio;
157
158
  private readonly scaleUpStepRatio;
158
159
  private readonly scaleDownStepRatio;
159
- private readonly loggingIntervalMillis;
160
- private readonly autoscaleIntervalMillis;
161
160
  private readonly maxTasksPerMinute;
162
- private _minConcurrency;
163
- private _maxConcurrency;
164
- private _desiredConcurrency;
165
161
  private _currentConcurrency;
166
- private lastLoggingTime?;
167
- private _tasksPerMinute;
168
162
  private readonly snapshotter;
169
- private readonly loadSignals;
170
163
  private readonly systemStatus;
171
- private autoscaleInterval?;
172
- private tasksDonePerSecondInterval?;
173
- /** Whether the snapshotter and autoscaling intervals are currently running. */
174
- private running;
175
- /** The in-flight (or completed) startup, memoized so concurrent `start()` calls await one boot. */
176
- private startPromise?;
177
- /** Set once per session, so a pool outliving `stop()` is reported once rather than every half second. */
178
- private warnedAboutQueryWhileStopped;
179
164
  constructor(options?: ConcurrencySystemOptions);
180
165
  /**
181
166
  * Gets the minimum number of tasks running in parallel.
@@ -270,14 +255,14 @@ export declare class ConcurrencySystem implements IConcurrencySystem {
270
255
  * Evaluates the historical system status and scales the shared desired concurrency up or down accordingly. Driven
271
256
  * by the autoscaling interval started in {@link ConcurrencySystem.start|`start()`}.
272
257
  */
273
- private _autoscale;
258
+ private autoscale;
274
259
  /**
275
260
  * Scales the system up by increasing the desired concurrency by the scaleUpStepRatio.
276
261
  */
277
- private _scaleUp;
262
+ private scaleUp;
278
263
  /**
279
264
  * Scales the system down by decreasing the desired concurrency by the scaleDownStepRatio.
280
265
  */
281
- private _scaleDown;
282
- private _incrementTasksDonePerSecond;
266
+ private scaleDown;
267
+ private incrementTasksDonePerSecond;
283
268
  }