@crawlee/core 4.0.0-beta.99 → 4.0.0-rc.1

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 (133) hide show
  1. package/README.md +1 -1
  2. package/configuration.d.ts +16 -47
  3. package/configuration.js +13 -25
  4. package/debug.js +4 -4
  5. package/errors.d.ts +28 -38
  6. package/errors.js +33 -47
  7. package/events/event_manager.d.ts +2 -2
  8. package/events/event_manager.js +7 -6
  9. package/events/index.d.ts +1 -0
  10. package/events/local_event_manager.d.ts +1 -8
  11. package/events/local_event_manager.js +13 -13
  12. package/events/system_info.d.ts +38 -0
  13. package/index.d.ts +2 -8
  14. package/index.js +4 -8
  15. package/internal.d.ts +8 -0
  16. package/internal.js +9 -0
  17. package/log.d.ts +10 -11
  18. package/log.js +52 -20
  19. package/memory-storage/memory-storage.d.ts +15 -18
  20. package/memory-storage/memory-storage.js +80 -58
  21. package/memory-storage/resource-clients/dataset.d.ts +1 -6
  22. package/memory-storage/resource-clients/dataset.js +23 -31
  23. package/memory-storage/resource-clients/key-value-store.d.ts +1 -10
  24. package/memory-storage/resource-clients/key-value-store.js +43 -67
  25. package/memory-storage/resource-clients/request-queue.d.ts +1 -42
  26. package/memory-storage/resource-clients/request-queue.js +109 -117
  27. package/owned_or_injected.d.ts +1 -3
  28. package/owned_or_injected.js +17 -17
  29. package/package.json +17 -20
  30. package/proxy_configuration.d.ts +21 -26
  31. package/proxy_configuration.js +35 -25
  32. package/recoverable_state.d.ts +104 -47
  33. package/recoverable_state.js +199 -74
  34. package/request.d.ts +20 -107
  35. package/request.js +78 -244
  36. package/serialization.js +17 -16
  37. package/service_locator.d.ts +22 -10
  38. package/service_locator.js +59 -48
  39. package/storages/batched_adds.d.ts +37 -0
  40. package/storages/batched_adds.js +73 -0
  41. package/storages/dataset.d.ts +13 -8
  42. package/storages/dataset.js +149 -40
  43. package/storages/index.d.ts +4 -4
  44. package/storages/index.js +2 -4
  45. package/storages/key_value_store.d.ts +16 -35
  46. package/storages/key_value_store.js +223 -110
  47. package/storages/key_value_store_codec.js +6 -11
  48. package/storages/request_dedup_cache.d.ts +1 -4
  49. package/storages/request_dedup_cache.js +15 -15
  50. package/storages/request_list.d.ts +9 -104
  51. package/storages/request_list.js +236 -233
  52. package/storages/request_loader.d.ts +49 -18
  53. package/storages/request_loader.js +36 -1
  54. package/storages/request_manager.d.ts +86 -0
  55. package/storages/request_manager_tandem.d.ts +14 -38
  56. package/storages/request_manager_tandem.js +67 -64
  57. package/storages/request_queue.d.ts +23 -50
  58. package/storages/request_queue.js +371 -226
  59. package/storages/storage_instance_manager.d.ts +2 -4
  60. package/storages/storage_instance_manager.js +21 -21
  61. package/storages/storage_stats.d.ts +1 -1
  62. package/storages/storage_stats.js +4 -4
  63. package/storages/transaction.d.ts +270 -0
  64. package/storages/transaction.js +296 -0
  65. package/storages/utils.d.ts +6 -3
  66. package/storages/utils.js +11 -2
  67. package/system-info/runtime.js +7 -7
  68. package/url.d.ts +9 -0
  69. package/url.js +11 -0
  70. package/validators.d.ts +23 -25
  71. package/validators.js +14 -25
  72. package/autoscaling/autoscaled_pool.d.ts +0 -213
  73. package/autoscaling/autoscaled_pool.js +0 -378
  74. package/autoscaling/client_load_signal.d.ts +0 -59
  75. package/autoscaling/client_load_signal.js +0 -73
  76. package/autoscaling/concurrency_system.d.ts +0 -283
  77. package/autoscaling/concurrency_system.js +0 -350
  78. package/autoscaling/cpu_load_signal.d.ts +0 -44
  79. package/autoscaling/cpu_load_signal.js +0 -46
  80. package/autoscaling/event_loop_load_signal.d.ts +0 -54
  81. package/autoscaling/event_loop_load_signal.js +0 -60
  82. package/autoscaling/index.d.ts +0 -9
  83. package/autoscaling/index.js +0 -9
  84. package/autoscaling/load_signal.d.ts +0 -99
  85. package/autoscaling/load_signal.js +0 -103
  86. package/autoscaling/memory_load_signal.d.ts +0 -56
  87. package/autoscaling/memory_load_signal.js +0 -106
  88. package/autoscaling/snapshotter.d.ts +0 -87
  89. package/autoscaling/snapshotter.js +0 -67
  90. package/autoscaling/system_status.d.ts +0 -161
  91. package/autoscaling/system_status.js +0 -139
  92. package/autoscaling/weighted_avg.d.ts +0 -5
  93. package/autoscaling/weighted_avg.js +0 -14
  94. package/cookie_utils.d.ts +0 -44
  95. package/cookie_utils.js +0 -122
  96. package/crawlers/context_pipeline.d.ts +0 -70
  97. package/crawlers/context_pipeline.js +0 -122
  98. package/crawlers/crawler_commons.d.ts +0 -257
  99. package/crawlers/crawler_commons.js +0 -107
  100. package/crawlers/error_snapshotter.d.ts +0 -59
  101. package/crawlers/error_snapshotter.js +0 -117
  102. package/crawlers/error_tracker.d.ts +0 -54
  103. package/crawlers/error_tracker.js +0 -308
  104. package/crawlers/index.d.ts +0 -5
  105. package/crawlers/index.js +0 -5
  106. package/crawlers/internals/types.d.ts +0 -7
  107. package/crawlers/statistics.d.ts +0 -209
  108. package/crawlers/statistics.js +0 -350
  109. package/enqueue_links/enqueue_links.d.ts +0 -264
  110. package/enqueue_links/enqueue_links.js +0 -271
  111. package/enqueue_links/index.d.ts +0 -2
  112. package/enqueue_links/index.js +0 -2
  113. package/enqueue_links/shared.d.ts +0 -83
  114. package/enqueue_links/shared.js +0 -221
  115. package/router.d.ts +0 -309
  116. package/router.js +0 -309
  117. package/session_pool/consts.d.ts +0 -3
  118. package/session_pool/consts.js +0 -3
  119. package/session_pool/errors.d.ts +0 -7
  120. package/session_pool/errors.js +0 -11
  121. package/session_pool/fingerprint.d.ts +0 -9
  122. package/session_pool/fingerprint.js +0 -30
  123. package/session_pool/index.d.ts +0 -4
  124. package/session_pool/index.js +0 -4
  125. package/session_pool/session.d.ts +0 -161
  126. package/session_pool/session.js +0 -218
  127. package/session_pool/session_pool.d.ts +0 -246
  128. package/session_pool/session_pool.js +0 -386
  129. package/storages/access_checking.d.ts +0 -12
  130. package/storages/access_checking.js +0 -17
  131. package/storages/sitemap_request_loader.d.ts +0 -249
  132. package/storages/sitemap_request_loader.js +0 -432
  133. /package/{crawlers/internals/types.js → events/system_info.js} +0 -0
