@crawlee/core 4.0.0-beta.9 → 4.0.0-beta.90

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 (263) hide show
  1. package/README.md +17 -13
  2. package/autoscaling/autoscaled_pool.d.ts +66 -153
  3. package/autoscaling/autoscaled_pool.js +95 -251
  4. package/autoscaling/client_load_signal.d.ts +59 -0
  5. package/autoscaling/client_load_signal.js +73 -0
  6. package/autoscaling/concurrency_system.d.ts +283 -0
  7. package/autoscaling/concurrency_system.js +350 -0
  8. package/autoscaling/cpu_load_signal.d.ts +44 -0
  9. package/autoscaling/cpu_load_signal.js +46 -0
  10. package/autoscaling/event_loop_load_signal.d.ts +54 -0
  11. package/autoscaling/event_loop_load_signal.js +60 -0
  12. package/autoscaling/index.d.ts +6 -1
  13. package/autoscaling/index.js +6 -1
  14. package/autoscaling/load_signal.d.ts +99 -0
  15. package/autoscaling/load_signal.js +103 -0
  16. package/autoscaling/memory_load_signal.d.ts +56 -0
  17. package/autoscaling/memory_load_signal.js +106 -0
  18. package/autoscaling/snapshotter.d.ts +61 -163
  19. package/autoscaling/snapshotter.js +45 -263
  20. package/autoscaling/system_status.d.ts +63 -83
  21. package/autoscaling/system_status.js +90 -120
  22. package/configuration.d.ts +90 -223
  23. package/configuration.js +164 -222
  24. package/cookie_utils.d.ts +4 -3
  25. package/cookie_utils.js +20 -13
  26. package/crawlers/context_pipeline.d.ts +70 -0
  27. package/crawlers/context_pipeline.js +122 -0
  28. package/crawlers/crawler_commons.d.ts +76 -33
  29. package/crawlers/crawler_commons.js +15 -24
  30. package/crawlers/crawler_utils.d.ts +2 -3
  31. package/crawlers/crawler_utils.js +1 -2
  32. package/crawlers/error_snapshotter.d.ts +3 -3
  33. package/crawlers/error_snapshotter.js +2 -3
  34. package/crawlers/error_tracker.d.ts +2 -2
  35. package/crawlers/error_tracker.js +0 -1
  36. package/crawlers/index.d.ts +1 -2
  37. package/crawlers/index.js +1 -2
  38. package/crawlers/internals/types.d.ts +7 -0
  39. package/crawlers/internals/types.js +1 -0
  40. package/crawlers/statistics.d.ts +28 -23
  41. package/crawlers/statistics.js +38 -34
  42. package/debug.d.ts +36 -0
  43. package/debug.js +70 -0
  44. package/enqueue_links/enqueue_links.d.ts +44 -22
  45. package/enqueue_links/enqueue_links.js +51 -30
  46. package/enqueue_links/index.d.ts +0 -1
  47. package/enqueue_links/index.js +0 -1
  48. package/enqueue_links/shared.d.ts +25 -9
  49. package/enqueue_links/shared.js +69 -38
  50. package/errors.d.ts +53 -4
  51. package/errors.js +70 -5
  52. package/events/event_manager.d.ts +34 -8
  53. package/events/event_manager.js +8 -10
  54. package/events/index.d.ts +0 -1
  55. package/events/index.js +0 -1
  56. package/events/local_event_manager.d.ts +15 -3
  57. package/events/local_event_manager.js +37 -11
  58. package/index.d.ts +6 -3
  59. package/index.js +5 -2
  60. package/log.d.ts +82 -3
  61. package/log.js +102 -1
  62. package/memory-storage/consts.d.ts +4 -0
  63. package/memory-storage/consts.js +4 -0
  64. package/memory-storage/index.d.ts +1 -0
  65. package/memory-storage/index.js +1 -0
  66. package/memory-storage/memory-storage.d.ts +46 -0
  67. package/memory-storage/memory-storage.js +136 -0
  68. package/memory-storage/resource-clients/common/base-client.d.ts +4 -0
  69. package/memory-storage/resource-clients/common/base-client.js +6 -0
  70. package/memory-storage/resource-clients/dataset.d.ts +40 -0
  71. package/memory-storage/resource-clients/dataset.js +113 -0
  72. package/memory-storage/resource-clients/key-value-store.d.ts +63 -0
  73. package/memory-storage/resource-clients/key-value-store.js +203 -0
  74. package/memory-storage/resource-clients/request-queue.d.ts +96 -0
  75. package/memory-storage/resource-clients/request-queue.js +421 -0
  76. package/memory-storage/utils.d.ts +17 -0
  77. package/memory-storage/utils.js +42 -0
  78. package/owned_or_injected.d.ts +60 -0
  79. package/owned_or_injected.js +98 -0
  80. package/package.json +12 -10
  81. package/proxy_configuration.d.ts +29 -152
  82. package/proxy_configuration.js +21 -173
  83. package/recoverable_state.d.ts +120 -0
  84. package/recoverable_state.js +143 -0
  85. package/request.d.ts +84 -13
  86. package/request.js +107 -28
  87. package/router.d.ts +143 -17
  88. package/router.js +125 -30
  89. package/serialization.d.ts +0 -1
  90. package/serialization.js +1 -2
  91. package/service_locator.d.ts +156 -0
  92. package/service_locator.js +238 -0
  93. package/session_pool/consts.d.ts +1 -2
  94. package/session_pool/consts.js +1 -2
  95. package/session_pool/errors.d.ts +0 -1
  96. package/session_pool/errors.js +0 -1
  97. package/session_pool/fingerprint.d.ts +9 -0
  98. package/session_pool/fingerprint.js +30 -0
  99. package/session_pool/index.d.ts +0 -2
  100. package/session_pool/index.js +0 -2
  101. package/session_pool/session.d.ts +37 -75
  102. package/session_pool/session.js +49 -102
  103. package/session_pool/session_pool.d.ts +85 -90
  104. package/session_pool/session_pool.js +131 -120
  105. package/storages/access_checking.d.ts +0 -1
  106. package/storages/access_checking.js +5 -2
  107. package/storages/dataset.d.ts +103 -53
  108. package/storages/dataset.js +174 -132
  109. package/storages/index.d.ts +8 -7
  110. package/storages/index.js +6 -7
  111. package/storages/key_value_store.d.ts +167 -38
  112. package/storages/key_value_store.js +274 -127
  113. package/storages/key_value_store_codec.d.ts +32 -0
  114. package/storages/key_value_store_codec.js +113 -0
  115. package/storages/request_dedup_cache.d.ts +23 -0
  116. package/storages/request_dedup_cache.js +48 -0
  117. package/storages/request_list.d.ts +54 -98
  118. package/storages/request_list.js +99 -75
  119. package/storages/request_loader.d.ts +96 -0
  120. package/storages/request_loader.js +1 -0
  121. package/storages/request_manager.d.ts +33 -0
  122. package/storages/request_manager.js +1 -0
  123. package/storages/request_manager_tandem.d.ts +106 -0
  124. package/storages/request_manager_tandem.js +197 -0
  125. package/storages/request_queue.d.ts +290 -47
  126. package/storages/request_queue.js +629 -215
  127. package/storages/{sitemap_request_list.d.ts → sitemap_request_loader.d.ts} +28 -24
  128. package/storages/{sitemap_request_list.js → sitemap_request_loader.js} +49 -47
  129. package/storages/storage_instance_manager.d.ts +91 -0
  130. package/storages/storage_instance_manager.js +258 -0
  131. package/storages/storage_stats.d.ts +48 -0
  132. package/storages/storage_stats.js +29 -0
  133. package/storages/utils.d.ts +54 -9
  134. package/storages/utils.js +64 -13
  135. package/system-info/cpu-info.d.ts +67 -0
  136. package/system-info/cpu-info.js +216 -0
  137. package/system-info/memory-info.d.ts +31 -0
  138. package/system-info/memory-info.js +115 -0
  139. package/system-info/ps-tree.d.ts +17 -0
  140. package/system-info/ps-tree.js +144 -0
  141. package/system-info/runtime.d.ts +14 -0
  142. package/system-info/runtime.js +80 -0
  143. package/typedefs.d.ts +1 -2
  144. package/typedefs.js +0 -1
  145. package/validators.d.ts +8 -1
  146. package/validators.js +10 -3
  147. package/autoscaling/autoscaled_pool.d.ts.map +0 -1
  148. package/autoscaling/autoscaled_pool.js.map +0 -1
  149. package/autoscaling/index.d.ts.map +0 -1
  150. package/autoscaling/index.js.map +0 -1
  151. package/autoscaling/snapshotter.d.ts.map +0 -1
  152. package/autoscaling/snapshotter.js.map +0 -1
  153. package/autoscaling/system_status.d.ts.map +0 -1
  154. package/autoscaling/system_status.js.map +0 -1
  155. package/configuration.d.ts.map +0 -1
  156. package/configuration.js.map +0 -1
  157. package/cookie_utils.d.ts.map +0 -1
  158. package/cookie_utils.js.map +0 -1
  159. package/crawlers/crawler_commons.d.ts.map +0 -1
  160. package/crawlers/crawler_commons.js.map +0 -1
  161. package/crawlers/crawler_extension.d.ts +0 -12
  162. package/crawlers/crawler_extension.d.ts.map +0 -1
  163. package/crawlers/crawler_extension.js +0 -14
  164. package/crawlers/crawler_extension.js.map +0 -1
  165. package/crawlers/crawler_utils.d.ts.map +0 -1
  166. package/crawlers/crawler_utils.js.map +0 -1
  167. package/crawlers/error_snapshotter.d.ts.map +0 -1
  168. package/crawlers/error_snapshotter.js.map +0 -1
  169. package/crawlers/error_tracker.d.ts.map +0 -1
  170. package/crawlers/error_tracker.js.map +0 -1
  171. package/crawlers/index.d.ts.map +0 -1
  172. package/crawlers/index.js.map +0 -1
  173. package/crawlers/statistics.d.ts.map +0 -1
  174. package/crawlers/statistics.js.map +0 -1
  175. package/enqueue_links/enqueue_links.d.ts.map +0 -1
  176. package/enqueue_links/enqueue_links.js.map +0 -1
  177. package/enqueue_links/index.d.ts.map +0 -1
  178. package/enqueue_links/index.js.map +0 -1
  179. package/enqueue_links/shared.d.ts.map +0 -1
  180. package/enqueue_links/shared.js.map +0 -1
  181. package/errors.d.ts.map +0 -1
  182. package/errors.js.map +0 -1
  183. package/events/event_manager.d.ts.map +0 -1
  184. package/events/event_manager.js.map +0 -1
  185. package/events/index.d.ts.map +0 -1
  186. package/events/index.js.map +0 -1
  187. package/events/local_event_manager.d.ts.map +0 -1
  188. package/events/local_event_manager.js.map +0 -1
  189. package/http_clients/base-http-client.d.ts +0 -134
  190. package/http_clients/base-http-client.d.ts.map +0 -1
  191. package/http_clients/base-http-client.js +0 -33
  192. package/http_clients/base-http-client.js.map +0 -1
  193. package/http_clients/form-data-like.d.ts +0 -67
  194. package/http_clients/form-data-like.d.ts.map +0 -1
  195. package/http_clients/form-data-like.js +0 -5
  196. package/http_clients/form-data-like.js.map +0 -1
  197. package/http_clients/got-scraping-http-client.d.ts +0 -15
  198. package/http_clients/got-scraping-http-client.d.ts.map +0 -1
  199. package/http_clients/got-scraping-http-client.js +0 -69
  200. package/http_clients/got-scraping-http-client.js.map +0 -1
  201. package/http_clients/index.d.ts +0 -3
  202. package/http_clients/index.d.ts.map +0 -1
  203. package/http_clients/index.js +0 -3
  204. package/http_clients/index.js.map +0 -1
  205. package/index.d.ts.map +0 -1
  206. package/index.js.map +0 -1
  207. package/log.d.ts.map +0 -1
  208. package/log.js.map +0 -1
  209. package/proxy_configuration.d.ts.map +0 -1
  210. package/proxy_configuration.js.map +0 -1
  211. package/request.d.ts.map +0 -1
  212. package/request.js.map +0 -1
  213. package/router.d.ts.map +0 -1
  214. package/router.js.map +0 -1
  215. package/serialization.d.ts.map +0 -1
  216. package/serialization.js.map +0 -1
  217. package/session_pool/consts.d.ts.map +0 -1
  218. package/session_pool/consts.js.map +0 -1
  219. package/session_pool/errors.d.ts.map +0 -1
  220. package/session_pool/errors.js.map +0 -1
  221. package/session_pool/events.d.ts +0 -3
  222. package/session_pool/events.d.ts.map +0 -1
  223. package/session_pool/events.js +0 -3
  224. package/session_pool/events.js.map +0 -1
  225. package/session_pool/index.d.ts.map +0 -1
  226. package/session_pool/index.js.map +0 -1
  227. package/session_pool/session.d.ts.map +0 -1
  228. package/session_pool/session.js.map +0 -1
  229. package/session_pool/session_pool.d.ts.map +0 -1
  230. package/session_pool/session_pool.js.map +0 -1
  231. package/storages/access_checking.d.ts.map +0 -1
  232. package/storages/access_checking.js.map +0 -1
  233. package/storages/dataset.d.ts.map +0 -1
  234. package/storages/dataset.js.map +0 -1
  235. package/storages/index.d.ts.map +0 -1
  236. package/storages/index.js.map +0 -1
  237. package/storages/key_value_store.d.ts.map +0 -1
  238. package/storages/key_value_store.js.map +0 -1
  239. package/storages/request_list.d.ts.map +0 -1
  240. package/storages/request_list.js.map +0 -1
  241. package/storages/request_provider.d.ts +0 -307
  242. package/storages/request_provider.d.ts.map +0 -1
  243. package/storages/request_provider.js +0 -555
  244. package/storages/request_provider.js.map +0 -1
  245. package/storages/request_queue.d.ts.map +0 -1
  246. package/storages/request_queue.js.map +0 -1
  247. package/storages/request_queue_v2.d.ts +0 -87
  248. package/storages/request_queue_v2.d.ts.map +0 -1
  249. package/storages/request_queue_v2.js +0 -438
  250. package/storages/request_queue_v2.js.map +0 -1
  251. package/storages/sitemap_request_list.d.ts.map +0 -1
  252. package/storages/sitemap_request_list.js.map +0 -1
  253. package/storages/storage_manager.d.ts +0 -58
  254. package/storages/storage_manager.d.ts.map +0 -1
  255. package/storages/storage_manager.js +0 -105
  256. package/storages/storage_manager.js.map +0 -1
  257. package/storages/utils.d.ts.map +0 -1
  258. package/storages/utils.js.map +0 -1
  259. package/tsconfig.build.tsbuildinfo +0 -1
  260. package/typedefs.d.ts.map +0 -1
  261. package/typedefs.js.map +0 -1
  262. package/validators.d.ts.map +0 -1
  263. package/validators.js.map +0 -1
