@crawlee/core 4.0.0-beta.105 → 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 (75) 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/statistics.d.ts +1 -8
  23. package/crawlers/statistics.js +45 -44
  24. package/events/event_manager.d.ts +1 -1
  25. package/events/event_manager.js +3 -3
  26. package/events/local_event_manager.d.ts +1 -1
  27. package/events/local_event_manager.js +3 -3
  28. package/log.js +5 -1
  29. package/memory-storage/memory-storage.d.ts +1 -5
  30. package/memory-storage/memory-storage.js +2 -2
  31. package/memory-storage/resource-clients/dataset.d.ts +1 -1
  32. package/memory-storage/resource-clients/dataset.js +6 -5
  33. package/memory-storage/resource-clients/key-value-store.d.ts +1 -1
  34. package/memory-storage/resource-clients/key-value-store.js +13 -12
  35. package/memory-storage/resource-clients/request-queue.d.ts +4 -23
  36. package/memory-storage/resource-clients/request-queue.js +59 -58
  37. package/owned_or_injected.d.ts +1 -3
  38. package/owned_or_injected.js +17 -17
  39. package/package.json +5 -5
  40. package/proxy_configuration.d.ts +1 -3
  41. package/proxy_configuration.js +8 -8
  42. package/recoverable_state.d.ts +1 -10
  43. package/recoverable_state.js +41 -41
  44. package/request.d.ts +1 -2
  45. package/request.js +10 -13
  46. package/router.d.ts +1 -4
  47. package/router.js +23 -23
  48. package/serialization.js +8 -9
  49. package/service_locator.d.ts +1 -10
  50. package/service_locator.js +48 -48
  51. package/session_pool/session.d.ts +1 -12
  52. package/session_pool/session.js +50 -50
  53. package/session_pool/session_pool.d.ts +2 -11
  54. package/session_pool/session_pool.js +59 -58
  55. package/storages/dataset.d.ts +1 -1
  56. package/storages/dataset.js +5 -5
  57. package/storages/key_value_store.d.ts +1 -4
  58. package/storages/key_value_store.js +21 -20
  59. package/storages/request_dedup_cache.d.ts +1 -2
  60. package/storages/request_dedup_cache.js +9 -9
  61. package/storages/request_list.d.ts +2 -22
  62. package/storages/request_list.js +74 -73
  63. package/storages/request_manager_tandem.d.ts +1 -10
  64. package/storages/request_manager_tandem.js +27 -27
  65. package/storages/request_queue.d.ts +2 -18
  66. package/storages/request_queue.js +37 -35
  67. package/storages/sitemap_request_loader.d.ts +1 -44
  68. package/storages/sitemap_request_loader.js +87 -87
  69. package/storages/storage_instance_manager.d.ts +1 -2
  70. package/storages/storage_instance_manager.js +17 -17
  71. package/storages/storage_stats.d.ts +1 -1
  72. package/storages/storage_stats.js +4 -4
  73. package/storages/transaction.d.ts +1 -3
  74. package/storages/transaction.js +17 -17
  75. package/system-info/runtime.js +7 -7