@@ -1,386 +0,0 @@
1
- import { AsyncQueue } from '@sapphire/async-queue';
2
- import ow from 'ow';
3
- import { serviceLocator } from '../service_locator.js';
4
- import { KeyValueStore } from '../storages/key_value_store.js';
5
- import { MAX_POOL_SIZE, PERSIST_STATE_KEY } from './consts.js';
6
- import { createDefaultSessionFingerprint } from './fingerprint.js';
7
- import { Session } from './session.js';
8
- const SESSION_REUSE_STRATEGIES = ['random', 'round-robin', 'use-until-failure'];
9
- /**
10
- * Handles the rotation, creation and persistence of user-like sessions.
11
- * Creates a pool of {@link Session} instances, that are randomly rotated.
12
- * When some session is marked as blocked, it is removed and new one is created instead (the pool never returns an unusable session).
13
- * Learn more in the {@doclink guides/session-management | Session management guide}.
14
- *
15
- * Session pool is already integrated into crawlers and is always active.
16
- * All public methods are lazy-initialized — the pool initializes itself on first use.
17
- *
18
- * You can configure the pool with many options. See the {@link SessionPoolOptions}.
19
- * Session pool is by default persisted in default {@link KeyValueStore}.
20
- * If you want to have one pool for all runs you have to specify
21
- * {@link SessionPoolOptions.persistStateKeyValueStoreId}.
22
- *
23
- * **Advanced usage:**
24
- *
25
- * ```javascript
26
- * const sessionPool = new SessionPool({
27
- * maxPoolSize: 25,
28
- * sessionOptions:{
29
- * maxAgeSecs: 10,
30
- * maxUsageCount: 150, // for example when you know that the site blocks after 150 requests.
31
- * },
32
- * persistStateKeyValueStoreId: 'my-key-value-store-for-sessions',
33
- * persistStateKey: 'my-session-pool',
34
- * });
35
- *
36
- * // Get random session from the pool
37
- * const session1 = await sessionPool.getSession();
38
- * const session2 = await sessionPool.getSession();
39
- * const session3 = await sessionPool.getSession();
40
- *
41
- * // Now you can mark the session either failed or successful
42
- *
43
- * // Marks session as bad after unsuccessful usage -> it increases error count (soft retire)
44
- * session1.markBad()
45
- *
46
- * // Marks as successful.
47
- * session2.markGood()
48
- *
49
- * // Retires session -> session is removed from the pool
50
- * session3.retire()
51
- *
52
- * ```
53
- *
54
- * **Default session allocation flow:*
55
- * 1. Until the `SessionPool` reaches `maxPoolSize`, new sessions are created, provided to the user and added to the pool
56
- * 2. Blocked/retired sessions stay in the pool but are never provided to the user
57
- * 3. Once the pool is full (live plus blocked session count reaches `maxPoolSize`), a random session from the pool is provided.
58
- * 4. If a blocked session would be picked, instead all blocked sessions are evicted from the pool and a new session is created and provided
59
- *
60
- * @category Scaling
61
- */
62
- export class SessionPool {
63
- static nextId = 0;
64
- id;
65
- log;
66
- maxPoolSize;
67
- createSessionFunction;
68
- keyValueStore;
69
- sessions = [];
70
- sessionMap = new Map();
71
- sessionOptions;
72
- persistStateKeyValueStoreId;
73
- persistStateKey;
74
- listener;
75
- events;
76
- persistenceOptions;
77
- sessionReuseStrategy;
78
- initPromise;
79
- queue = new AsyncQueue();
80
- roundRobinIndex = 0;
81
- constructor(options = {}) {
82
- ow(options, ow.object.exactShape({
83
- id: ow.optional.any(ow.number, ow.string),
84
- maxPoolSize: ow.optional.number,
85
- persistStateKeyValueStoreId: ow.optional.string,
86
- persistStateKey: ow.optional.string,
87
- createSessionFunction: ow.optional.function,
88
- sessionOptions: ow.optional.object,
89
- log: ow.optional.object,
90
- persistenceOptions: ow.optional.object,
91
- sessionReuseStrategy: ow.optional.string.oneOf([...SESSION_REUSE_STRATEGIES]),
92
- }));
93
- const { id, maxPoolSize = MAX_POOL_SIZE, persistStateKeyValueStoreId, persistStateKey, createSessionFunction, sessionOptions = {}, log = serviceLocator.getLogger(), persistenceOptions = {
94
- enable: true,
95
- }, sessionReuseStrategy = 'random', } = options;
96
- this.id = id != null ? String(id) : String(SessionPool.nextId++);
97
- this.sessionReuseStrategy = sessionReuseStrategy;
98
- this.events = serviceLocator.getEventManager();
99
- this.log = log.child({ prefix: 'SessionPool' });
100
- this.persistenceOptions = persistenceOptions;
101
- // Pool Configuration
102
- this.maxPoolSize = maxPoolSize;
103
- this.createSessionFunction = createSessionFunction || this.defaultCreateSessionFunction;
104
- // Session configuration. The pool-scoped logger is merged into per-call sessionOptions inside
105
- // `_invokeCreateSessionFunction`, so every Session inherits it without custom createSessionFunctions
106
- // having to know about it.
107
- this.sessionOptions = {
108
- ...sessionOptions,
109
- log: this.log,
110
- };
111
- // Session keyValueStore
112
- this.persistStateKeyValueStoreId = persistStateKeyValueStoreId;
113
- this.persistStateKey = persistStateKey ?? `${PERSIST_STATE_KEY}_${this.id}`;
114
- }
115
- /**
116
- * Gets count of usable sessions in the pool.
117
- */
118
- async usableSessionsCount() {
119
- await this.ensureInitialized();
120
- return this.sessions.filter((session) => session.isUsable()).length;
121
- }
122
- /**
123
- * Gets count of retired sessions in the pool.
124
- */
125
- async retiredSessionsCount() {
126
- await this.ensureInitialized();
127
- return this.sessions.filter((session) => !session.isUsable()).length;
128
- }
129
- /**
130
- * Starts periodic state persistence and potentially loads SessionPool state from {@link KeyValueStore}.
131
- * Called automatically on first use of any public method.
132
- */
133
- async ensureInitialized() {
134
- if (!this.initPromise) {
135
- this.initPromise = this.setupPool();
136
- }
137
- return this.initPromise;
138
- }
139
- async setupPool() {
140
- if (!this.persistenceOptions.enable) {
141
- return;
142
- }
143
- this.keyValueStore = await KeyValueStore.open(this.persistStateKeyValueStoreId ? { id: this.persistStateKeyValueStoreId } : null, {
144
- configuration: serviceLocator.getConfiguration(),
145
- });
146
- if (!this.persistStateKeyValueStoreId) {
147
- this.log.debug(`No 'persistStateKeyValueStoreId' options specified, this session pool's data has been saved in the KeyValueStore with the id: ${this.keyValueStore.id}`);
148
- }
149
- // in case of migration happened and SessionPool state should be restored from the keyValueStore.
150
- await this.maybeLoadSessionPool();
151
- this.listener = this.persistState.bind(this);
152
- this.events.on("persistState" /* EventType.PERSIST_STATE */, this.listener);
153
- }
154
- /**
155
- * Adds a new session to the session pool. The pool automatically creates sessions up to the maximum size of the pool,
156
- * but this allows you to add more sessions once the max pool size is reached.
157
- * This also allows you to add session with overridden session options (e.g. with specific session id).
158
- * @param [options] The configuration options for the session being added to the session pool.
159
- */
160
- async addSession(options = {}) {
161
- await this.ensureInitialized();
162
- const { id } = options;
163
- if (id) {
164
- const sessionExists = this.sessionMap.has(id);
165
- if (sessionExists) {
166
- throw new Error(`Cannot add session with id '${id}' as it already exists in the pool`);
167
- }
168
- }
169
- if (!this.hasSpaceForSession()) {
170
- this.removeRetiredSessions();
171
- }
172
- const newSession = options instanceof Session ? options : await this._invokeCreateSessionFunction(options);
173
- this.log.debug(`Adding new Session - ${newSession.id}`);
174
- this.registerSession(newSession);
175
- }
176
- /**
177
- * Adds a new session to the session pool. The pool automatically creates sessions up to the maximum size of the pool,
178
- * but this allows you to add more sessions once the max pool size is reached.
179
- * This also allows you to add session with overridden session options (e.g. with specific session id).
180
- * @param [options] The configuration options for the session being added to the session pool.
181
- */
182
- async newSession(sessionOptions) {
183
- await this.ensureInitialized();
184
- const newSession = await this._invokeCreateSessionFunction(sessionOptions);
185
- this.registerSession(newSession);
186
- return newSession;
187
- }
188
- /**
189
- * Gets session.
190
- * If there is space for new session, it creates and returns new session.
191
- * If the session pool is full, it picks a session from the pool,
192
- * If the picked session is usable it is returned, otherwise it creates and returns a new one.
193
- * @param [sessionId] If provided, it returns the usable session with this id, `undefined` otherwise.
194
- */
195
- async getSession(sessionId) {
196
- await this.ensureInitialized();
197
- await this.queue.wait();
198
- try {
199
- if (sessionId) {
200
- const session = this.sessionMap.get(sessionId);
201
- if (session?.isUsable())
202
- return session;
203
- return undefined;
204
- }
205
- const pickedSession = this.pickSession();
206
- if (pickedSession)
207
- return pickedSession;
208
- if (this.hasSpaceForSession()) {
209
- return await this.createSession();
210
- }
211
- this.removeRetiredSessions();
212
- return await this.createSession();
213
- }
214
- finally {
215
- this.queue.shift();
216
- }
217
- }
218
- /**
219
- * @param options - Override the persistence options provided in the constructor
220
- */
221
- async resetStore(options) {
222
- if (!this.persistenceOptions.enable && !options?.enable) {
223
- return;
224
- }
225
- await this.ensureInitialized();
226
- await this.keyValueStore?.setValue(this.persistStateKey, null);
227
- }
228
- /**
229
- * Returns an object representing the internal state of the `SessionPool` instance.
230
- * Note that the object's fields can change in future releases.
231
- */
232
- async getState() {
233
- await this.ensureInitialized();
234
- return {
235
- usableSessionsCount: await this.usableSessionsCount(),
236
- retiredSessionsCount: await this.retiredSessionsCount(),
237
- sessions: this.sessions.map((session) => session.getState()),
238
- };
239
- }
240
- /**
241
- * Persists the current state of the `SessionPool` into the default {@link KeyValueStore}.
242
- * The state is persisted automatically in regular intervals.
243
- * @param options - Override the persistence options provided in the constructor
244
- */
245
- async persistState(options) {
246
- if (!this.persistenceOptions.enable && !options?.enable) {
247
- return;
248
- }
249
- await this.ensureInitialized();
250
- this.log.debug('Persisting state', {
251
- persistStateKeyValueStoreId: this.persistStateKeyValueStoreId,
252
- persistStateKey: this.persistStateKey,
253
- });
254
- await this.keyValueStore
255
- ?.setValue(this.persistStateKey, await this.getState())
256
- .catch((error) => this.log.warning(`Failed to persist the session pool stats to ${this.persistStateKey}`, { error }));
257
- }
258
- /**
259
- * Removes listener from `persistState` event.
260
- * This function should be called after you are done with using the `SessionPool` instance.
261
- */
262
- async teardown() {
263
- if (!this.initPromise)
264
- return;
265
- await this.ensureInitialized();
266
- if (this.listener) {
267
- this.events.off("persistState" /* EventType.PERSIST_STATE */, this.listener);
268
- }
269
- await this.persistState();
270
- }
271
- /**
272
- * Removes retired `Session` instances from `SessionPool`.
273
- */
274
- removeRetiredSessions() {
275
- this.sessions = this.sessions.filter((storedSession) => {
276
- if (storedSession.isUsable())
277
- return true;
278
- this.sessionMap.delete(storedSession.id);
279
- this.log.debug(`Removed Session - ${storedSession.id}`);
280
- return false;
281
- });
282
- }
283
- /**
284
- * Adds `Session` instance to `SessionPool`.
285
- * @param newSession `Session` instance to be added.
286
- */
287
- registerSession(newSession) {
288
- this.sessions.push(newSession);
289
- this.sessionMap.set(newSession.id, newSession);
290
- }
291
- /**
292
- * Gets random index.
293
- */
294
- getRandomIndex() {
295
- return Math.floor(Math.random() * this.sessions.length);
296
- }
297
- /**
298
- * Creates new session without any extra behavior.
299
- * @param [options]
300
- * @param [options.sessionOptions] The configuration options for the session being created.
301
- * @returns New session.
302
- */
303
- async defaultCreateSessionFunction(options = {}) {
304
- ow(options, ow.object.exactShape({ sessionOptions: ow.optional.object }));
305
- const { sessionOptions = {} } = options;
306
- return new Session(sessionOptions);
307
- }
308
- /**
309
- * Invokes `createSessionFunction` with `sessionOptions` already merged from pool-wide defaults and
310
- * the supplied per-call overrides, so custom implementations don't need to spread `pool.sessionOptions` themselves.
311
- *
312
- * A default {@link SessionFingerprint} is generated up front (host OS as
313
- * `platform`, a random valid `browser`/`device` for that platform). Pool-wide
314
- * and per-call options override it, and a persisted fingerprint coming
315
- * through `maybeLoadSessionPool` naturally wins because it arrives in
316
- * `perCallOptions`.
317
- */
318
- async _invokeCreateSessionFunction(perCallOptions) {
319
- const sessionOptions = {
320
- fingerprint: createDefaultSessionFingerprint(),
321
- ...this.sessionOptions,
322
- ...perCallOptions,
323
- };
324
- return this.createSessionFunction({ sessionOptions });
325
- }
326
- /**
327
- * Creates new session and adds it to the pool.
328
- * @returns Newly created `Session` instance.
329
- */
330
- async createSession() {
331
- const newSession = await this._invokeCreateSessionFunction();
332
- this.registerSession(newSession);
333
- this.log.debug(`Created new Session - ${newSession.id}`);
334
- return newSession;
335
- }
336
- /**
337
- * Decides whether there is enough space for creating new session.
338
- */
339
- hasSpaceForSession() {
340
- return this.sessions.length < this.maxPoolSize;
341
- }
342
- /**
343
- * Picks a session from the `SessionPool` according to the configured `sessionReuseStrategy`.
344
- * Returns `undefined` when no session should be reused and a new one should be created instead.
345
- */
346
- pickSession() {
347
- if (this.sessionReuseStrategy !== 'use-until-failure' && this.hasSpaceForSession())
348
- return undefined;
349
- if (this.sessionReuseStrategy === 'use-until-failure') {
350
- return this.sessions.find((session) => session.isUsable());
351
- }
352
- let picked;
353
- if (this.sessionReuseStrategy === 'round-robin') {
354
- const index = this.roundRobinIndex % this.sessions.length;
355
- this.roundRobinIndex = index + 1;
356
- picked = this.sessions[index];
357
- }
358
- else {
359
- picked = this.sessions[this.getRandomIndex()];
360
- }
361
- return picked.isUsable() ? picked : undefined;
362
- }
363
- /**
364
- * Potentially loads `SessionPool`.
365
- * If the state was persisted it loads the `SessionPool` from the persisted state.
366
- */
367
- async maybeLoadSessionPool() {
368
- const loadedSessionPool = await this.keyValueStore?.getValue(this.persistStateKey);
369
- if (!loadedSessionPool)
370
- return;
371
- // Invalidate old sessions and load active sessions only
372
- this.log.debug('Recreating state from KeyValueStore', {
373
- persistStateKeyValueStoreId: this.persistStateKeyValueStoreId,
374
- persistStateKey: this.persistStateKey,
375
- });
376
- for (const sessionObject of loadedSessionPool.sessions) {
377
- sessionObject.createdAt = new Date(sessionObject.createdAt);
378
- sessionObject.expiresAt = new Date(sessionObject.expiresAt);
379
- const recreatedSession = await this._invokeCreateSessionFunction(sessionObject);
380
- if (recreatedSession.isUsable()) {
381
- this.registerSession(recreatedSession);
382
- }
383
- }
384
- this.log.debug(`${this.sessions.length} active sessions loaded from KeyValueStore`);
385
- }
386
- }
@@ -1,12 +0,0 @@
1
- import type { Awaitable } from '@crawlee/types';
2
- /**
3
- * Invoke a storage access checker function defined using {@link withCheckedStorageAccess} higher up in the call stack.
4
- */
5
- export declare const checkStorageAccess: () => void | undefined;
6
- /**
7
- * Define a storage access checker function that should be used by calls to {@link checkStorageAccess} in the callbacks.
8
- *
9
- * @param checkFunction The check function that should be invoked by {@link checkStorageAccess} calls
10
- * @param callback The code that should be invoked with the `checkFunction` setting
11
- */
12
- export declare const withCheckedStorageAccess: <T>(checkFunction: () => void, callback: () => Awaitable<T>) => Promise<T>;
@@ -1,17 +0,0 @@
1
- import { AsyncLocalStorage } from 'node:async_hooks';
2
- import { tryCancel } from '@apify/timeout';
3
- const storage = new AsyncLocalStorage();
4
- /**
5
- * Invoke a storage access checker function defined using {@link withCheckedStorageAccess} higher up in the call stack.
6
- */
7
- export const checkStorageAccess = () => {
8
- tryCancel();
9
- return storage.getStore()?.checkFunction();
10
- };
11
- /**
12
- * Define a storage access checker function that should be used by calls to {@link checkStorageAccess} in the callbacks.
13
- *
14
- * @param checkFunction The check function that should be invoked by {@link checkStorageAccess} calls
15
- * @param callback The code that should be invoked with the `checkFunction` setting
16
- */
17
- export const withCheckedStorageAccess = async (checkFunction, callback) => storage.run({ checkFunction }, callback);
@@ -1,249 +0,0 @@
1
- import type { BaseHttpClient } from '@crawlee/types';
2
- import { type ParseSitemapOptions } from '@crawlee/utils';
3
- import type { GlobInput, RegExpInput } from '../enqueue_links/shared.js';
4
- import { Request } from '../request.js';
5
- import type { IRequestLoader } from './request_loader.js';
6
- import type { IRequestManager } from './request_manager.js';
7
- interface UrlConstraints {
8
- /**
9
- * An array of glob pattern strings or plain objects
10
- * containing glob pattern strings matching the URLs to be enqueued.
11
- *
12
- * The plain objects must include at least the `glob` property, which holds the glob pattern string.
13
- *
14
- * The matching is always case-insensitive.
15
- * If you need case-sensitive matching, use `regexps` property directly.
16
- *
17
- * If `globs` is an empty array or `undefined`, and `regexps` are also not defined, then the `SitemapRequestLoader`
18
- * includes all the URLs from the sitemap.
19
- */
20
- globs?: readonly GlobInput[];
21
- /**
22
- * An array of glob pattern strings, regexp patterns or plain objects
23
- * containing patterns matching URLs that will **never** be included.
24
- *
25
- * The plain objects must include either the `glob` property or the `regexp` property.
26
- *
27
- * Glob matching is always case-insensitive.
28
- * If you need case-sensitive matching, provide a regexp.
29
- */
30
- exclude?: readonly (GlobInput | RegExp)[];
31
- /**
32
- * An array of regular expressions or plain objects
33
- * containing regular expressions matching the URLs to be enqueued.
34
- *
35
- * The plain objects must include at least the `regexp` property, which holds the regular expression.
36
- *
37
- * If `regexps` is an empty array or `undefined`, and `globs` are also not defined, then the `SitemapRequestLoader`
38
- * includes all the URLs from the sitemap.
39
- */
40
- regexps?: readonly RegExpInput[];
41
- }
42
- export interface SitemapRequestLoaderOptions extends UrlConstraints {
43
- /**
44
- * List of sitemap URLs to parse.
45
- */
46
- sitemapUrls: string[];
47
- /**
48
- * Proxy URL to be used for sitemap loading.
49
- */
50
- proxyUrl?: string;
51
- /**
52
- * Key for persisting the state of the request list in the `KeyValueStore`.
53
- */
54
- persistStateKey?: string;
55
- /**
56
- * Persistence-related options to control how and when crawler's data gets persisted.
57
- */
58
- persistenceOptions?: {
59
- /**
60
- * Use this flag to disable or enable periodic persistence to key value store.
61
- * @default true
62
- */
63
- enable?: boolean;
64
- };
65
- /**
66
- * Abort signal to be used for sitemap loading.
67
- */
68
- signal?: AbortSignal;
69
- /**
70
- * Timeout for sitemap loading in milliseconds. If both `signal` and `timeoutMillis` are provided, either of them can abort the loading.
71
- */
72
- timeoutMillis?: number;
73
- /**
74
- * Maximum number of buffered URLs for the sitemap loading stream.
75
- * If the buffer is full, the stream will pause until the buffer is drained.
76
- *
77
- * @default 200
78
- */
79
- maxBufferSize?: number;
80
- /**
81
- * Advanced options for the underlying `parseSitemap` call.
82
- */
83
- parseSitemapOptions?: Omit<ParseSitemapOptions, 'emitNestedSitemaps' | 'maxDepth'>;
84
- /**
85
- * Custom HTTP client to be used for sitemap loading.
86
- */
87
- httpClient?: BaseHttpClient;
88
- }
89
- /**
90
- * A list of URLs to crawl parsed from a sitemap.
91
- *
92
- * The loading of the sitemap is performed in the background so that crawling can start before the sitemap is fully loaded.
93
- */
94
- export declare class SitemapRequestLoader implements IRequestLoader {
95
- /**
96
- * Set of URLs that were returned by `fetchNextRequest()` and not marked as handled yet.
97
- * @internal
98
- */
99
- inProgress: Set<string>;
100
- /**
101
- * Map of returned Request objects that have not been marked as handled yet.
102
- *
103
- * We use this to persist custom user fields on the in-progress requests.
104
- */
105
- private requestData;
106
- /**
107
- * Object for keeping track of the sitemap parsing progress.
108
- */
109
- private sitemapParsingProgress;
110
- /**
111
- * Object stream of URLs parsed from the sitemaps.
112
- * Using `highWaterMark`, this can manage the speed of the sitemap loading.
113
- *
114
- * Fetch the next URL to be processed using `fetchNextRequest()`.
115
- */
116
- private urlQueueStream;
117
- /**
118
- * Indicates whether the request list sitemap loading was aborted.
119
- *
120
- * If the loading was aborted before the sitemaps were fully loaded, the request list might be missing some URLs.
121
- * The `isSitemapFullyLoaded` method can be used to check if the sitemaps were fully loaded.
122
- *
123
- * If the loading is aborted and all the requests are handled, `isFinished()` will return `true`.
124
- */
125
- private abortLoading;
126
- /** Number of URLs that were marked as handled */
127
- private handledUrlCount;
128
- private persistStateKey?;
129
- private store?;
130
- private closed;
131
- /**
132
- * Proxy URL to be used for sitemap loading.
133
- */
134
- private proxyUrl?;
135
- /**
136
- * Logger instance.
137
- */
138
- private log;
139
- private urlExcludePatternObjects;
140
- private urlPatternObjects;
141
- /** EventManager used to handle persistence */
142
- private events;
143
- private persistenceOptions;
144
- /** @internal */
145
- private constructor();
146
- /**
147
- * Creates a new object stream with the specified highWaterMark.
148
- * @param highWaterMark High water mark for the stream (the maximum number of objects the stream will buffer).
149
- * @returns A new object stream.
150
- */
151
- private createNewStream;
152
- /**
153
- * Returns a function that checks whether the provided pattern matches the closure URL.
154
- * @param url URL to be checked.
155
- * @returns A matcher function that checks whether the pattern matches the closure URL.
156
- */
157
- private matchesUrl;
158
- /**
159
- * Checks whether the URL matches the `globs` / `regexps` / `exclude` provided in the `options`.
160
- * @param url URL to be checked.
161
- * @returns `true` if the URL matches the patterns, `false` otherwise.
162
- */
163
- private isUrlMatchingPatterns;
164
- /**
165
- * Adds a URL to the queue of parsed URLs.
166
- *
167
- * Blocks if the stream is full until it is drained.
168
- */
169
- private pushNextUrl;
170
- /**
171
- * Reads the next URL from the queue of parsed URLs.
172
- *
173
- * If the stream is empty, blocks until a new URL is pushed.
174
- * @returns The next URL from the queue or `null` if we have read all URLs.
175
- */
176
- private readNextUrl;
177
- /**
178
- * Indicates whether the background processing of sitemap contents has successfully finished.
179
- *
180
- * If this is `false`, the background processing is either still in progress or was aborted.
181
- */
182
- isSitemapFullyLoaded(): boolean;
183
- /**
184
- * Start processing the sitemaps and loading the URLs.
185
- *
186
- * Resolves once all the sitemaps URLs have been fully loaded (sets `isSitemapFullyLoaded` to `true`).
187
- */
188
- private load;
189
- /**
190
- * Open a sitemap and start processing it.
191
- *
192
- * Resolves to a new instance of `SitemapRequestLoader`, which **might not be fully loaded yet** - i.e. the sitemap might still be loading in the background.
193
- *
194
- * Track the loading progress using the `isSitemapFullyLoaded` property.
195
- */
196
- static open(options: SitemapRequestLoaderOptions): Promise<SitemapRequestLoader>;
197
- /**
198
- * @inheritDoc
199
- */
200
- getTotalCount(): Promise<number>;
201
- /**
202
- * @inheritDoc
203
- */
204
- getPendingCount(): Promise<number>;
205
- /**
206
- * Combines this list with a request manager (a {@link RequestQueue} by default) into a
207
- * {@link RequestManagerTandem}, allowing requests to be added and reclaimed while still
208
- * being read from this list first.
209
- */
210
- toTandem(requestManager?: IRequestManager): Promise<IRequestManager>;
211
- /**
212
- * @inheritDoc
213
- */
214
- isFinished(): Promise<boolean>;
215
- /**
216
- * @inheritDoc
217
- */
218
- isEmpty(): Promise<boolean>;
219
- /**
220
- * @inheritDoc
221
- */
222
- getHandledCount(): Promise<number>;
223
- /**
224
- * @inheritDoc
225
- */
226
- persistState(): Promise<void>;
227
- private restoreState;
228
- /**
229
- * @inheritDoc
230
- */
231
- fetchNextRequest(): Promise<Request | null>;
232
- /**
233
- * @inheritDoc
234
- */
235
- // @ts-ignore optional peer dependency or compatibility with es2022
236
- [Symbol.asyncIterator](): AsyncGenerator<Request<import("@crawlee/types").Dictionary>, void, unknown>;
237
- /**
238
- * Aborts the internal sitemap loading, stops the processing of the sitemap contents and drops all the pending URLs.
239
- *
240
- * Calling `fetchNextRequest()` after this method will always return `null`.
241
- */
242
- teardown(): Promise<void>;
243
- /**
244
- * @inheritDoc
245
- */
246
- markRequestAsHandled(request: Request): Promise<void>;
247
- private ensureInProgress;
248
- }
249
- export {};