@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
@@ -15,92 +15,91 @@ const CRITICAL_OVERLOAD_RATE_LIMIT_MILLIS = 10_000;
15
15
  export class MemoryLoadSignal {
16
16
  name = 'memInfo';
17
17
  overloadedRatio;
18
- store = new SnapshotStore();
19
- maxUsedRatio;
18
+ #store = new SnapshotStore();
19
+ #maxUsedRatio;
20
20
  /** All resolved in `start()`, before anything that reads them can fire. */
21
- config;
22
- log;
23
- maxMemoryBytes;
24
- events;
25
- maxMemoryRatio;
26
- lastLoggedCriticalMemoryOverloadAt = null;
21
+ #config;
22
+ #log;
23
+ #maxMemoryBytes;
24
+ #events;
25
+ #maxMemoryRatio;
26
+ #lastLoggedCriticalMemoryOverloadAt = null;
27
27
  constructor(options = {}) {
28
- this.maxUsedRatio = options.maxUsedRatio ?? 0.9;
28
+ this.#maxUsedRatio = options.maxUsedRatio ?? 0.9;
29
29
  this.overloadedRatio = options.overloadedRatio ?? 0.2;
30
30
  this.handle = this.handle.bind(this);
31
31
  }
32
32
  async start(context) {
33
- this.store.useSampleWindow(context.maxSampleWindowMillis);
33
+ this.#store.useSampleWindow(context.maxSampleWindowMillis);
34
34
  // A new session starts from a clean slate, so it is not judged on measurements from before the downtime.
35
- this.store.clear();
35
+ this.#store.clear();
36
36
  // Resolved here rather than in the constructor: an instance built ahead of time (to be wrapped, or shared
37
37
  // between systems) must not capture whichever services happened to be registered at that moment.
38
- this.config = serviceLocator.getConfiguration();
39
- this.events = serviceLocator.getEventManager();
40
- this.log = serviceLocator.getLogger().child({ prefix: 'MemoryLoadSignal' });
41
- const memoryMbytes = this.config.memoryMbytes ?? 0;
38
+ this.#config = serviceLocator.getConfiguration();
39
+ this.#events = serviceLocator.getEventManager();
40
+ this.#log = serviceLocator.getLogger().child({ prefix: 'MemoryLoadSignal' });
41
+ const memoryMbytes = this.#config.memoryMbytes ?? 0;
42
42
  if (memoryMbytes > 0) {
43
- this.maxMemoryBytes = memoryMbytes * 1024 * 1024;
43
+ this.#maxMemoryBytes = memoryMbytes * 1024 * 1024;
44
44
  }
45
45
  else {
46
- this.maxMemoryRatio = this.config.availableMemoryRatio;
47
- if (!this.maxMemoryRatio) {
46
+ this.#maxMemoryRatio = this.#config.availableMemoryRatio;
47
+ if (!this.#maxMemoryRatio) {
48
48
  throw new Error('availableMemoryRatio is not set in configuration.');
49
49
  }
50
50
  else {
51
- this.log.debug(`Setting max memory of this run to ${this.maxMemoryRatio * 100} % of available memory. ` +
51
+ this.#log.debug(`Setting max memory of this run to ${this.#maxMemoryRatio * 100} % of available memory. ` +
52
52
  'Use the CRAWLEE_MEMORY_MBYTES or CRAWLEE_AVAILABLE_MEMORY_RATIO environment variable to override it.');
53
53
  }
54
54
  // Fallback memory measurement in case memTotalBytes is missing from SystemInfo.
55
- this.maxMemoryBytes = await this._getTotalMemoryBytes();
55
+ this.#maxMemoryBytes = await this.getTotalMemoryBytes();
56
56
  }
57
- this.events.on("systemInfo" /* EventType.SYSTEM_INFO */, this.handle);
57
+ this.#events.on("systemInfo" /* EventType.SYSTEM_INFO */, this.handle);
58
58
  }
59
59
  async stop() {
60
- this.events?.off("systemInfo" /* EventType.SYSTEM_INFO */, this.handle);
61
- this.events = undefined;
60
+ this.#events?.off("systemInfo" /* EventType.SYSTEM_INFO */, this.handle);
61
+ this.#events = undefined;
62
62
  }
63
63
  getSample(sampleDurationMillis) {
64
- return this.store.getSample(sampleDurationMillis);
64
+ return this.#store.getSample(sampleDurationMillis);
65
65
  }
66
66
  /** @internal Records a snapshot from a `SYSTEM_INFO` payload. Exposed for tests. */
67
67
  handle(systemInfo) {
68
68
  const createdAt = systemInfo.createdAt ? new Date(systemInfo.createdAt) : new Date();
69
69
  const { memCurrentBytes, memTotalBytes } = systemInfo;
70
- let maxMemoryBytes = this.maxMemoryBytes;
71
- if (this.maxMemoryRatio !== undefined && this.maxMemoryRatio > 0) {
72
- maxMemoryBytes = this.maxMemoryRatio * (memTotalBytes ?? this.maxMemoryBytes);
70
+ let maxMemoryBytes = this.#maxMemoryBytes;
71
+ if (this.#maxMemoryRatio !== undefined && this.#maxMemoryRatio > 0) {
72
+ maxMemoryBytes = this.#maxMemoryRatio * (memTotalBytes ?? this.#maxMemoryBytes);
73
73
  }
74
74
  const snapshot = {
75
75
  createdAt,
76
- isOverloaded: memCurrentBytes / maxMemoryBytes > this.maxUsedRatio,
76
+ isOverloaded: memCurrentBytes / maxMemoryBytes > this.#maxUsedRatio,
77
77
  usedBytes: memCurrentBytes,
78
78
  };
79
- this.store.push(snapshot, createdAt);
80
- this._memoryOverloadWarning(systemInfo, maxMemoryBytes);
79
+ this.#store.push(snapshot, createdAt);
80
+ this.memoryOverloadWarning(systemInfo, maxMemoryBytes);
81
81
  }
82
- /** @internal */
83
- _memoryOverloadWarning(systemInfo, maxMemoryBytes) {
84
- const effectiveMax = maxMemoryBytes ?? this.maxMemoryBytes;
82
+ memoryOverloadWarning(systemInfo, maxMemoryBytes) {
83
+ const effectiveMax = maxMemoryBytes ?? this.#maxMemoryBytes;
85
84
  const { memCurrentBytes } = systemInfo;
86
85
  const createdAt = systemInfo.createdAt ? new Date(systemInfo.createdAt) : new Date();
87
- if (this.lastLoggedCriticalMemoryOverloadAt &&
88
- +createdAt < +this.lastLoggedCriticalMemoryOverloadAt + CRITICAL_OVERLOAD_RATE_LIMIT_MILLIS)
86
+ if (this.#lastLoggedCriticalMemoryOverloadAt &&
87
+ +createdAt < +this.#lastLoggedCriticalMemoryOverloadAt + CRITICAL_OVERLOAD_RATE_LIMIT_MILLIS)
89
88
  return;
90
- const maxDesiredMemoryBytes = this.maxUsedRatio * effectiveMax;
91
- const reserveMemory = effectiveMax * (1 - this.maxUsedRatio) * RESERVE_MEMORY_RATIO;
89
+ const maxDesiredMemoryBytes = this.#maxUsedRatio * effectiveMax;
90
+ const reserveMemory = effectiveMax * (1 - this.#maxUsedRatio) * RESERVE_MEMORY_RATIO;
92
91
  const criticalOverloadBytes = maxDesiredMemoryBytes + reserveMemory;
93
92
  const isCriticalOverload = memCurrentBytes > criticalOverloadBytes;
94
93
  if (isCriticalOverload) {
95
94
  const usedPercentage = Math.round((memCurrentBytes / effectiveMax) * 100);
96
95
  const toMb = (bytes) => Math.round(bytes / 1024 ** 2);
97
- this.log.warning('Memory is critically overloaded. ' +
96
+ this.#log.warning('Memory is critically overloaded. ' +
98
97
  `Using ${toMb(memCurrentBytes)} MB of ${toMb(effectiveMax)} MB (${usedPercentage}%). Consider increasing available memory.`);
99
- this.lastLoggedCriticalMemoryOverloadAt = createdAt;
98
+ this.#lastLoggedCriticalMemoryOverloadAt = createdAt;
100
99
  }
101
100
  }
102
- async _getTotalMemoryBytes() {
103
- const containerized = this.config.containerized ?? (await isContainerized());
101
+ async getTotalMemoryBytes() {
102
+ const containerized = this.#config.containerized ?? (await isContainerized());
104
103
  return (await getMemoryInfo({ containerized, logger: serviceLocator.getLogger() })).totalBytes;
105
104
  }
106
105
  }
@@ -61,10 +61,7 @@ export type SnapshotterOptions = Omit<LoadSignalsOptions, 'custom'>;
61
61
  * @internal
62
62
  */
63
63
  export declare class Snapshotter {
64
- private readonly memorySignal?;
65
- private readonly eventLoopSignal?;
66
- private readonly cpuSignal?;
67
- private readonly clientSignal?;
64
+ #private;
68
65
  /**
69
66
  * Returns the enabled built-in signals, so `SystemStatus` can iterate them alongside any custom `LoadSignal`
70
67
  * instances. Signals switched off through the options are simply absent — the system status reports them as
@@ -13,10 +13,10 @@ import { MemoryLoadSignal } from './memory_load_signal.js';
13
13
  */
14
14
  export class Snapshotter {
15
15
  // Absent when switched off through the corresponding option (e.g. `client: false`).
16
- memorySignal;
17
- eventLoopSignal;
18
- cpuSignal;
19
- clientSignal;
16
+ #memorySignal;
17
+ #eventLoopSignal;
18
+ #cpuSignal;
19
+ #clientSignal;
20
20
  /**
21
21
  * Returns the enabled built-in signals, so `SystemStatus` can iterate them alongside any custom `LoadSignal`
22
22
  * instances. Signals switched off through the options are simply absent — the system status reports them as
@@ -24,10 +24,10 @@ export class Snapshotter {
24
24
  */
25
25
  getLoadSignals() {
26
26
  const builtin = [
27
- this.memorySignal,
28
- this.eventLoopSignal,
29
- this.cpuSignal,
30
- this.clientSignal,
27
+ this.#memorySignal,
28
+ this.#eventLoopSignal,
29
+ this.#cpuSignal,
30
+ this.#clientSignal,
31
31
  ];
32
32
  return builtin.filter((signal) => signal !== undefined);
33
33
  }
@@ -39,13 +39,13 @@ export class Snapshotter {
39
39
  // Each signal resolves its own ambient dependencies when started, and is told the window it will be sampled
40
40
  // over then too - so there is nothing to thread in here beyond the caller's tuning.
41
41
  if (memory !== false)
42
- this.memorySignal = new MemoryLoadSignal(memory);
42
+ this.#memorySignal = new MemoryLoadSignal(memory);
43
43
  if (eventLoop !== false)
44
- this.eventLoopSignal = new EventLoopLoadSignal(eventLoop);
44
+ this.#eventLoopSignal = new EventLoopLoadSignal(eventLoop);
45
45
  if (cpu !== false)
46
- this.cpuSignal = new CpuLoadSignal(cpu);
46
+ this.#cpuSignal = new CpuLoadSignal(cpu);
47
47
  if (client !== false)
48
- this.clientSignal = new ClientLoadSignal(client);
48
+ this.#clientSignal = new ClientLoadSignal(client);
49
49
  }
50
50
  /**
51
51
  * Starts capturing snapshots at configured intervals. The `context` carries the sample window the signals will
@@ -105,9 +105,7 @@ export interface FinalStatistics {
105
105
  * @internal
106
106
  */
107
107
  export declare class SystemStatus {
108
- private readonly currentHistoryMillis;
109
- private readonly historyMillis;
110
- private readonly signals;
108
+ #private;
111
109
  constructor(options: SystemStatusOptions);
112
110
  /**
113
111
  * The widest window any signal will be queried with, and therefore exactly how much history the signals are asked
@@ -32,14 +32,14 @@ const BUILTIN_SIGNAL_NAMES = new Set(Object.keys(BUILTIN_SIGNAL_OPTION_KEYS));
32
32
  * @internal
33
33
  */
34
34
  export class SystemStatus {
35
- currentHistoryMillis;
36
- historyMillis;
37
- signals;
35
+ #currentHistoryMillis;
36
+ #historyMillis;
37
+ #signals;
38
38
  constructor(options) {
39
39
  const { currentHistorySecs = DEFAULT_CURRENT_HISTORY_SECS, historySecs = DEFAULT_SNAPSHOT_HISTORY_SECS, snapshotter, loadSignals = [], } = options;
40
- this.currentHistoryMillis = currentHistorySecs * 1000;
41
- this.historyMillis = historySecs * 1000;
42
- this.signals = [...snapshotter.getLoadSignals(), ...loadSignals];
40
+ this.#currentHistoryMillis = currentHistorySecs * 1000;
41
+ this.#historyMillis = historySecs * 1000;
42
+ this.#signals = [...snapshotter.getLoadSignals(), ...loadSignals];
43
43
  this.assertUniqueSignalNames();
44
44
  }
45
45
  /**
@@ -48,7 +48,7 @@ export class SystemStatus {
48
48
  * defaults.
49
49
  */
50
50
  get maxSampleWindowMillis() {
51
- return Math.max(this.currentHistoryMillis, this.historyMillis);
51
+ return Math.max(this.#currentHistoryMillis, this.#historyMillis);
52
52
  }
53
53
  /**
54
54
  * Signal names are the keys of the reported {@link SystemInfo}, so a duplicate would leave a status object that
@@ -57,7 +57,7 @@ export class SystemStatus {
57
57
  */
58
58
  assertUniqueSignalNames() {
59
59
  const seen = new Set();
60
- for (const { name } of this.signals) {
60
+ for (const { name } of this.#signals) {
61
61
  if (!seen.has(name)) {
62
62
  seen.add(name);
63
63
  continue;
@@ -85,7 +85,7 @@ export class SystemStatus {
85
85
  * and `true` otherwise.
86
86
  */
87
87
  getCurrentStatus() {
88
- return this.isSystemIdle(this.currentHistoryMillis);
88
+ return this.isSystemIdle(this.#currentHistoryMillis);
89
89
  }
90
90
  /**
91
91
  * Returns an {@link SystemInfo} object with the following structure:
@@ -103,7 +103,7 @@ export class SystemStatus {
103
103
  * `historySecs` seconds and `true` otherwise.
104
104
  */
105
105
  getHistoricalStatus() {
106
- return this.isSystemIdle(this.historyMillis);
106
+ return this.isSystemIdle(this.#historyMillis);
107
107
  }
108
108
  /**
109
109
  * Returns a system status object.
@@ -117,7 +117,7 @@ export class SystemStatus {
117
117
  clientInfo: { isOverloaded: false, limitRatio: 0, actualRatio: 0 },
118
118
  };
119
119
  let loadSignalInfo;
120
- for (const signal of this.signals) {
120
+ for (const signal of this.#signals) {
121
121
  const sample = signal.getSample(sampleDurationMillis);
122
122
  const info = evaluateLoadSignalSample(sample, signal.overloadedRatio);
123
123
  if (info.isOverloaded) {
@@ -123,12 +123,12 @@ export interface Configuration extends ResolvedConfigValues {
123
123
  * `containerized` | `CRAWLEE_CONTAINERIZED` | -
124
124
  */
125
125
  export declare class Configuration {
126
+ #private;
126
127
  /**
127
128
  * Field definitions for this configuration class.
128
129
  * Subclasses override this to register additional fields.
129
130
  */
130
131
  protected static fields: Record<string, ConfigField>;
131
- private resolvedValues;
132
132
  /**
133
133
  * Creates new `Configuration` instance with provided options.
134
134
  * Constructor options take precedence over environment variables, which take precedence
package/configuration.js CHANGED
@@ -147,7 +147,7 @@ export class Configuration {
147
147
  * Subclasses override this to register additional fields.
148
148
  */
149
149
  static fields = crawleeConfigFields;
150
- resolvedValues;
150
+ #resolvedValues;
151
151
  /**
152
152
  * Creates new `Configuration` instance with provided options.
153
153
  * Constructor options take precedence over environment variables, which take precedence
@@ -156,7 +156,7 @@ export class Configuration {
156
156
  constructor(options = {}) {
157
157
  const fields = this.constructor.fields;
158
158
  const fileOptions = Configuration.loadFileOptions();
159
- this.resolvedValues = Configuration.resolveAll(fields, options, fileOptions);
159
+ this.#resolvedValues = Configuration.resolveAll(fields, options, fileOptions);
160
160
  this.registerAccessors();
161
161
  // Set the log level
162
162
  const logLevel = this.logLevel;
@@ -209,7 +209,7 @@ export class Configuration {
209
209
  const descriptors = {};
210
210
  for (const key of Object.keys(fields)) {
211
211
  descriptors[key] = {
212
- get: () => this.resolvedValues[key],
212
+ get: () => this.#resolvedValues[key],
213
213
  set() {
214
214
  throw new TypeError('Configuration is immutable. Pass options via the constructor instead.');
215
215
  },
@@ -26,12 +26,12 @@ export class ContextPipeline {
26
26
  * properties from the `ContextPipeline` interface, making type checking more reliable.
27
27
  */
28
28
  class ContextPipelineImpl extends ContextPipeline {
29
- middleware;
30
- parent;
29
+ #middleware;
30
+ #parent;
31
31
  constructor(middleware, parent) {
32
32
  super();
33
- this.middleware = middleware;
34
- this.parent = parent;
33
+ this.#middleware = middleware;
34
+ this.#parent = parent;
35
35
  }
36
36
  /**
37
37
  * @inheritdoc
@@ -50,8 +50,8 @@ class ContextPipelineImpl extends ContextPipeline {
50
50
  *middlewareChain() {
51
51
  let step = this;
52
52
  while (step !== undefined) {
53
- yield step.middleware;
54
- step = step.parent;
53
+ yield step.#middleware;
54
+ step = step.#parent;
55
55
  }
56
56
  }
57
57
  /**
@@ -1,12 +1,11 @@
1
1
  import type { Dictionary, HttpRequestOptions, ISession, ProxyInfo, SendRequestOptions } from '@crawlee/types';
2
2
  import type { ReadonlyDeep, SetRequired } from 'type-fest';
3
- import type { Configuration } from '../configuration.js';
4
3
  import type { EnqueueLinksOptions } from '../enqueue_links/enqueue_links.js';
5
4
  import type { CrawleeLogger } from '../log.js';
6
5
  import type { Request, RequestOptions, Source } from '../request.js';
7
6
  import type { StorageIdentifier } from '../storages/storage_instance_manager.js';
8
7
  import type { Dataset } from '../storages/dataset.js';
9
- import { KeyValueStore, type RecordOptions } from '../storages/key_value_store.js';
8
+ import type { KeyValueStore } from '../storages/key_value_store.js';
10
9
  import type { RequestQueueOperationOptions } from '../storages/request_queue.js';
11
10
  /** @internal */
12
11
  export type IsAny<T> = 0 extends 1 & T ? true : false;
@@ -176,6 +175,11 @@ export interface CrawlingContext<UserData extends Dictionary = Dictionary> exten
176
175
  sendRequest: (requestOverrides?: Partial<HttpRequestOptions>, optionsOverrides?: SendRequestOptions) => Promise<Response>;
177
176
  /**
178
177
  * Register a function to be called at the very end of the request handling process. This is useful for resources that should be accessible to error handlers, for instance.
178
+ *
179
+ * The callback runs *outside* the request's storage transaction, so storage writes made here are
180
+ * applied immediately and are **not** rolled back when the request fails. In
181
+ * {@link AdaptivePlaywrightCrawler} it also runs once per request handler attempt, so a write
182
+ * here can land more than once for a single request. Push results from the request handler itself.
179
183
  */
180
184
  registerDeferredCleanup(cleanup: () => Promise<unknown>): void;
181
185
  /**
@@ -198,58 +202,4 @@ export interface CrawlingContext<UserData extends Dictionary = Dictionary> exten
198
202
  */
199
203
  extendTimeout(secs: number): void;
200
204
  }
201
- /**
202
- * A partial implementation of {@link RestrictedCrawlingContext} that stores parameters of calls to context methods for later inspection.
203
- *
204
- * @experimental
205
- */
206
- export declare class RequestHandlerResult {
207
- private configuration;
208
- private crawleeStateKey;
209
- private _keyValueStoreChanges;
210
- private pushDataCalls;
211
- private addRequestsCalls;
212
- constructor(configuration: Configuration, crawleeStateKey: string);
213
- /**
214
- * A record of calls to {@link RestrictedCrawlingContext.pushData}, {@link RestrictedCrawlingContext.addRequests}, {@link RestrictedCrawlingContext.enqueueLinks} made by a request handler.
215
- */
216
- get calls(): ReadonlyDeep<{
217
- pushData: Parameters<RestrictedCrawlingContext['pushData']>[];
218
- addRequests: Parameters<RestrictedCrawlingContext['addRequests']>[];
219
- }>;
220
- /**
221
- * A record of changes made to key-value stores by a request handler.
222
- */
223
- get keyValueStoreChanges(): ReadonlyDeep<Record<string, Record<string, {
224
- changedValue: unknown;
225
- options?: RecordOptions;
226
- }>>>;
227
- /**
228
- * Items added to datasets by a request handler.
229
- */
230
- get datasetItems(): ReadonlyDeep<{
231
- item: Dictionary;
232
- datasetIdentifier?: string | StorageIdentifier;
233
- }[]>;
234
- /**
235
- * URLs enqueued to the request queue by a request handler, either via {@link RestrictedCrawlingContext.addRequests} or {@link RestrictedCrawlingContext.enqueueLinks}
236
- */
237
- get enqueuedUrls(): ReadonlyDeep<{
238
- url: string;
239
- label?: string;
240
- }[]>;
241
- /**
242
- * URL lists enqueued to the request queue by a request handler via {@link RestrictedCrawlingContext.addRequests} using the `requestsFromUrl` option.
243
- */
244
- get enqueuedUrlLists(): ReadonlyDeep<{
245
- listUrl: string;
246
- label?: string;
247
- }[]>;
248
- pushData: RestrictedCrawlingContext['pushData'];
249
- addRequests: RestrictedCrawlingContext['addRequests'];
250
- useState: RestrictedCrawlingContext['useState'];
251
- getKeyValueStore: RestrictedCrawlingContext['getKeyValueStore'];
252
- private getKeyValueStoreChangedValue;
253
- private setKeyValueStoreChangedValue;
254
- }
255
205
  export {};
@@ -1,107 +1 @@
1
- import { KeyValueStore } from '../storages/key_value_store.js';
2
- /**
3
- * A partial implementation of {@link RestrictedCrawlingContext} that stores parameters of calls to context methods for later inspection.
4
- *
5
- * @experimental
6
- */
7
- export class RequestHandlerResult {
8
- configuration;
9
- crawleeStateKey;
10
- _keyValueStoreChanges = {};
11
- pushDataCalls = [];
12
- addRequestsCalls = [];
13
- constructor(configuration, crawleeStateKey) {
14
- this.configuration = configuration;
15
- this.crawleeStateKey = crawleeStateKey;
16
- }
17
- /**
18
- * A record of calls to {@link RestrictedCrawlingContext.pushData}, {@link RestrictedCrawlingContext.addRequests}, {@link RestrictedCrawlingContext.enqueueLinks} made by a request handler.
19
- */
20
- get calls() {
21
- return {
22
- pushData: this.pushDataCalls,
23
- addRequests: this.addRequestsCalls,
24
- };
25
- }
26
- /**
27
- * A record of changes made to key-value stores by a request handler.
28
- */
29
- get keyValueStoreChanges() {
30
- return this._keyValueStoreChanges;
31
- }
32
- /**
33
- * Items added to datasets by a request handler.
34
- */
35
- get datasetItems() {
36
- return this.pushDataCalls.flatMap(([data, datasetIdentifier]) => (Array.isArray(data) ? data : [data]).map((item) => ({ item, datasetIdentifier })));
37
- }
38
- /**
39
- * URLs enqueued to the request queue by a request handler, either via {@link RestrictedCrawlingContext.addRequests} or {@link RestrictedCrawlingContext.enqueueLinks}
40
- */
41
- get enqueuedUrls() {
42
- const result = [];
43
- for (const [requests] of this.addRequestsCalls) {
44
- for (const request of requests) {
45
- if (typeof request === 'object' &&
46
- (!('requestsFromUrl' in request) || request.requestsFromUrl !== undefined) &&
47
- request.url !== undefined) {
48
- result.push({ url: request.url, label: request.label });
49
- }
50
- else if (typeof request === 'string') {
51
- result.push({ url: request });
52
- }
53
- }
54
- }
55
- return result;
56
- }
57
- /**
58
- * URL lists enqueued to the request queue by a request handler via {@link RestrictedCrawlingContext.addRequests} using the `requestsFromUrl` option.
59
- */
60
- get enqueuedUrlLists() {
61
- const result = [];
62
- for (const [requests] of this.addRequestsCalls) {
63
- for (const request of requests) {
64
- if (typeof request === 'object' &&
65
- 'requestsFromUrl' in request &&
66
- request.requestsFromUrl !== undefined) {
67
- result.push({ listUrl: request.requestsFromUrl, label: request.label });
68
- }
69
- }
70
- }
71
- return result;
72
- }
73
- pushData = async (data, datasetIdOrName) => {
74
- this.pushDataCalls.push([data, datasetIdOrName]);
75
- };
76
- addRequests = async (requests, options = {}) => {
77
- this.addRequestsCalls.push([requests, options]);
78
- };
79
- useState = async (defaultValue) => {
80
- const store = await this.getKeyValueStore(undefined);
81
- return await store.getAutoSavedValue(this.crawleeStateKey, defaultValue);
82
- };
83
- getKeyValueStore = async (identifier) => {
84
- const store = await KeyValueStore.open(identifier, { configuration: this.configuration });
85
- const storeId = store.id;
86
- return {
87
- id: storeId ?? this.configuration.defaultKeyValueStoreId,
88
- name: store.name,
89
- getValue: async (key) => this.getKeyValueStoreChangedValue(storeId, key) ?? (await store.getValue(key)),
90
- setValue: async (key, value, options) => {
91
- this.setKeyValueStoreChangedValue(storeId, key, value, options);
92
- },
93
- getAutoSavedValue: store.getAutoSavedValue.bind(store),
94
- getPublicUrl: store.getPublicUrl.bind(store),
95
- };
96
- };
97
- getKeyValueStoreChangedValue = (storeKey, key) => {
98
- const id = storeKey ?? this.configuration.defaultKeyValueStoreId;
99
- this._keyValueStoreChanges[id] ??= {};
100
- return this.keyValueStoreChanges[id][key]?.changedValue ?? null;
101
- };
102
- setKeyValueStoreChangedValue = (storeKey, key, changedValue, options) => {
103
- const id = storeKey ?? this.configuration.defaultKeyValueStoreId;
104
- this._keyValueStoreChanges[id] ??= {};
105
- this._keyValueStoreChanges[id][key] = { changedValue, options };
106
- };
107
- }
1
+ export {};
@@ -1,5 +1,5 @@
1
1
  export * from './context_pipeline.js';
2
- export * from './crawler_commons.js';
2
+ export type * from './crawler_commons.js';
3
3
  export * from './statistics.js';
4
4
  export * from './error_tracker.js';
5
5
  export * from './error_snapshotter.js';
package/crawlers/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  export * from './context_pipeline.js';
2
- export * from './crawler_commons.js';
3
2
  export * from './statistics.js';
4
3
  export * from './error_tracker.js';
5
4
  export * from './error_snapshotter.js';
@@ -81,6 +81,7 @@ export interface CalculatedStatistics {
81
81
  * @category Crawlers
82
82
  */
83
83
  export declare class Statistics implements IStatistics {
84
+ #private;
84
85
  private static id;
85
86
  /**
86
87
  * An error tracker for final retry errors.
@@ -104,15 +105,7 @@ export declare class Statistics implements IStatistics {
104
105
  readonly requestRetryHistogram: number[];
105
106
  protected keyValueStore?: KeyValueStore;
106
107
  protected readonly persistStateKey: string;
107
- private logIntervalMillis;
108
- private logMessage;
109
- private listener;
110
- private requestsInProgress;
111
108
  private readonly log;
112
- private instanceStart;
113
- private logInterval;
114
- private _events?;
115
- private persistenceOptions;
116
109
  private get events();
117
110
  /**
118
111
  * Construct a statistics instance to pass to a crawler via its `statistics` option, e.g. to preconfigure