@@ -56,26 +56,28 @@ export class RequestQueue {
56
56
  id;
57
57
  name;
58
58
  backend;
59
- proxyConfiguration;
59
+ #proxyConfiguration;
60
60
  log;
61
+ // kept as TS-private: request_queue tests read this cache directly
61
62
  requestCache;
62
63
  /**
63
64
  * Remembers the `requestId` of every request already submitted to the client — including background
64
65
  * batches that `requestCache` skips — so overlapping URL sets aren't re-submitted.
65
66
  * See {@link RequestDeduplicationCache} for why this is a separate, cheaper cache.
66
67
  */
67
- requestSeenCache;
68
- queuePausedForMigration = false;
68
+ #requestSeenCache;
69
+ #queuePausedForMigration = false;
70
+ // kept as TS-private: packages/core/test request-queue tests write this counter directly
69
71
  inProgressRequestBatchCount = 0;
70
72
  /**
71
73
  * The largest expected request-processing time (in seconds) seen so far via
72
74
  * {@link setExpectedRequestProcessingTimeSecs}. Used to ensure that value is only ever raised, never
73
75
  * lowered, before being forwarded to the storage backend.
74
76
  */
75
- expectedRequestProcessingSecs = 0;
76
- httpClient;
77
- events;
78
- statsTracker = new StorageStatsTracker({
77
+ #expectedRequestProcessingSecs = 0;
78
+ #httpClient;
79
+ #events;
80
+ #statsTracker = new StorageStatsTracker({
79
81
  writeCount: 0,
80
82
  headItemReadCount: 0,
81
83
  });
@@ -84,7 +86,7 @@ export class RequestQueue {
84
86
  * queue-head reads issued to the underlying storage backend). Counted per backend call.
85
87
  */
86
88
  get stats() {
87
- return this.statsTracker.current;
89
+ return this.#statsTracker.current;
88
90
  }
89
91
  /**
90
92
  * @internal
@@ -92,14 +94,14 @@ export class RequestQueue {
92
94
  constructor(options) {
93
95
  this.id = options.metadata.id;
94
96
  this.name = options.metadata.name;
95
- this.events = serviceLocator.getEventManager();
97
+ this.#events = serviceLocator.getEventManager();
96
98
  this.backend = options.backend;
97
- this.proxyConfiguration = options.proxyConfiguration;
99
+ this.#proxyConfiguration = options.proxyConfiguration;
98
100
  this.requestCache = new LruCache({ maxLength: MAX_CACHED_REQUESTS });
99
- this.requestSeenCache = new RequestDeduplicationCache();
101
+ this.#requestSeenCache = new RequestDeduplicationCache();
100
102
  this.log = serviceLocator.getLogger().child({ prefix: `RequestQueue(${this.id}, ${this.name ?? 'no-name'})` });
101
- this.events.on("migrating" /* EventType.MIGRATING */, async () => {
102
- this.queuePausedForMigration = true;
103
+ this.#events.on("migrating" /* EventType.MIGRATING */, async () => {
104
+ this.#queuePausedForMigration = true;
103
105
  });
104
106
  }
105
107
  /**
@@ -169,7 +171,7 @@ export class RequestQueue {
169
171
  forefront,
170
172
  };
171
173
  }
172
- this.statsTracker.add('writeCount');
174
+ this.#statsTracker.add('writeCount');
173
175
  const { processedRequests } = await this.backend.addBatchOfRequests([request], { forefront });
174
176
  this.recordRequestJournalEntry(transaction, [request], forefront, true);
175
177
  const queueOperationInfo = {
@@ -178,7 +180,7 @@ export class RequestQueue {
178
180
  forefront,
179
181
  };
180
182
  this.cacheRequest(cacheKey, queueOperationInfo);
181
- this.requestSeenCache.add(cacheKey, request.id);
183
+ this.#requestSeenCache.add(cacheKey, request.id);
182
184
  return queueOperationInfo;
183
185
  }
184
186
  /**
@@ -240,7 +242,7 @@ export class RequestQueue {
240
242
  // reading saves a probe. Same lookup as the write-through path.
241
243
  const cacheKey = getRequestId(request.uniqueKey);
242
244
  const cachedInfo = this.requestCache.get(cacheKey);
243
- const knownRequestId = cachedInfo?.id ?? this.requestSeenCache.get(cacheKey);
245
+ const knownRequestId = cachedInfo?.id ?? this.#requestSeenCache.get(cacheKey);
244
246
  if (knownRequestId) {
245
247
  this.recordRequestJournalEntry(transaction, [request], forefront, false);
246
248
  return {
@@ -306,7 +308,7 @@ export class RequestQueue {
306
308
  : []);
307
309
  if (requests.length === 0)
308
310
  continue;
309
- this.statsTracker.add('writeCount');
311
+ this.#statsTracker.add('writeCount');
310
312
  const { processedRequests, unprocessedRequests } = await this.backend.addBatchOfRequests(requests, {
311
313
  forefront,
312
314
  });
@@ -314,7 +316,7 @@ export class RequestQueue {
314
316
  for (const processed of processedRequests) {
315
317
  const cacheKey = getRequestId(processed.uniqueKey);
316
318
  this.cacheRequest(cacheKey, { ...processed, forefront });
317
- this.requestSeenCache.add(cacheKey, processed.requestId);
319
+ this.#requestSeenCache.add(cacheKey, processed.requestId);
318
320
  }
319
321
  if (unprocessedRequests.length > 0) {
320
322
  // Warn and skip, rather than retry or fail. `unprocessedRequests` is what remains after
@@ -389,7 +391,7 @@ export class RequestQueue {
389
391
  const cacheKey = getCachedRequestId(request.uniqueKey);
390
392
  // Prefer the full `requestCache` record; fall back to the dedup cache for background batches it skips.
391
393
  const cachedInfo = this.requestCache.get(cacheKey);
392
- const knownRequestId = cachedInfo?.id ?? this.requestSeenCache.get(cacheKey);
394
+ const knownRequestId = cachedInfo?.id ?? this.#requestSeenCache.get(cacheKey);
393
395
  if (knownRequestId) {
394
396
  request.id = knownRequestId;
395
397
  results.processedRequests.push({
@@ -408,7 +410,7 @@ export class RequestQueue {
408
410
  if (!requestsToAdd.size) {
409
411
  return results;
410
412
  }
411
- this.statsTracker.add('writeCount');
413
+ this.#statsTracker.add('writeCount');
412
414
  const apiResults = await this.backend.addBatchOfRequests([...requestsToAdd.values()], { forefront });
413
415
  // Report unprocessed requests
414
416
  results.unprocessedRequests = apiResults.unprocessedRequests;
@@ -421,7 +423,7 @@ export class RequestQueue {
421
423
  this.cacheRequest(cacheKey, { ...newRequest, forefront });
422
424
  }
423
425
  // Unlike `requestCache`, populate this on every batch (including background ones).
424
- this.requestSeenCache.add(cacheKey, newRequest.requestId);
426
+ this.#requestSeenCache.add(cacheKey, newRequest.requestId);
425
427
  }
426
428
  return results;
427
429
  }
@@ -609,10 +611,10 @@ export class RequestQueue {
609
611
  */