@@ -1,5 +1,4 @@
1
- import type { Log } from '@apify/log';
2
- import { Configuration } from '../configuration.js';
1
+ import type { CrawleeLogger } from '../log.js';
3
2
  import { KeyValueStore } from '../storages/key_value_store.js';
4
3
  import { ErrorTracker } from './error_tracker.js';
5
4
  /**
@@ -17,7 +16,7 @@ export interface PersistenceOptions {
17
16
  * statistics for requests.
18
17
  *
19
18
  * All statistic information is saved on key value store
20
- * under the key `SDK_CRAWLER_STATISTICS_*`, persists between
19
+ * under the key `CRAWLEE_CRAWLER_STATISTICS_*`, persists between
21
20
  * migrations and abort/resurrect
22
21
  *
23
22
  * @category Crawlers
@@ -27,15 +26,15 @@ export declare class Statistics {
27
26
  /**
28
27
  * An error tracker for final retry errors.
29
28
  */
30
- errorTracker: ErrorTracker;
29
+ readonly errorTracker: ErrorTracker;
31
30
  /**
32
31
  * An error tracker for retry errors prior to the final retry.
33
32
  */
34
- errorTrackerRetry: ErrorTracker;
33
+ readonly errorTrackerRetry: ErrorTracker;
35
34
  /**
36
35
  * Statistic instance id.
37
36
  */
