@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
@@ -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)) {
@@ -19,8 +19,7 @@ type Hashable = string;
19
19
  * assigns a reserved default alias.
20
20
  */
21
21
  export declare class StorageInstanceManager {
22
- private readonly cache;
23
- private readonly openerLocks;
22
+ #private;
24
23
  /**
25
24
  * Open (or retrieve from cache) a storage instance.
26
25
  *
@@ -120,8 +120,8 @@ class StorageCache {
120
120
  * assigns a reserved default alias.
121
121
  */
122
122
  export class StorageInstanceManager {
123
- cache = new StorageCache();
124
- openerLocks = new Map();
123
+ #cache = new StorageCache();
124
+ #openerLocks = new Map();
125
125
  /**
126
126
  * Open (or retrieve from cache) a storage instance.
127
127
  *
@@ -142,46 +142,46 @@ export class StorageInstanceManager {
142
142
  }
143
143
  // Fast-path cache check (no lock).
144
144
  if (alias !== undefined) {
145
- const cached = this.cache.get(cls, { alias, backendCacheKey });
145
+ const cached = this.#cache.get(cls, { alias, backendCacheKey });
146
146
  if (cached)
147
147
  return cached;
148
148
  }
149
149
  else if (id) {
150
- const cached = this.cache.get(cls, { id, backendCacheKey });
150
+ const cached = this.#cache.get(cls, { id, backendCacheKey });
151
151
  if (cached)
152
152
  return cached;
153
153
  }
154
154
  else if (name) {
155
- const cached = this.cache.get(cls, { name, backendCacheKey });
155
+ const cached = this.#cache.get(cls, { name, backendCacheKey });
156
156
  if (cached)
157
157
  return cached;
158
158
  }
159
159
  const identifierKey = id ?? name ?? alias ?? DEFAULT_STORAGE_ALIAS;
160
160
  const lockKey = `${cls.name}:${identifierKey}:${backendCacheKey}`;
161
- if (!this.openerLocks.has(lockKey)) {
162
- this.openerLocks.set(lockKey, new AsyncQueue());
161
+ if (!this.#openerLocks.has(lockKey)) {
162
+ this.#openerLocks.set(lockKey, new AsyncQueue());
163
163
  }
164
- const queue = this.openerLocks.get(lockKey);
164
+ const queue = this.#openerLocks.get(lockKey);
165
165
  await queue.wait();
166
166
  try {
167
167
  // Double-check cache under lock (another caller may have filled it while we waited).
168
168
  if (alias !== undefined) {
169
- const cached = this.cache.get(cls, { alias, backendCacheKey });
169
+ const cached = this.#cache.get(cls, { alias, backendCacheKey });
170
170
  if (cached)
171
171
  return cached;
172
172
  }
173
173
  else if (id) {
174
- const cached = this.cache.get(cls, { id, backendCacheKey });
174
+ const cached = this.#cache.get(cls, { id, backendCacheKey });
175
175
  if (cached)
176
176
  return cached;
177
177
  }
178
178
  else if (name) {
179
- const cached = this.cache.get(cls, { name, backendCacheKey });
179
+ const cached = this.#cache.get(cls, { name, backendCacheKey });
180
180
  if (cached)
181
181
  return cached;
182
182
  }
183
183
  // Prevent the same string from being used as both a name and an alias.
184
- this.cache.checkNameAliasConflict(cls, { name, alias, backendCacheKey });
184
+ this.#cache.checkNameAliasConflict(cls, { name, alias, backendCacheKey });
185
185
  // Cache miss — create the sub-backend and storage instance.
186
186
  const subBackend = await backendOpener();
187
187
  const storageInfo = await subBackend.getMetadata();
@@ -189,7 +189,7 @@ export class StorageInstanceManager {
189
189
  // we just fetched (so `id`/`name` etc. are available synchronously) along with the backend.
190
190
  const instance = new cls({ metadata: storageInfo, backend: subBackend });
191
191
  // Atomic cache writes (no awaits between these).
192
- this.cache.set(cls, instance, backendCacheKey, alias);
192
+ this.#cache.set(cls, instance, backendCacheKey, alias);
193
193
  return instance;
194
194
  }
195
195
  finally {
@@ -197,7 +197,7 @@ export class StorageInstanceManager {
197
197
  // Clean up idle locks so the map doesn't grow unboundedly
198
198
  // (mirrors crawlee-python's WeakValueDictionary behaviour).
199
199
  if (queue.remaining === 0) {
200
- this.openerLocks.delete(lockKey);
200
+ this.#openerLocks.delete(lockKey);
201
201
  }
202
202
  }
203
203
  }
@@ -205,7 +205,7 @@ export class StorageInstanceManager {
205
205
  * Remove a storage instance from the cache (called from `storage.drop()`).
206
206
  */
207
207
  removeFromCache(instance) {
208
- this.cache.removeFromCache(instance);
208
+ this.#cache.removeFromCache(instance);
209
209
  }
210
210
  /**
211
211
  * Clear the entire cache. Also calls `clearCache()` on any cached KeyValueStore
@@ -213,12 +213,12 @@ export class StorageInstanceManager {
213
213
  * Called during service locator reset.
214
214
  */
215
215
  clearCache() {
216
- for (const instance of this.cache.allValues()) {
216
+ for (const instance of this.#cache.allValues()) {
217
217
  if ('clearCache' in instance && typeof instance.clearCache === 'function') {
218
218
  instance.clearCache();
219
219
  }
220
220
  }
221
- this.cache.clear();
221
+ this.#cache.clear();
222
222
  }
223
223
  }
224
224
  /**
@@ -39,7 +39,7 @@ export interface RequestQueueStats {
39
39
  * the buckets that make sense for it.
40
40
  */
41
41
  export declare class StorageStatsTracker<T extends Record<keyof T, number>> {
42
- private readonly counters;
42
+ #private;
43
43
  constructor(initial: T);
44
44
  /** Increment a counter bucket by `by` (default `1`). */
45
45
  add(key: keyof T, by?: number): void;
@@ -14,16 +14,16 @@
14
14
  * the buckets that make sense for it.
15
15
  */
16
16
  export class StorageStatsTracker {
17
- counters;
17
+ #counters;
18
18
  constructor(initial) {
19
- this.counters = { ...initial };
19
+ this.#counters = { ...initial };
20
20
  }
21
21
  /** Increment a counter bucket by `by` (default `1`). */
22
22
  add(key, by = 1) {
23
- this.counters[key] += by;
23
+ this.#counters[key] += by;
24
24
  }
25
25
  /** Return a snapshot of the current counters. The returned object is a copy and safe to keep. */
26
26
  get current() {
27
- return { ...this.counters };
27
+ return { ...this.#counters };
28
28
  }
29
29
  }