610
612
  async fetchNextRequest() {
611
613
  rejectOperationInTransaction('RequestQueue.fetchNextRequest()', 'it is part of the crawler request-processing bookkeeping, which a transaction must not affect.');
612
- if (this.queuePausedForMigration) {
614
+ if (this.#queuePausedForMigration) {
613
615
  return null;
614
616
  }
615
- this.statsTracker.add('headItemReadCount');
617
+ this.#statsTracker.add('headItemReadCount');
616
618
  const requestOptions = await this.backend.fetchNextRequest();
617
619
  if (!requestOptions)
618
620
  return null;
@@ -633,7 +635,7 @@ export class RequestQueue {
633
635
  }));
634
636
  const forefront = this.requestCache.get(getRequestId(request.uniqueKey))?.forefront ?? false;
635
637
  const handledAt = request.handledAt ?? new Date().toISOString();
636
- this.statsTracker.add('writeCount');
638
+ this.#statsTracker.add('writeCount');
637
639
  const processedRequest = await this.backend.markRequestAsHandled({
638
640
  ...request,
639
641
  handledAt,
@@ -667,7 +669,7 @@ export class RequestQueue {
667
669
  forefront: ow.optional.boolean,
668
670
  }));
669
671
  const { forefront = false } = options;
670
- this.statsTracker.add('writeCount');
672
+ this.#statsTracker.add('writeCount');
671
673
  const processedRequest = await this.backend.reclaimRequest(request, { forefront });
672
674
  // The request was not in progress — nothing to reclaim.