38
- readonly id: number;
37
+ readonly id: string;
39
38
  /**
40
39
  * Current statistic state used for doing calculations on {@link Statistics.calculate} calls
41
40
  */
@@ -44,12 +43,8 @@ export declare class Statistics {
44
43
  * Contains the current retries histogram. Index 0 means 0 retries, index 2, 2 retries, and so on
45
44
  */
46
45
  readonly requestRetryHistogram: number[];
47
- /**
48
- * Contains the associated Configuration instance
49
- */
50
- private readonly config;
51
46
  protected keyValueStore?: KeyValueStore;
52
- protected persistStateKey: string;
47
+ protected readonly persistStateKey: string;
53
48
  private logIntervalMillis;
54
49
  private logMessage;
55
50
  private listener;
@@ -57,8 +52,9 @@ export declare class Statistics {
57
52
  private readonly log;
58
53
  private instanceStart;
59
54
  private logInterval;
60
- private events;
55
+ private _events?;
61
56
  private persistenceOptions;
57
+ private get events();
62
58
  /**
63
59
  * @internal
64
60
  */
@@ -90,6 +86,12 @@ export declare class Statistics {
90
86
  * @ignore
91
87
  */
92
88
  failJob(id: number | string, retryCount: number): void;
89
+ /**
90
+ * Discards a started job without affecting the finished/failed counters, e.g. when a request
91
+ * turns out to be skipped (robots.txt, enqueue strategy) after `startJob` was already called for it.
92
+ * @ignore
93
+ */
94
+ discardJob(id: number | string): void;
93
95
  /**
94
96
  * Calculate the current statistics
95
97
  */
@@ -111,7 +113,7 @@ export declare class Statistics {
111
113
  * Stops logging and remove event listeners, then persist
112
114
  */
113
115
  stopCapturing(): Promise<void>;
114
- protected _saveRetryCountForJob(retryCount: number): void;
116
+ private saveRetryCountForJob;
115
117
  /**
116
118
  * Persist internal state to the key value store
117
119
  * @param options - Override the persistence options provided in the constructor
@@ -120,8 +122,8 @@ export declare class Statistics {
120
122
  /**
121
123
  * Loads the current statistic from the key value store if any
122
124
  */
123
- protected _maybeLoadStatistics(): Promise<void>;
124
- protected _teardown(): void;
125
+ protected maybeLoadStatistics(): Promise<void>;
126
+ private teardown;
125
127
  /**
126
128
  * Make this class serializable when called with `JSON.stringify(statsInstance)` directly
127
129
  * or through `keyValueStore.setValue('KEY', statsInstance)`
@@ -146,17 +148,12 @@ export interface StatisticsOptions {
146
148
  * Parent logger instance, the statistics will create a child logger from this.
147
149
  * @default crawler.log
148
150
  */
149
- log?: Log;
151
+ log?: CrawleeLogger;
150
152
  /**
151
153
  * Key value store instance to persist the statistics.
152
154
  * If not provided, the default one will be used when capturing starts
153
155
  */
154
156
  keyValueStore?: KeyValueStore;
155
- /**
156
- * Configuration instance to use
157
- * @default Configuration.getGlobalConfig()
158
- */
159
- config?: Configuration;
160
157
  /**
161
158
  * Control how and when to persist the statistics.
162
159
  */
@@ -166,13 +163,22 @@ export interface StatisticsOptions {
166
163
  * @default false
167
164
  */
168
165
  saveErrorSnapshots?: boolean;
166
+ /**
167
+ * A unique identifier for this statistics instance. This ID is used for persistence
168
+ * to the key value store, ensuring the same statistics can be loaded after script restarts.
169
+ *
170
+ * If not provided, an auto-incremented ID will be used for backward compatibility.
171
+ * This means statistics may not persist correctly across script restarts
172
+ * if crawler creation order changes.
173
+ */
174
+ id?: string;
169
175
  }
170
176
  /**
171
177
  * Format of the persisted stats
172
178
  */
173
179
  export interface StatisticPersistedState extends Omit<StatisticState, 'statsPersistedAt'> {
174
180
  requestRetryHistogram: number[];
175
- statsId: number;
181
+ statsId: string;
176
182
  requestAvgFailedDurationMillis: number;
177
183
  requestAvgFinishedDurationMillis: number;
178
184
  requestTotalDurationMillis: number;
@@ -201,4 +207,3 @@ export interface StatisticState {
201
207
  retryErrors: Record<string, unknown>;
202
208
  requestsWithStatusCode: Record<string, number>;
203
209
  }
204
- //# sourceMappingURL=statistics.d.ts.map
@@ -1,6 +1,5 @@
1
1
  import ow from 'ow';
2
- import { Configuration } from '../configuration.js';
3
- import { log as defaultLog } from '../log.js';
2
+ import { serviceLocator } from '../service_locator.js';
4
3
  import { KeyValueStore } from '../storages/key_value_store.js';
5
4
  import { ErrorTracker } from './error_tracker.js';
6
5
  /**
@@ -30,7 +29,7 @@ const errorTrackerConfig = {
30
29
  * statistics for requests.
31
30
  *
32
31
  * All statistic information is saved on key value store
33
- * under the key `SDK_CRAWLER_STATISTICS_*`, persists between
32
+ * under the key `CRAWLEE_CRAWLER_STATISTICS_*`, persists between
34
33
  * migrations and abort/resurrect
35
34
  *
36
35
  * @category Crawlers
@@ -48,7 +47,7 @@ export class Statistics {
48
47
  /**
49
48
  * Statistic instance id.
50
49
  */
51
- id = Statistics.id++; // assign an id while incrementing so it can be saved/restored from KV
50
+ id;
52
51
  /**
53
52
  * Current statistic state used for doing calculations on {@link Statistics.calculate} calls
54
53
  */
@@ -57,12 +56,8 @@ export class Statistics {
57
56
  * Contains the current retries histogram. Index 0 means 0 retries, index 2, 2 retries, and so on
58
57
  */
59
58
  requestRetryHistogram = [];
60
- /**
61
- * Contains the associated Configuration instance
62
- */
63
- config;
64
59
  keyValueStore = undefined;
65
- persistStateKey = `SDK_CRAWLER_STATISTICS_${this.id}`;
60
+ persistStateKey;
66
61
  logIntervalMillis;
67
62
  logMessage;
68
63
  listener;
@@ -70,8 +65,14 @@ export class Statistics {
70
65
  log;
71
66
  instanceStart;
72
67
  logInterval;
73
- events;
68
+ _events;
74
69
  persistenceOptions;
70
+ get events() {
71
+ if (!this._events) {
72
+ this._events = serviceLocator.getEventManager();
73
+ }
74
+ return this._events;
75
+ }
75
76
  /**
76
77
  * @internal
77
78
  */
@@ -81,22 +82,22 @@ export class Statistics {
81
82
  logMessage: ow.optional.string,
82
83
  log: ow.optional.object,
83
84
  keyValueStore: ow.optional.object,
84
- config: ow.optional.object,
85
85
  persistenceOptions: ow.optional.object,
86
86
  saveErrorSnapshots: ow.optional.boolean,
87
+ id: ow.optional.any(ow.number, ow.string),
87
88
  }));
88
- const { logIntervalSecs = 60, logMessage = 'Statistics', keyValueStore, config = Configuration.getGlobalConfig(), persistenceOptions = {
89
+ const { logIntervalSecs = 60, logMessage = 'Statistics', keyValueStore, persistenceOptions = {
89
90
  enable: true,
90
- }, saveErrorSnapshots = false, } = options;
91
- this.log = (options.log ?? defaultLog).child({ prefix: 'Statistics' });
91
+ }, saveErrorSnapshots = false, id, } = options;
92
+ this.id = id ?? String(Statistics.id++);
93
+ this.persistStateKey = `CRAWLEE_CRAWLER_STATISTICS_${this.id}`;
94
+ this.log = (options.log ?? serviceLocator.getLogger()).child({ prefix: 'Statistics' });
92
95
  this.errorTracker = new ErrorTracker({ ...errorTrackerConfig, saveErrorSnapshots });
93
96
  this.errorTrackerRetry = new ErrorTracker({ ...errorTrackerConfig, saveErrorSnapshots });
94
97
  this.logIntervalMillis = logIntervalSecs * 1000;
95
98
  this.logMessage = logMessage;
96
99
  this.keyValueStore = keyValueStore;
97
100
  this.listener = this.persistState.bind(this);
98
- this.events = config.getEventManager();
99
- this.config = config;
100
101
  this.persistenceOptions = persistenceOptions;
101
102
  // initialize by "resetting"
102
103
  this.reset();
@@ -128,7 +129,7 @@ export class Statistics {
128
129
  this.requestRetryHistogram.length = 0;
129
130
  this.requestsInProgress.clear();
130
131
  this.instanceStart = Date.now();
131
- this._teardown();
132
+ this.teardown();
132
133
  }
133
134
  /**
134
135
  * @param options - Override the persistence options provided in the constructor
@@ -174,7 +175,7 @@ export class Statistics {
174
175
  const jobDurationMillis = job.finish();
175
176
  this.state.requestsFinished++;
176
177
  this.state.requestTotalFinishedDurationMillis += jobDurationMillis;
177
- this._saveRetryCountForJob(retryCount);
178
+ this.saveRetryCountForJob(retryCount);
178
179
  if (jobDurationMillis < this.state.requestMinDurationMillis)
179
180
  this.state.requestMinDurationMillis = jobDurationMillis;
180
181
  if (jobDurationMillis > this.state.requestMaxDurationMillis)
@@ -191,7 +192,15 @@ export class Statistics {
191
192
  return;
192
193
  this.state.requestTotalFailedDurationMillis += job.finish();
193
194
  this.state.requestsFailed++;
194
- this._saveRetryCountForJob(retryCount);
195
+ this.saveRetryCountForJob(retryCount);
196
+ this.requestsInProgress.delete(id);
197
+ }
198
+ /**
199
+ * Discards a started job without affecting the finished/failed counters, e.g. when a request
200
+ * turns out to be skipped (robots.txt, enqueue strategy) after `startJob` was already called for it.
201
+ * @ignore
202
+ */
203
+ discardJob(id) {
195
204
  this.requestsInProgress.delete(id);
196
205
  }
197
206
  /**
@@ -216,12 +225,12 @@ export class Statistics {
216
225
  * displaying the current state in predefined intervals
217
226
  */
218
227
  async startCapturing() {
219
- this.keyValueStore ??= await KeyValueStore.open(null, { config: this.config });
228
+ this.keyValueStore ??= await KeyValueStore.open(null, { configuration: serviceLocator.getConfiguration() });
220
229
  if (this.state.crawlerStartedAt === null) {
221
230
  this.state.crawlerStartedAt = new Date();
222
231
  }
223
232
  if (this.persistenceOptions.enable) {
224
- await this._maybeLoadStatistics();
233
+ await this.maybeLoadStatistics();
225
234
  this.events.on("persistState" /* EventType.PERSIST_STATE */, this.listener);
226
235
  }
227
236
  this.logInterval = setInterval(() => {
@@ -235,11 +244,11 @@ export class Statistics {
235
244
  * Stops logging and remove event listeners, then persist
236
245
  */
237
246
  async stopCapturing() {
238
- this._teardown();
247
+ this.teardown();
239
248
  this.state.crawlerFinishedAt = new Date();
240
249
  await this.persistState();
241
250
  }
242
- _saveRetryCountForJob(retryCount) {
251
+ saveRetryCountForJob(retryCount) {
243
252
  if (retryCount > 0)
244
253
  this.state.requestsRetries++;
245
254
  this.requestRetryHistogram[retryCount] ??= 0;
@@ -258,20 +267,14 @@ export class Statistics {
258
267
  return;
259
268
  }
260
269
  this.log.debug('Persisting state', { persistStateKey: this.persistStateKey });
261
- // use half the interval of `persistState` to avoid race conditions
262
- const persistStateIntervalMillis = this.config.get('persistStateIntervalMillis');
263
- const timeoutSecs = persistStateIntervalMillis / 2_000;
264
270
  await this.keyValueStore
265
- .setValue(this.persistStateKey, this.toJSON(), {
266
- timeoutSecs,
267
- doNotRetryTimeouts: true,
268
- })
271
+ .setValue(this.persistStateKey, this.toJSON())
269
272
  .catch((error) => this.log.warning(`Failed to persist the statistics to ${this.persistStateKey}`, { error }));
270
273
  }
271
274
  /**
272
275
  * Loads the current statistic from the key value store if any
273
276
  */
274
- async _maybeLoadStatistics() {
277
+ async maybeLoadStatistics() {
275
278
  // this might be called before startCapturing was called without using await, should not crash
276
279
  if (!this.keyValueStore) {
277
280
  return;
@@ -306,9 +309,11 @@ export class Statistics {
306
309
  this.instanceStart = Date.now() - (+this.state.statsPersistedAt - savedState.crawlerLastStartTimestamp);
307
310
  this.log.debug('Loaded from KeyValueStore');
308
311
  }
309
- _teardown() {
312
+ teardown() {
310
313
  // this can be called before a call to startCapturing happens (or in a 'finally' block)
311
- this.events.off("persistState" /* EventType.PERSIST_STATE */, this.listener);
314
+ // Only unsubscribe if event manager was already resolved — avoid eagerly resolving it
315
+ // (e.g. during the constructor's reset() call, which would capture the wrong context)
316
+ this._events?.off("persistState" /* EventType.PERSIST_STATE */, this.listener);
312
317
  if (this.logInterval) {
313
318
  clearInterval(this.logInterval);
314
319
  this.logInterval = null;
@@ -343,4 +348,3 @@ export class Statistics {
343
348
  return result;
344
349
  }
345
350
  }
346
- //# sourceMappingURL=statistics.js.map
package/debug.d.ts ADDED
@@ -0,0 +1,36 @@
1
+ import type { IncomingMessage } from 'node:http';
2
+ import type { Dictionary } from '@crawlee/types';
3
+ import type { Request } from './request.js';
4
+ interface BrowserResponseLike {
5
+ status(): number;
6
+ }
7
+ /**
8
+ * Creates a standardized debug info from request and response. This info is usually added to dataset under the hidden `#debug` field.
9
+ *
10
+ * @param request [Request](https://sdk.apify.com/docs/api/request) object.
11
+ * @param [response]
12
+ * Puppeteer [`Response`](https://pptr.dev/#?product=Puppeteer&version=v1.11.0&show=api-class-response)
13
+ * or NodeJS [`http.IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_serverresponse).
14
+ * @param [additionalFields] Object containing additional fields to be added.
15
+ *
16
+ * @internal
17
+ */
18
+ export declare function createRequestDebugInfo(request: Request, response?: IncomingMessage | Partial<BrowserResponseLike>, additionalFields?: Dictionary): Dictionary;
19
+ /**
20
+ * Returns a human-readable label for an unknown value,
21
+ * suitable for embedding in error messages and log output.
22
+ *
23
+ * Returns `constructor.name` when available (e.g. `"Configuration"`, `"Number"`),
24
+ * otherwise falls back to `util.inspect` (e.g. for `null`, `undefined`).
25
+ *
26
+ * @internal
27
+ */
28
+ export declare function inspectValue(value: unknown): string;
29
+ /**
30
+ * Returns the type of a value as a lowercase string, with `Date`, `Buffer` and `RegExp` reported
31
+ * by their constructor name. Used for building validation error messages.
32
+ *
33
+ * @internal
34
+ */
35
+ export declare function getObjectType(value: unknown): string;
36
+ export {};
package/debug.js ADDED
@@ -0,0 +1,70 @@
1
+ import { inspect } from 'node:util';
2
+ import ow from 'ow';
3
+ /**
4
+ * Creates a standardized debug info from request and response. This info is usually added to dataset under the hidden `#debug` field.
5
+ *
6
+ * @param request [Request](https://sdk.apify.com/docs/api/request) object.
7
+ * @param [response]
8
+ * Puppeteer [`Response`](https://pptr.dev/#?product=Puppeteer&version=v1.11.0&show=api-class-response)
9
+ * or NodeJS [`http.IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_serverresponse).
10
+ * @param [additionalFields] Object containing additional fields to be added.
11
+ *
12
+ * @internal
13
+ */
14
+ export function createRequestDebugInfo(request, response = {}, additionalFields = {}) {
15
+ ow(request, ow.object);
16
+ ow(response, ow.object);
17
+ ow(additionalFields, ow.object);
18
+ return {
19
+ requestId: request.id,
20
+ url: request.url,
21
+ loadedUrl: request.loadedUrl,
22
+ method: request.method,
23
+ retryCount: request.retryCount,
24
+ errorMessages: request.errorMessages,
25
+ // Puppeteer response has .status() function and NodeJS response, statusCode property.
26
+ statusCode: 'status' in response && response.status instanceof Function
27
+ ? response.status()
28
+ : response.statusCode,
29
+ ...additionalFields,
30
+ };
31
+ }
32
+ /**
33
+ * Returns a human-readable label for an unknown value,
34
+ * suitable for embedding in error messages and log output.
35
+ *
36
+ * Returns `constructor.name` when available (e.g. `"Configuration"`, `"Number"`),
37
+ * otherwise falls back to `util.inspect` (e.g. for `null`, `undefined`).
38
+ *
39
+ * @internal
40
+ */
41
+ export function inspectValue(value) {
42
+ if (typeof value === 'object' && value !== null && value.constructor?.name) {
43
+ return value.constructor.name;
44
+ }
45
+ return inspect(value, {
46
+ depth: 0,
47
+ compact: true,
48
+ maxStringLength: 64,
49
+ breakLength: Infinity,
50
+ colors: false,
51
+ });
52
+ }
53
+ /**
54
+ * Returns the type of a value as a lowercase string, with `Date`, `Buffer` and `RegExp` reported
55
+ * by their constructor name. Used for building validation error messages.
56
+ *
57
+ * @internal
58
+ */
59
+ export function getObjectType(value) {
60
+ const simple = typeof value;
61
+ if (['string', 'number', 'boolean', 'bigint'].includes(simple)) {
62
+ return simple;
63
+ }
64
+ const objectType = Object.prototype.toString.call(value);
65
+ const type = /\[object (\w+)]/.exec(objectType)[1];
66
+ if (type === 'Uint8Array') {
67
+ return 'Buffer';
68
+ }
69
+ return ['Date', 'Buffer', 'RegExp'].includes(type) ? type : type.toLowerCase();
70
+ }
@@ -1,25 +1,30 @@
1
- import type { Awaitable, BatchAddRequestsResult, Dictionary } from '@crawlee/types';
1
+ import type { BatchAddRequestsResult, Dictionary } from '@crawlee/types';
2
2
  import { type RobotsTxtFile } from '@crawlee/utils';
3
3
  import type { SetRequired } from 'type-fest';
4
- import type { RequestProvider, RequestQueueOperationOptions } from '../storages/request_provider.js';
5
- import type { GlobInput, PseudoUrlInput, RegExpInput, RequestTransform } from './shared.js';
6
- export type SkippedRequestCallback = (args: {
7
- url: string;
8
- reason: 'robotsTxt';
9
- }) => Awaitable<void>;
4
+ import { Request } from '../request.js';
5
+ import type { IRequestManager } from '../storages/request_manager.js';
6
+ import type { AddRequestsBatchedOptions, AddRequestsBatchedResult, RequestQueueOperationOptions } from '../storages/request_queue.js';
7
+ import type { GlobInput, PseudoUrlInput, RegExpInput, RequestTransform, SkippedRequestCallback } from './shared.js';
10
8
  export interface EnqueueLinksOptions extends RequestQueueOperationOptions {
11
9
  /** Limit the amount of actually enqueued URLs to this number. Useful for testing across the entire crawling scope. */
12
10
  limit?: number;
13
11
  /** An array of URLs to enqueue. */
14
12
  urls?: readonly string[];
15
- /** A request queue to which the URLs will be enqueued. */
16
- requestQueue?: RequestProvider;
13
+ /** A request manager to which the URLs will be enqueued. */
14
+ requestManager?: IRequestManager;
17
15
  /** A CSS selector matching links to be enqueued. */
18
16
  selector?: string;
19
17
  /** Sets {@link Request.userData} for newly enqueued requests. */
20
18
  userData?: Dictionary;
21
- /** Sets {@link Request.label} for newly enqueued requests. */
19
+ /**
20
+ * Sets {@link Request.label} for newly enqueued requests.
21
+ *
22
+ * This option has the lowest priority and can be overwritten by request options
23
+ * specified in `globs`, `regexps`, or `pseudoUrls` objects, as well as by `transformRequestFunction`.
24
+ */
22
25
  label?: string;
26
+ /** Sets {@link Request.sessionId} for newly enqueued requests. */
27
+ sessionId?: string;
23
28
  /**
24
29
  * If set to `true`, tells the crawler to skip navigation and process the request directly.
25
30
  * @default false
@@ -49,7 +54,6 @@ export interface EnqueueLinksOptions extends RequestQueueOperationOptions {
49
54
  * containing patterns matching URLs that will **never** be enqueued.
50
55
  *
51
56
  * The plain objects must include either the `glob` property or the `regexp` property.
52
- * All remaining keys will be used as request options for the corresponding enqueued {@link Request} objects.
53
57
  *
54
58
  * Glob matching is always case-insensitive.
55
59
  * If you need case-sensitive matching, provide a regexp.
@@ -86,12 +90,12 @@ export interface EnqueueLinksOptions extends RequestQueueOperationOptions {
86
90
  */
87
91
  pseudoUrls?: readonly PseudoUrlInput[];
88
92
  /**
89
- * Just before a new {@link Request} is constructed and enqueued to the {@link RequestQueue}, this function can be used
90
- * to remove it or modify its contents such as `userData`, `payload` or, most importantly `uniqueKey`. This is useful
93
+ * After request options are filtered by patterns, this function can be used
94
+ * to remove them or modify their contents such as `userData`, `payload` or, most importantly `uniqueKey`. This is useful
91
95
  * when you need to enqueue multiple `Requests` to the queue that share the same URL, but differ in methods or payloads,
92
96
  * or to dynamically update or create `userData`.
93
97
  *
94
- * For example: by adding `keepUrlFragment: true` to the `request` object, URL fragments will not be removed
98
+ * For example: by adding `keepUrlFragment: true` to the request options, URL fragments will not be removed
95
99
  * when `uniqueKey` is computed.
96
100
  *
97
101
  * **Example:**
@@ -105,9 +109,13 @@ export interface EnqueueLinksOptions extends RequestQueueOperationOptions {
105
109
  * }
106
110
  * ```
107
111
  *
108
- * Note that `transformRequestFunction` has a priority over request options
109
- * specified in `globs`, `regexps`, or `pseudoUrls` objects,
110
- * and thus some options could be over-written by `transformRequestFunction`.
112
+ * Note that `transformRequestFunction` has the highest priority and can overwrite request options
113
+ * specified in `globs`, `regexps`, or `pseudoUrls` objects, as well as the global `label` option.
114
+ *
115
+ * The function receives a {@link RequestOptions} object and can return either:
116
+ * - The modified {@link RequestOptions} object
117
+ * - `'unchanged'` to keep the original options as-is
118
+ * - A falsy value or `'skip'` to exclude the request from the queue
111
119
  */
112
120
  transformRequestFunction?: RequestTransform;
113
121
  /**
@@ -138,10 +146,21 @@ export interface EnqueueLinksOptions extends RequestQueueOperationOptions {
138
146
  * RobotsTxtFile instance for the current request that triggered the `enqueueLinks`.
139
147
  * If provided, disallowed URLs will be ignored.
140
148
  */
141
- robotsTxtFile?: RobotsTxtFile;
149
+ robotsTxtFile?: Pick<RobotsTxtFile, 'isAllowed'>;
150
+ /**
151
+ * Mirrors {@link BasicCrawlerOptions.respectRobotsTxtFile}: pass `false` to disable filtering or
152
+ * `{ userAgent }` to evaluate rules for a specific user-agent. Defaults to `*` when
153
+ * {@link EnqueueLinksOptions.robotsTxtFile|`robotsTxtFile`} is provided.
154
+ */
155
+ respectRobotsTxtFile?: boolean | {
156
+ userAgent?: string;
157
+ };
142
158
  /**
143
159
  * When a request is skipped for some reason, you can use this callback to act on it.
144
- * This is currently fired only for requests skipped based on robots.txt file.
160
+ * This is currently fired for requests skipped
161
+ * 1. based on robots.txt file,
162
+ * 2. because they don't match enqueueLinks filters,
163
+ * 3. or because the maxRequestsPerCrawl limit has been reached
145
164
  */
146
165
  onSkippedRequest?: SkippedRequestCallback;
147
166
  }
@@ -208,7 +227,7 @@ export declare enum EnqueueStrategy {
208
227
  * ```javascript
209
228
  * await enqueueLinks({
210
229
  * urls: aListOfFoundUrls,
211
- * requestQueue,
230
+ * requestManager,
212
231
  * selector: 'a.product-detail',
213
232
  * globs: [
214
233
  * 'https://www.example.com/handbags/*',
@@ -220,7 +239,11 @@ export declare enum EnqueueStrategy {
220
239
  * @param options All `enqueueLinks()` parameters are passed via an options object.
221
240
  * @returns Promise that resolves to {@link BatchAddRequestsResult} object.
222
241
  */
223
- export declare function enqueueLinks(options: SetRequired<EnqueueLinksOptions, 'requestQueue' | 'urls'>): Promise<BatchAddRequestsResult>;
242
+ export declare function enqueueLinks(options: SetRequired<Omit<EnqueueLinksOptions, 'requestManager'>, 'urls'> & {
243
+ requestManager: {
244
+ addRequestsBatched: (requests: Request<Dictionary>[], options: AddRequestsBatchedOptions) => Promise<AddRequestsBatchedResult>;
245
+ };
246
+ }): Promise<BatchAddRequestsResult>;
224
247
  /**
225
248
  * @internal
226
249
  * This method helps resolve the baseUrl that will be used for filtering in {@link enqueueLinks}.
@@ -239,4 +262,3 @@ export interface ResolveBaseUrl {
239
262
  originalRequestUrl: string;
240
263
  finalRequestUrl?: string;
241
264
  }
242
- //# sourceMappingURL=enqueue_links.d.ts.map