@crawlee/core 4.0.0-beta.104 → 4.0.0-beta.106

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 (83) hide show
  1. package/autoscaling/autoscaled_pool.d.ts +3 -21
  2. package/autoscaling/autoscaled_pool.js +85 -85
  3. package/autoscaling/client_load_signal.d.ts +1 -5
  4. package/autoscaling/client_load_signal.js +20 -20
  5. package/autoscaling/concurrency_system.d.ts +5 -20
  6. package/autoscaling/concurrency_system.js +81 -80
  7. package/autoscaling/cpu_load_signal.d.ts +1 -2
  8. package/autoscaling/cpu_load_signal.js +10 -10
  9. package/autoscaling/event_loop_load_signal.d.ts +1 -4
  10. package/autoscaling/event_loop_load_signal.js +18 -18
  11. package/autoscaling/load_signal.d.ts +1 -1
  12. package/autoscaling/load_signal.js +12 -11
  13. package/autoscaling/memory_load_signal.d.ts +3 -12
  14. package/autoscaling/memory_load_signal.js +40 -41
  15. package/autoscaling/snapshotter.d.ts +1 -4
  16. package/autoscaling/snapshotter.js +12 -12
  17. package/autoscaling/system_status.d.ts +1 -3
  18. package/autoscaling/system_status.js +11 -11
  19. package/configuration.d.ts +1 -1
  20. package/configuration.js +3 -3
  21. package/crawlers/context_pipeline.js +6 -6
  22. package/crawlers/crawler_commons.d.ts +6 -56
  23. package/crawlers/crawler_commons.js +1 -107
  24. package/crawlers/index.d.ts +1 -1
  25. package/crawlers/index.js +0 -1
  26. package/crawlers/statistics.d.ts +1 -8
  27. package/crawlers/statistics.js +45 -44
  28. package/events/event_manager.d.ts +1 -1
  29. package/events/event_manager.js +3 -3
  30. package/events/local_event_manager.d.ts +1 -1
  31. package/events/local_event_manager.js +3 -3
  32. package/log.js +5 -1
  33. package/memory-storage/memory-storage.d.ts +1 -5
  34. package/memory-storage/memory-storage.js +2 -2
  35. package/memory-storage/resource-clients/dataset.d.ts +1 -1
  36. package/memory-storage/resource-clients/dataset.js +6 -5
  37. package/memory-storage/resource-clients/key-value-store.d.ts +1 -1
  38. package/memory-storage/resource-clients/key-value-store.js +13 -12
  39. package/memory-storage/resource-clients/request-queue.d.ts +4 -23
  40. package/memory-storage/resource-clients/request-queue.js +59 -58
  41. package/owned_or_injected.d.ts +1 -3
  42. package/owned_or_injected.js +17 -17
  43. package/package.json +5 -5
  44. package/proxy_configuration.d.ts +1 -3
  45. package/proxy_configuration.js +8 -8
  46. package/recoverable_state.d.ts +1 -10
  47. package/recoverable_state.js +41 -41
  48. package/request.d.ts +1 -2
  49. package/request.js +10 -13
  50. package/router.d.ts +1 -4
  51. package/router.js +23 -23
  52. package/serialization.js +8 -9
  53. package/service_locator.d.ts +1 -10
  54. package/service_locator.js +48 -48
  55. package/session_pool/session.d.ts +1 -12
  56. package/session_pool/session.js +50 -50
  57. package/session_pool/session_pool.d.ts +2 -11
  58. package/session_pool/session_pool.js +59 -58
  59. package/storages/dataset.d.ts +12 -1
  60. package/storages/dataset.js +121 -22
  61. package/storages/index.d.ts +1 -1
  62. package/storages/index.js +1 -1
  63. package/storages/key_value_store.d.ts +19 -4
  64. package/storages/key_value_store.js +174 -48
  65. package/storages/request_dedup_cache.d.ts +1 -2
  66. package/storages/request_dedup_cache.js +9 -9
  67. package/storages/request_list.d.ts +2 -22
  68. package/storages/request_list.js +74 -73
  69. package/storages/request_manager_tandem.d.ts +1 -10
  70. package/storages/request_manager_tandem.js +27 -27
  71. package/storages/request_queue.d.ts +21 -18
  72. package/storages/request_queue.js +256 -53
  73. package/storages/sitemap_request_loader.d.ts +1 -44
  74. package/storages/sitemap_request_loader.js +87 -87
  75. package/storages/storage_instance_manager.d.ts +1 -2
  76. package/storages/storage_instance_manager.js +17 -17
  77. package/storages/storage_stats.d.ts +1 -1
  78. package/storages/storage_stats.js +4 -4
  79. package/storages/transaction.d.ts +252 -0
  80. package/storages/transaction.js +251 -0
  81. package/system-info/runtime.js +7 -7
  82. package/storages/access_checking.d.ts +0 -12
  83. 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.