673
675
  if (!processedRequest) {
@@ -730,10 +732,10 @@ export class RequestQueue {
730
732
  * short the reservation of a long-lived one and have its in-flight request stolen.
731
733
  */
732
734
  async setExpectedRequestProcessingTimeSecs(secs) {
733
- if (secs <= this.expectedRequestProcessingSecs) {
735
+ if (secs <= this.#expectedRequestProcessingSecs) {
734
736
  return;
735
737
  }
736
- this.expectedRequestProcessingSecs = secs;
738
+ this.#expectedRequestProcessingSecs = secs;
737
739
  await this.backend.setExpectedRequestProcessingTimeSecs?.(secs);
738
740
  }
739
741
  /**
@@ -769,12 +771,12 @@ export class RequestQueue {
769
771
  await this.backend.purge();
770
772
  // Reset in-memory bookkeeping so the queue behaves as if freshly opened.
771
773
  this.requestCache.clear();
772
- this.requestSeenCache.clear();
774
+ this.#requestSeenCache.clear();
773
775
  this.inProgressRequestBatchCount = 0;
774
776
  // Reset the expected-processing-time high-water mark too, otherwise the monotonic-raise guard
775
777
  // in `setExpectedRequestProcessingTimeSecs` would let a value raised in an earlier run leak into a
776
778
  // later one and silently swallow a lower hint (the queue is meant to be reusable across runs).
777
- this.expectedRequestProcessingSecs = 0;
779
+ this.#expectedRequestProcessingSecs = 0;
778
780
  }
779
781
  /**
780
782
  * @inheritdoc
@@ -842,10 +844,10 @@ export class RequestQueue {
842
844
  // Download remote resource and parse URLs.
843
845
  let urlsArr;
844
846
  try {
845
- urlsArr = await this._downloadListOfUrls({
847
+ urlsArr = await this.downloadListOfUrls({
846
848
  url: requestsFromUrl,
847
849
  urlRegExp: regex,
848
- proxyUrl: (await this.proxyConfiguration?.newProxyInfo())?.url,
850
+ proxyUrl: (await this.#proxyConfiguration?.newProxyInfo())?.url,
849
851
  });
850
852
  }
851
853
  catch (err) {
@@ -877,10 +879,10 @@ export class RequestQueue {
877
879
  /**
878
880
  * @internal wraps public utility for mocking purposes
879
881
  */
880
- async _downloadListOfUrls(options) {
882
+ async downloadListOfUrls(options) {
881
883
  return downloadListOfUrls({
882
884
  ...options,
883
- httpClient: this.httpClient,
885
+ httpClient: this.#httpClient,
884
886
  });
885
887
  }
886
888
  /**
@@ -919,8 +921,8 @@ export class RequestQueue {
919
921
  backendOpener: () => storageBackend.createRequestQueueBackend(resolved),
920
922
  backendCacheKey: storageBackend.getStorageBackendCacheKey?.() ?? storageBackend.constructor.name,
921
923
  });
922
- queue.proxyConfiguration = options.proxyConfiguration;
923
- queue.httpClient = options.httpClient;
924
+ queue.#proxyConfiguration = options.proxyConfiguration;
925
+ queue.#httpClient = options.httpClient;
924
926
  return queue;
925
927
  }
926
928
  }
@@ -80,55 +80,12 @@ export interface SitemapRequestLoaderOptions extends UrlConstraints {
80
80
  * The loading of the sitemap is performed in the background so that crawling can start before the sitemap is fully loaded.
81
81
  */
82
82
  export declare class SitemapRequestLoader implements IRequestLoader {
83
+ #private;
83
84
  /**
84
85
  * Set of URLs that were returned by `fetchNextRequest()` and not marked as handled yet.
85
86
  * @internal
86
87
  */
87
88
  inProgress: Set<string>;
88
- /**
89
- * Map of returned Request objects that have not been marked as handled yet.
90
- *
91
- * We use this to persist custom user fields on the in-progress requests.
92
- */
93
- private requestData;
94
- /**
95
- * Object for keeping track of the sitemap parsing progress.
96
- */
97
- private sitemapParsingProgress;
98
- /**
99
- * Object stream of URLs parsed from the sitemaps.
100
- * Using `highWaterMark`, this can manage the speed of the sitemap loading.
101
- *
102
- * Fetch the next URL to be processed using `fetchNextRequest()`.
103
- */
104
- private urlQueueStream;
105
- /**
106
- * Indicates whether the request list sitemap loading was aborted.
107
- *
108
- * If the loading was aborted before the sitemaps were fully loaded, the request list might be missing some URLs.
109
- * The `isSitemapFullyLoaded` method can be used to check if the sitemaps were fully loaded.
110
- *
111
- * If the loading is aborted and all the requests are handled, `isFinished()` will return `true`.
112
- */
113
- private abortLoading;
114
- /** Number of URLs that were marked as handled */
115
- private handledUrlCount;
116
- private persistStateKey?;
117
- private store?;
118
- private closed;
119
- /**
120
- * Proxy URL to be used for sitemap loading.
121
- */
122
- private proxyUrl?;
123
- /**
124
- * Logger instance.
125
- */
126
- private log;
127
- private urlExcludePatternObjects;
128
- private urlPatternObjects;
129
- /** EventManager used to handle persistence */
130
- private events;
131
- private persistenceOptions;
132
89
  /** @internal */
133
90
  private constructor();
134
91
  /**
@@ -25,11 +25,11 @@ export class SitemapRequestLoader {
25
25
  *
26
26
  * We use this to persist custom user fields on the in-progress requests.
27
27
  */
28
- requestData = new Map();
28
+ #requestData = new Map();
29
29
  /**
30
30
  * Object for keeping track of the sitemap parsing progress.
31
31
  */
32
- sitemapParsingProgress = {
32
+ #sitemapParsingProgress = {
33
33
  /**
34
34
  * URL of the sitemap that is currently being parsed. `null` if no sitemap is being parsed.
35
35
  */
@@ -49,7 +49,7 @@ export class SitemapRequestLoader {
49
49
  *
50
50
  * Fetch the next URL to be processed using `fetchNextRequest()`.
51
51
  */
52
- urlQueueStream;
52
+ #urlQueueStream;
53
53
  /**
54
54
  * Indicates whether the request list sitemap loading was aborted.
55
55
  *
@@ -58,25 +58,25 @@ export class SitemapRequestLoader {
58
58
  *
59
59
  * If the loading is aborted and all the requests are handled, `isFinished()` will return `true`.
60
60
  */
61
- abortLoading = false;
61
+ #abortLoading = false;
62
62
  /** Number of URLs that were marked as handled */
63
- handledUrlCount = 0;
64
- persistStateKey;
65
- store;
66
- closed = false;
63
+ #handledUrlCount = 0;
64
+ #persistStateKey;
65
+ #store;
66
+ #closed = false;
67
67
  /**
68
68
  * Proxy URL to be used for sitemap loading.
69
69
  */
70
- proxyUrl;
70
+ #proxyUrl;
71
71
  /**
72
72
  * Logger instance.
73
73
  */
74
- log;
75
- urlExcludePatternObjects = [];
76
- urlPatternObjects = [];
74
+ #log;
75
+ #urlExcludePatternObjects = [];
76
+ #urlPatternObjects = [];
77
77
  /** EventManager used to handle persistence */
78
- events;
79
- persistenceOptions;
78
+ #events;
79
+ #persistenceOptions;
80
80
  /** @internal */
81
81
  constructor(options) {
82
82
  const urlPatternValidator = ow.any(ow.string, ow.regExp, ow.object.hasKeys('glob'), ow.object.hasKeys('regexp'));
@@ -94,19 +94,19 @@ export class SitemapRequestLoader {
94
94
  httpClient: ow.optional.object,
95
95
  }));
96
96
  const { include, exclude } = options;
97
- this.log = serviceLocator.getLogger().child({ prefix: 'SitemapRequestLoader' });
97
+ this.#log = serviceLocator.getLogger().child({ prefix: 'SitemapRequestLoader' });
98
98
  if (exclude?.length) {
99
- this.urlExcludePatternObjects.push(...constructUrlPatternObjects(exclude));
99
+ this.#urlExcludePatternObjects.push(...constructUrlPatternObjects(exclude));
100
100
  }
101
101
  if (include?.length) {
102
- this.urlPatternObjects.push(...constructUrlPatternObjects(include));
102
+ this.#urlPatternObjects.push(...constructUrlPatternObjects(include));
103
103
  }
104
- this.persistStateKey = options.persistStateKey;
105
- this.persistenceOptions = { enable: true, ...options.persistenceOptions };
106
- this.proxyUrl = options.proxyUrl;
107
- this.urlQueueStream = this.createNewStream(options.maxBufferSize ?? 200);
108
- this.sitemapParsingProgress.pendingSitemapUrls = new Set(options.sitemapUrls);
109
- this.events = serviceLocator.getEventManager();
104
+ this.#persistStateKey = options.persistStateKey;
105
+ this.#persistenceOptions = { enable: true, ...options.persistenceOptions };
106
+ this.#proxyUrl = options.proxyUrl;
107
+ this.#urlQueueStream = this.createNewStream(options.maxBufferSize ?? 200);
108
+ this.#sitemapParsingProgress.pendingSitemapUrls = new Set(options.sitemapUrls);
109
+ this.#events = serviceLocator.getEventManager();
110
110
  this.persistState = this.persistState.bind(this);
111
111
  }
112
112
  /**
@@ -139,8 +139,8 @@ export class SitemapRequestLoader {
139
139
  * @returns `true` if the URL matches the patterns, `false` otherwise.
140
140
  */
141
141
  isUrlMatchingPatterns(url) {
142
- return (!this.urlExcludePatternObjects.some(this.matchesUrl(url)) &&
143
- (this.urlPatternObjects.length === 0 || this.urlPatternObjects.some(this.matchesUrl(url))));
142
+ return (!this.#urlExcludePatternObjects.some(this.matchesUrl(url)) &&
143
+ (this.#urlPatternObjects.length === 0 || this.#urlPatternObjects.some(this.matchesUrl(url))));
144
144
  }
145
145
  /**
146
146
  * Adds a URL to the queue of parsed URLs.
@@ -149,13 +149,13 @@ export class SitemapRequestLoader {
149
149
  */
150
150
  async pushNextUrl(url) {
151
151
  return new Promise((resolve) => {
152
- if (this.closed || (url && !this.isUrlMatchingPatterns(url))) {
152
+ if (this.#closed || (url && !this.isUrlMatchingPatterns(url))) {
153
153
  resolve();
154
154
  return;
155
155
  }
156
- if (!this.urlQueueStream.push(url)) {
156
+ if (!this.#urlQueueStream.push(url)) {
157
157
  // This doesn't work with the 'drain' event (it's not emitted for some reason).
158
- this.urlQueueStream.once('readdata', () => {
158
+ this.#urlQueueStream.once('readdata', () => {
159
159
  resolve();
160
160
  });
161
161
  }
@@ -172,21 +172,21 @@ export class SitemapRequestLoader {
172
172
  */
173
173
  async readNextUrl() {
174
174
  return new Promise((resolve) => {
175
- if (this.closed) {
175
+ if (this.#closed) {
176
176
  resolve(null);
177
177
  return;
178
178
  }
179
- const result = this.urlQueueStream.read();
179
+ const result = this.#urlQueueStream.read();
180
180
  if (!result && !this.isSitemapFullyLoaded()) {
181
- this.urlQueueStream.once('readable', () => {
182
- const nextUrl = this.urlQueueStream.read();
181
+ this.#urlQueueStream.once('readable', () => {
182
+ const nextUrl = this.#urlQueueStream.read();
183
183
  resolve(nextUrl);
184
184
  });
185
185
  }
186
186
  else {
187
187
  resolve(result);
188
188
  }
189
- this.urlQueueStream.emit('readdata');
189
+ this.#urlQueueStream.emit('readdata');
190
190
  });
191
191
  }
192
192
  /**
@@ -195,8 +195,8 @@ export class SitemapRequestLoader {
195
195
  * If this is `false`, the background processing is either still in progress or was aborted.
196
196
  */
197
197
  isSitemapFullyLoaded() {
198
- return (this.sitemapParsingProgress.inProgressSitemapUrl === null &&
199
- this.sitemapParsingProgress.pendingSitemapUrls.size === 0);
198
+ return (this.#sitemapParsingProgress.inProgressSitemapUrl === null &&
199
+ this.#sitemapParsingProgress.pendingSitemapUrls.size === 0);
200
200
  }
201
201
  /**
202
202
  * Start processing the sitemaps and loading the URLs.
@@ -204,34 +204,34 @@ export class SitemapRequestLoader {
204
204
  * Resolves once all the sitemaps URLs have been fully loaded (sets `isSitemapFullyLoaded` to `true`).
205
205
  */
206
206
  async load({ parseSitemapOptions, }) {
207
- while (!this.isSitemapFullyLoaded() && !this.abortLoading) {
208
- const sitemapUrl = this.sitemapParsingProgress.inProgressSitemapUrl ??
209
- this.sitemapParsingProgress.pendingSitemapUrls.values().next().value;
207
+ while (!this.isSitemapFullyLoaded() && !this.#abortLoading) {
208
+ const sitemapUrl = this.#sitemapParsingProgress.inProgressSitemapUrl ??
209
+ this.#sitemapParsingProgress.pendingSitemapUrls.values().next().value;
210
210
  try {
211
- for await (const item of parseSitemap([{ type: 'url', url: sitemapUrl }], this.proxyUrl, {
211
+ for await (const item of parseSitemap([{ type: 'url', url: sitemapUrl }], this.#proxyUrl, {
212
212
  ...parseSitemapOptions,
213
213
  maxDepth: 0,
214
214
  emitNestedSitemaps: true,
215
215
  })) {
216
216
  if (!item.originSitemapUrl) {
217
217
  // This is a nested sitemap
218
- this.sitemapParsingProgress.pendingSitemapUrls.add(item.loc);
218
+ this.#sitemapParsingProgress.pendingSitemapUrls.add(item.loc);
219
219
  continue;
220
220
  }
221
- if (!this.sitemapParsingProgress.inProgressEntries.has(item.loc)) {
221
+ if (!this.#sitemapParsingProgress.inProgressEntries.has(item.loc)) {
222
222
  await this.pushNextUrl(item.loc);
223
- this.sitemapParsingProgress.inProgressEntries.add(item.loc);
223
+ this.#sitemapParsingProgress.inProgressEntries.add(item.loc);
224
224
  }
225
225
  }
226
226
  }
227
227
  catch (e) {
228
- this.log.error('Error loading sitemap contents:', e);
228
+ this.#log.error('Error loading sitemap contents:', e);
229
229
  }
230
- this.sitemapParsingProgress.pendingSitemapUrls.delete(sitemapUrl);
231
- this.sitemapParsingProgress.inProgressEntries.clear();
232
- this.sitemapParsingProgress.inProgressSitemapUrl = null;
230
+ this.#sitemapParsingProgress.pendingSitemapUrls.delete(sitemapUrl);
231
+ this.#sitemapParsingProgress.inProgressEntries.clear();
232
+ this.#sitemapParsingProgress.inProgressSitemapUrl = null;
233
233
  }
234
- this.urlQueueStream.end();
234
+ this.#urlQueueStream.end();
235
235
  }
236
236
  /**
237
237
  * Open a sitemap and start processing it.
@@ -250,15 +250,15 @@ export class SitemapRequestLoader {
250
250
  void requestList.load({
251
251
  parseSitemapOptions: { logger: serviceLocator.getLogger(), ...options.parseSitemapOptions, httpClient },
252
252
  });
253
- if (requestList.persistenceOptions.enable) {
254
- requestList.events.on("persistState" /* EventType.PERSIST_STATE */, requestList.persistState);
253
+ if (requestList.#persistenceOptions.enable) {
254
+ requestList.#events.on("persistState" /* EventType.PERSIST_STATE */, requestList.persistState);
255
255
  }
256
256
  options?.signal?.addEventListener('abort', () => {
257
- requestList.abortLoading = true;
257
+ requestList.#abortLoading = true;
258
258
  });
259
259
  if (options.timeoutMillis) {
260
260
  setTimeout(() => {
261
- requestList.abortLoading = true;
261
+ requestList.#abortLoading = true;
262
262
  }, options.timeoutMillis);
263
263
  }
264
264
  return requestList;
@@ -269,14 +269,14 @@ export class SitemapRequestLoader {
269
269
  async getTotalCount() {
270
270
  // Total known so far = not-yet-fetched (still buffered in the stream) + in-progress (fetched but not
271
271
  // yet handled) + already handled.
272
- return this.urlQueueStream.readableLength + this.inProgress.size + this.handledUrlCount;
272
+ return this.#urlQueueStream.readableLength + this.inProgress.size + this.#handledUrlCount;
273
273
  }
274
274
  /**
275
275
  * @inheritDoc
276
276
  */
277
277
  async getPendingCount() {
278
278
  // Pending = everything not yet handled = not-yet-fetched + in-progress.
279
- return this.urlQueueStream.readableLength + this.inProgress.size;
279
+ return this.#urlQueueStream.readableLength + this.inProgress.size;
280
280
  }
281
281
  /**
282
282
  * Combines this list with a request manager (a {@link RequestQueue} by default) into a
@@ -293,31 +293,31 @@ export class SitemapRequestLoader {
293
293
  * @inheritDoc
294
294
  */
295
295
  async isFinished() {
296
- return ((await this.isEmpty()) && this.inProgress.size === 0 && (this.isSitemapFullyLoaded() || this.abortLoading));
296
+ return ((await this.isEmpty()) && this.inProgress.size === 0 && (this.isSitemapFullyLoaded() || this.#abortLoading));
297
297
  }
298
298
  /**
299
299
  * @inheritDoc
300
300
  */
301
301
  async isEmpty() {
302
- return this.urlQueueStream.readableLength === 0;
302
+ return this.#urlQueueStream.readableLength === 0;
303
303
  }
304
304
  /**
305
305
  * @inheritDoc
306
306
  */
307
307
  async getHandledCount() {
308
- return this.handledUrlCount;
308
+ return this.#handledUrlCount;
309
309
  }
310
310
  /**
311
311
  * @inheritDoc
312
312
  */
313
313
  async persistState() {
314
- if (this.persistStateKey === undefined) {
314
+ if (this.#persistStateKey === undefined) {
315
315
  return;
316
316
  }
317
- this.store ??= await KeyValueStore.open();
317
+ this.#store ??= await KeyValueStore.open();
318
318
  const urlQueue = [];
319
- while (this.urlQueueStream.readableLength > 0) {
320
- const url = this.urlQueueStream.read();
319
+ while (this.#urlQueueStream.readableLength > 0) {
320
+ const url = this.#urlQueueStream.read();
321
321
  if (url === null) {
322
322
  break;
323
323
  }
@@ -325,48 +325,48 @@ export class SitemapRequestLoader {
325
325
  }
326
326
  // Create a new stream, as we have read all the URLs from the current one.
327
327
  // Pushing the urls back to the original stream might not be possible if it has been ended.
328
- const newStream = this.createNewStream(this.urlQueueStream.readableHighWaterMark);
328
+ const newStream = this.createNewStream(this.#urlQueueStream.readableHighWaterMark);
329
329
  for (const url of urlQueue) {
330
330
  newStream.push(url);
331
331
  }
332
- if (this.urlQueueStream.writableEnded) {
332
+ if (this.#urlQueueStream.writableEnded) {
333
333
  newStream.end();
334
334
  }
335
- this.urlQueueStream = newStream;
336
- await this.store.setValue(this.persistStateKey, {
335
+ this.#urlQueueStream = newStream;
336
+ await this.#store.setValue(this.#persistStateKey, {
337
337
  sitemapParsingProgress: {
338
- pendingSitemapUrls: Array.from(this.sitemapParsingProgress.pendingSitemapUrls),
339
- inProgressSitemapUrl: this.sitemapParsingProgress.inProgressSitemapUrl,
340
- inProgressEntries: Array.from(this.sitemapParsingProgress.inProgressEntries),
338
+ pendingSitemapUrls: Array.from(this.#sitemapParsingProgress.pendingSitemapUrls),
339
+ inProgressSitemapUrl: this.#sitemapParsingProgress.inProgressSitemapUrl,
340
+ inProgressEntries: Array.from(this.#sitemapParsingProgress.inProgressEntries),
341
341
  },
342
342
  // Re-queue in-progress requests to the front so they are retried if the state is restored.
343
343
  urlQueue: [...this.inProgress, ...urlQueue],
344
- requestData: Array.from(this.requestData.entries()),
345
- abortLoading: this.abortLoading,
346
- closed: this.closed,
344
+ requestData: Array.from(this.#requestData.entries()),
345
+ abortLoading: this.#abortLoading,
346
+ closed: this.#closed,
347
347
  });
348
348
  }
349
349
  async restoreState() {
350
350
  await purgeDefaultStorages({ onlyPurgeOnce: true });
351
- if (this.persistStateKey === undefined) {
351
+ if (this.#persistStateKey === undefined) {
352
352
  return;
353
353
  }
354
- this.store ??= await KeyValueStore.open();
355
- const state = await this.store.getValue(this.persistStateKey);
354
+ this.#store ??= await KeyValueStore.open();
355
+ const state = await this.#store.getValue(this.#persistStateKey);
356
356
  if (state === null) {
357
357
  return;
358
358
  }
359
- this.sitemapParsingProgress = {
359
+ this.#sitemapParsingProgress = {
360
360
  pendingSitemapUrls: new Set(state.sitemapParsingProgress.pendingSitemapUrls),
361
361
  inProgressSitemapUrl: state.sitemapParsingProgress.inProgressSitemapUrl,
362
362
  inProgressEntries: new Set(state.sitemapParsingProgress.inProgressEntries),
363
363
  };
364
- this.requestData = new Map(state.requestData ?? []);
364
+ this.#requestData = new Map(state.requestData ?? []);
365
365
  for (const url of state.urlQueue) {
366
- this.urlQueueStream.push(url);
366
+ this.#urlQueueStream.push(url);
367
367
  }
368
- this.abortLoading = state.abortLoading;
369
- this.closed = state.closed;
368
+ this.#abortLoading = state.abortLoading;
369
+ this.#closed = state.closed;
370
370
  }
371
371
  /**
372
372
  * @inheritDoc
@@ -377,11 +377,11 @@ export class SitemapRequestLoader {
377
377
  return null;
378
378
  }
379
379
  // A restored in-progress request already has its Request data; don't overwrite it.
380
- if (!this.requestData.has(nextUrl)) {
381
- this.requestData.set(nextUrl, new Request({ url: nextUrl }));
380
+ if (!this.#requestData.has(nextUrl)) {
381
+ this.#requestData.set(nextUrl, new Request({ url: nextUrl }));
382
382
  }
383
383
  this.inProgress.add(nextUrl);
384
- return this.requestData.get(nextUrl);
384
+ return this.#requestData.get(nextUrl);
385
385
  }
386
386
  /**
387
387
  * @inheritDoc
@@ -400,20 +400,20 @@ export class SitemapRequestLoader {
400
400
  * Calling `fetchNextRequest()` after this method will always return `null`.
401
401
  */
402
402
  async teardown() {
403
- this.closed = true;
404
- this.abortLoading = true;
405
- this.events.off("persistState" /* EventType.PERSIST_STATE */, this.persistState);
403
+ this.#closed = true;
404
+ this.#abortLoading = true;
405
+ this.#events.off("persistState" /* EventType.PERSIST_STATE */, this.persistState);
406
406
  await this.persistState();
407
- this.urlQueueStream.emit('readdata'); // unblocks the potentially waiting `pushNextUrl` call
407
+ this.#urlQueueStream.emit('readdata'); // unblocks the potentially waiting `pushNextUrl` call
408
408
  }
409
409
  /**
410
410
  * @inheritDoc
411
411
  */
412
412
  async markRequestAsHandled(request) {
413
- this.handledUrlCount += 1;
413
+ this.#handledUrlCount += 1;
414
414
  this.ensureInProgress(request.url);
415
415
  this.inProgress.delete(request.url);
416
- this.requestData.delete(request.url);
416
+ this.#requestData.delete(request.url);
417
417
  }
418
418
  ensureInProgress(url) {
419
419
  if (!this.inProgress.has(url)) {