@@ -56,27 +56,27 @@ import { serviceLocator } from '../service_locator.js';
56
56
  * @internal
57
57
  */
58
58
  export class AutoscaledPool {
59
- log;
59
+ #log;
60
60
  // Configurable properties.
61
- maybeRunIntervalMillis;
62
- taskTimeoutMillis;
63
- runTaskFunction;
64
- isFinishedFunction;
65
- isTaskReadyFunction;
66
- concurrencySystem;
67
- consumer;
61
+ #maybeRunIntervalMillis;
62
+ #taskTimeoutMillis;
63
+ #runTaskFunction;
64
+ #isFinishedFunction;
65
+ #isTaskReadyFunction;
66
+ #concurrencySystem;
67
+ #consumer;
68
68
  // Internal properties.
69
- isStopped = false;
70
- resolve = null;
71
- reject = null;
72
- maybeRunInterval;
73
- queryingIsTaskReady;
74
- queryingIsFinished;
69
+ #isStopped = false;
70
+ #resolve = null;
71
+ #reject = null;
72
+ #maybeRunInterval;
73
+ #queryingIsTaskReady;
74
+ #queryingIsFinished;
75
75
  /**
76
76
  * This pool's *own* in-flight task count, as opposed to {@link AutoscaledPool.currentConcurrency}, which is the
77
77
  * (possibly shared) governor's total. `pause()` and `maybeFinish()` care only about this pool draining.
78
78
  */
79
- ownConcurrency = 0;
79
+ #ownConcurrency = 0;
80
80
  constructor(options) {
81
81
  ow(options, ow.object.exactShape({
82
82
  runTaskFunction: ow.function,
@@ -89,19 +89,19 @@ export class AutoscaledPool {
89
89
  consumer: ow.object.partialShape({ id: ow.string.nonEmpty }),
90
90
  }));
91
91
  const { runTaskFunction, isFinishedFunction, isTaskReadyFunction, maybeRunIntervalSecs = 0.5, taskTimeoutSecs = 0, log = serviceLocator.getLogger(), concurrencySystem, consumer, } = options;
92
- this.log = log.child({ prefix: 'AutoscaledPool' });
92
+ this.#log = log.child({ prefix: 'AutoscaledPool' });
93
93
  // 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;
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;
101
101
  // Internal properties.
102
- this.isStopped = false;
103
- this.resolve = null;
104
- this.reject = null;
102
+ this.#isStopped = false;
103
+ this.#resolve = null;
104
+ this.#reject = null;
105
105
  this.maybeRunTask = this.maybeRunTask.bind(this);
106
106
  }
107
107
  /**
@@ -112,18 +112,18 @@ export class AutoscaledPool {
112
112
  * {@link ConcurrencySystem} its owner holds, never through the pool.
113
113
  */
114
114
  get system() {
115
- return this.concurrencySystem;
115
+ return this.#concurrencySystem;
116
116
  }
117
117
  /** The estimated number of parallel tasks the governor can currently support. */
118
118
  get desiredConcurrency() {
119
- return this.concurrencySystem.desiredConcurrency;
119
+ return this.#concurrencySystem.desiredConcurrency;
120
120
  }
121
121
  /**
122
122
  * The number of parallel tasks currently booked against the governor. When it is shared, this counts every
123
123
  * borrowing pool's tasks, not just this one's.
124
124
  */
125
125
  get currentConcurrency() {
126
- return this.concurrencySystem.currentConcurrency;
126
+ return this.#concurrencySystem.currentConcurrency;
127
127
  }
128
128
  /**
129
129
  * Runs the auto-scaled pool. Returns a promise that gets resolved or rejected once
@@ -135,26 +135,26 @@ export class AutoscaledPool {
135
135
  async run() {
136
136
  // Checked here, on an awaited path — the capacity queries inside the task loop run from intervals and
137
137
  // `setImmediate`, where a throw would become an unhandled rejection and hang `run()` forever.
138
- if (!this.concurrencySystem.isRunning) {
138
+ if (!this.#concurrencySystem.isRunning) {
139
139
  throw new CriticalError('The ConcurrencySystem this AutoscaledPool borrows has not been started, so system load would not be ' +
140
140
  'monitored and the concurrency would never be adjusted. Whoever creates a ConcurrencySystem owns ' +
141
141
  'its lifecycle: call `await concurrencySystem.start()` before running the pools or crawlers that ' +
142
142
  'use it, and `await concurrencySystem.stop()` once they are all done.');
143
143
  }
144
144
  const poolPromise = new Promise((resolve, reject) => {
145
- this.resolve = resolve;
146
- this.reject = reject;
145
+ this.#resolve = resolve;
146
+ this.#reject = reject;
147
147
  });
148
148
  // This is here because if we scale down to let's say 1, then after each promise is finished
149
149
  // this.maybeRunTask() doesn't trigger another one. So if that 1 instance gets stuck it results
150
150
  // in the crawler getting stuck and even after scaling up it never triggers another promise.
151
- this.maybeRunInterval = betterSetInterval(this.maybeRunTask, this.maybeRunIntervalMillis);
151
+ this.#maybeRunInterval = betterSetInterval(this.maybeRunTask, this.#maybeRunIntervalMillis);
152
152
  try {
153
153
  await poolPromise;
154
154
  }
155
155
  finally {
156
156
  // If resolve is null, the pool is already destroyed.
157
- if (this.resolve)
157
+ if (this.#resolve)
158
158
  await this.destroy();
159
159
  }
160
160
  }
@@ -170,9 +170,9 @@ export class AutoscaledPool {
170
170
  * parts of their asynchronous chains of commands will not execute.
171
171
  */
172
172
  async abort() {
173
- this.isStopped = true;
174
- if (this.resolve) {
175
- this.resolve();
173
+ this.#isStopped = true;
174
+ if (this.#resolve) {
175
+ this.#resolve();
176
176
  await this.destroy();
177
177
  }
178
178
  }
@@ -192,9 +192,9 @@ export class AutoscaledPool {
192
192
  * it during a long pause, its owner can `stop()` and `start()` it again.
193
193
  */
194
194
  async pause(timeoutSecs) {
195
- if (this.isStopped)
195
+ if (this.#isStopped)
196
196
  return;
197
- this.isStopped = true;
197
+ this.#isStopped = true;
198
198
  await new Promise((resolve, reject) => {
199
199
  let timeout;
200
200
  let interval;
@@ -208,14 +208,14 @@ export class AutoscaledPool {
208
208
  }, timeoutSecs);
209
209
  }
210
210
  interval = setInterval(() => {
211
- if (this.ownConcurrency <= 0) {
211
+ if (this.#ownConcurrency <= 0) {
212
212
  // Clean up timeout and interval to prevent process hanging.
213
213
  if (timeout)
214
214
  clearTimeout(timeout);
215
215
  clearInterval(interval);
216
216
  resolve();
217
217
  }
218
- }, this.maybeRunIntervalMillis);
218
+ }, this.#maybeRunIntervalMillis);
219
219
  });
220
220
  }
221
221
  /**
@@ -225,7 +225,7 @@ export class AutoscaledPool {
225
225
  * Tasks will automatically start running again in `options.maybeRunIntervalSecs`.
226
226
  */
227
227
  resume() {
228
- this.isStopped = false;
228
+ this.#isStopped = false;
229
229
  }
230
230
  /**
231
231
  * Explicitly check the queue for new tasks. The AutoscaledPool checks the queue for new tasks periodically,
@@ -238,27 +238,27 @@ export class AutoscaledPool {
238
238
  * Starts a new task
239
239
  * if the number of running tasks (current concurrency) is lower than desired concurrency
240
240
  * and the system is not currently overloaded
241
- * and this.isTaskReadyFunction() returns true.
241
+ * and `isTaskReadyFunction()` returns true.
242
242
  *
243
243
  * It doesn't allow multiple concurrent runs of this method.
244
244
  */
245
245
  async maybeRunTask(intervalCallback) {
246
- this.log.perf('Attempting to run a task.');
246
+ this.#log.perf('Attempting to run a task.');
247
247
  // Check if the function was invoked by the maybeRunInterval and use an empty function if not.
248
248
  const done = intervalCallback || (() => { });
249
249
  // Prevent starting a new task if:
250
250
  // - the pool is paused or aborted
251
- if (this.isStopped) {
252
- this.log.perf('Task will not run. AutoscaledPool is stopped.');
251
+ if (this.#isStopped) {
252
+ this.#log.perf('Task will not run. AutoscaledPool is stopped.');
253
253
  return done();
254
254
  }
255
255
  // - we are already querying for a task.
256
- if (this.queryingIsTaskReady) {
257
- this.log.perf('Task will not run. Waiting for a ready task.');
256
+ if (this.#queryingIsTaskReady) {
257
+ this.#log.perf('Task will not run. Waiting for a ready task.');
258
258
  return done();
259
259
  }
260
260
  // - the budget has room for us.
261
- if (!this.concurrencySystem.hasCapacityForTask(this.consumer)) {
261
+ if (!this.#concurrencySystem.hasCapacityForTask(this.#consumer)) {
262
262
  done();
263
263
  // A shared governor's budget can stay saturated by another pool indefinitely, so we still have to be able
264
264
  // to notice that *this* pool has run out of work — `maybeFinish()` is the only thing that ever resolves
@@ -267,37 +267,37 @@ export class AutoscaledPool {
267
267
  return this.maybeFinish();
268
268
  }
269
269
  // - a task is ready.
270
- this.queryingIsTaskReady = true;
270
+ this.#queryingIsTaskReady = true;
271
271
  let isTaskReady;
272
272
  try {
273
- this.log.perf('Checking for ready tasks.');
274
- isTaskReady = await this.isTaskReadyFunction();
273
+ this.#log.perf('Checking for ready tasks.');
274
+ isTaskReady = await this.#isTaskReadyFunction();
275
275
  }
276
276
  catch (e) {
277
277
  const err = e;
278
- this.log.perf('Checking for ready tasks failed.');
278
+ this.#log.perf('Checking for ready tasks failed.');
279
279
  // We might have already rejected this promise.
280
- if (this.reject) {
280
+ if (this.#reject) {
281
281
  // No need to log all concurrent errors.
282
- this.log.exception(err, 'isTaskReadyFunction failed');
283
- this.reject(err);
282
+ this.#log.exception(err, 'isTaskReadyFunction failed');
283
+ this.#reject(err);
284
284
  }
285
285
  }
286
286
  finally {
287
- this.queryingIsTaskReady = false;
287
+ this.#queryingIsTaskReady = false;
288
288
  }
289
289
  if (!isTaskReady) {
290
- this.log.perf('Task will not run. No tasks are ready.');
290
+ this.#log.perf('Task will not run. No tasks are ready.');
291
291
  done();
292
292
  // No tasks could mean that we're finished with all tasks.
293
293
  return this.maybeFinish();
294
294
  }
295
295
  // - the budget still has room. Re-checked atomically, because another pool sharing the governor may have taken
296
296
  // the last free slot while we awaited `isTaskReadyFunction` above.
297
- if (!this.concurrencySystem.tryRegisterTaskStart(this.consumer)) {
297
+ if (!this.#concurrencySystem.tryRegisterTaskStart(this.#consumer)) {
298
298
  return done();
299
299
  }
300
- this.ownConcurrency++;
300
+ this.#ownConcurrency++;
301
301
  try {
302
302
  // Everything's fine. Run task.
303
303
  // Try to run next task to build up concurrency,
@@ -306,73 +306,73 @@ export class AutoscaledPool {
306
306
  // We need to restart interval here, so that it doesn't get blocked by a stalled task.
307
307
  done();
308
308
  // 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.`);
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.`);
312
312
  }
313
313
  else {
314
- await this.runTaskFunction();
314
+ await this.#runTaskFunction();
315
315
  }
316
- this.log.perf('Task finished.');
316
+ this.#log.perf('Task finished.');
317
317
  // Run task after the previous one finished. Only on success: a failed task rejects the pool, and
318
318
  // nudging the loop afterwards could start work on an already destroyed pool.
319
319
  setImmediate(this.maybeRunTask);
320
320
  }
321
321
  catch (e) {
322
322
  const err = e;
323
- this.log.perf('Running a task failed.');
323
+ this.#log.perf('Running a task failed.');
324
324
  // We might have already rejected this promise.
325
- if (this.reject) {
325
+ if (this.#reject) {
326
326
  // No need to log all concurrent errors.
327
327
  if (
328
328
  // avoid reprinting the same critical error multiple times, as it will be printed by Nodejs at the end anyway
329
329
  !(e instanceof CriticalError)) {
330
- this.log.exception(err, 'runTaskFunction failed.');
330
+ this.#log.exception(err, 'runTaskFunction failed.');
331
331
  }
332
- this.reject(err);
332
+ this.#reject(err);
333
333
  }
334
334
  }
335
335
  finally {
336
- this.concurrencySystem.registerTaskEnd(this.consumer);
337
- this.ownConcurrency--;
336
+ this.#concurrencySystem.registerTaskEnd(this.#consumer);
337
+ this.#ownConcurrency--;
338
338
  }
339
339
  return undefined;
340
340
  }
341
341
  /**
342
- * If there are no running tasks and this.isFinishedFunction() returns true then closes
342
+ * If there are no running tasks and `isFinishedFunction()` returns true then closes
343
343
  * the pool and resolves the pool's promise returned by the run() method.
344
344
  *
345
345
  * It doesn't allow multiple concurrent runs of this method.
346
346
  */
347
347
  async maybeFinish() {
348
- if (this.queryingIsFinished)
348
+ if (this.#queryingIsFinished)
349
349
  return;
350
- if (this.ownConcurrency > 0)
350
+ if (this.#ownConcurrency > 0)
351
351
  return;
352
- this.queryingIsFinished = true;
352
+ this.#queryingIsFinished = true;
353
353
  try {
354
- const isFinished = await this.isFinishedFunction();
355
- if (isFinished && this.resolve)
356
- this.resolve();
354
+ const isFinished = await this.#isFinishedFunction();
355
+ if (isFinished && this.#resolve)
356
+ this.#resolve();
357
357
  }
358
358
  catch (e) {
359
359
  const err = e;
360
- if (this.reject) {
360
+ if (this.#reject) {
361
361
  // No need to log all concurrent errors.
362
- this.log.exception(err, 'isFinishedFunction failed.');
363
- this.reject(err);
362
+ this.#log.exception(err, 'isFinishedFunction failed.');
363
+ this.#reject(err);
364
364
  }
365
365
  }
366
366
  finally {
367
- this.queryingIsFinished = false;
367
+ this.#queryingIsFinished = false;
368
368
  }
369
369
  }
370
370
  /**
371
371
  * Cleans up resources.
372
372
  */
373
373
  async destroy() {
374
- this.resolve = null;
375
- this.reject = null;
376
- betterClearInterval(this.maybeRunInterval);
374
+ this.#resolve = null;
375
+ this.#reject = null;
376
+ betterClearInterval(this.#maybeRunInterval);
377
377
  }
378
378
  }
@@ -39,13 +39,9 @@ export interface ClientLoadSignalOptions {
39
39
  * @category Scaling
40
40
  */
41
41
  export declare class ClientLoadSignal implements LoadSignal {
42
+ #private;
42
43
  readonly name = "clientInfo";
43
44
  readonly overloadedRatio: number;
44
- private readonly store;
45
- private readonly intervalMillis;
46
- private readonly maxErrors;
47
- private interval?;
48
- private client?;
49
45
  constructor(options?: ClientLoadSignalOptions);
50
46
  start(context: LoadSignalStartContext): Promise<void>;
51
47
  stop(): Promise<void>;
@@ -16,35 +16,35 @@ const CLIENT_RATE_LIMIT_ERROR_RETRY_COUNT = 2;
16
16
  export class ClientLoadSignal {
17
17
  name = 'clientInfo';
18
18
  overloadedRatio;
19
- store = new SnapshotStore();
20
- intervalMillis;
21
- maxErrors;
22
- interval;
23
- client;
19
+ #store = new SnapshotStore();
20
+ #intervalMillis;
21
+ #maxErrors;
22
+ #interval;
23
+ #client;
24
24
  constructor(options = {}) {
25
25
  this.overloadedRatio = options.overloadedRatio ?? 0.3;
26
- this.intervalMillis = (options.snapshotIntervalSecs ?? 1) * 1000;
27
- this.maxErrors = options.maxErrors ?? 3;
26
+ this.#intervalMillis = (options.snapshotIntervalSecs ?? 1) * 1000;
27
+ this.#maxErrors = options.maxErrors ?? 3;
28
28
  this.handle = this.handle.bind(this);
29
29
  }
30
30
  async start(context) {
31
- this.store.useSampleWindow(context.maxSampleWindowMillis);
31
+ this.#store.useSampleWindow(context.maxSampleWindowMillis);
32
32
  // A new session starts from a clean slate, or its first measurement diffs the error count against the previous
33
33
  // session's — possibly against a different backend, since the client is resolved afresh just below.
34
- this.store.clear();
34
+ this.#store.clear();
35
35
  // Resolved here rather than in the constructor, where asking for the backend would instantiate a default one
36
36
  // as a side effect - long before the crawler that owns the run has had a chance to register its own.
37
- this.client = serviceLocator.getStorageBackend();
38
- this.interval = betterSetInterval(this.handle, this.intervalMillis);
37
+ this.#client = serviceLocator.getStorageBackend();
38
+ this.#interval = betterSetInterval(this.handle, this.#intervalMillis);
39
39
  }
40
40
  async stop() {
41
- if (this.interval)
42
- betterClearInterval(this.interval);
43
- this.interval = undefined;
44
- this.client = undefined;
41
+ if (this.#interval)
42
+ betterClearInterval(this.#interval);
43
+ this.#interval = undefined;
44
+ this.#client = undefined;
45
45
  }
46
46
  getSample(sampleDurationMillis) {
47
- return this.store.getSample(sampleDurationMillis);
47
+ return this.#store.getSample(sampleDurationMillis);
48
48
  }
49
49
  /**
50
50
  * Records one snapshot, overloaded when rate-limit errors grew by more than the configured limit since the
@@ -53,21 +53,21 @@ export class ClientLoadSignal {
53
53
  */
54
54
  handle(intervalCallback) {
55
55
  const now = new Date();
56
- const allErrorCounts = this.client?.stats?.rateLimitErrors ?? [];
56
+ const allErrorCounts = this.#client?.stats?.rateLimitErrors ?? [];
57
57
  const currentErrCount = allErrorCounts[CLIENT_RATE_LIMIT_ERROR_RETRY_COUNT] || 0;
58
58
  const snapshot = {
59
59
  createdAt: now,
60
60
  isOverloaded: false,
61
61
  rateLimitErrorCount: currentErrCount,
62
62
  };
63
- const all = this.store.getAll();
63
+ const all = this.#store.getAll();
64
64
  const previousSnapshot = all[all.length - 1];
65
65
  if (previousSnapshot) {
66
66
  const delta = currentErrCount - previousSnapshot.rateLimitErrorCount;
67
- if (delta > this.maxErrors)
67
+ if (delta > this.#maxErrors)
68
68
  snapshot.isOverloaded = true;
69
69
  }
70
- this.store.push(snapshot, now);
70
+ this.#store.push(snapshot, now);
71
71
  intervalCallback();
72
72
  }
73
73
  }
@@ -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
  }