@crawlee/core 4.0.0-beta.13 → 4.0.0-beta.130
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.
- package/README.md +17 -13
- package/autoscaling/autoscaled_pool.d.ts +67 -172
- package/autoscaling/autoscaled_pool.js +182 -329
- package/autoscaling/concurrency_system.d.ts +268 -0
- package/autoscaling/concurrency_system.js +362 -0
- package/autoscaling/cpu_load_signal.d.ts +43 -0
- package/autoscaling/cpu_load_signal.js +47 -0
- package/autoscaling/event_loop_load_signal.d.ts +51 -0
- package/autoscaling/event_loop_load_signal.js +60 -0
- package/autoscaling/index.d.ts +6 -1
- package/autoscaling/index.js +6 -1
- package/autoscaling/load_signal.d.ts +100 -0
- package/autoscaling/load_signal.js +105 -0
- package/autoscaling/memory_load_signal.d.ts +47 -0
- package/autoscaling/memory_load_signal.js +106 -0
- package/autoscaling/snapshotter.d.ts +58 -163
- package/autoscaling/snapshotter.js +45 -263
- package/autoscaling/storage_backend_load_signal.d.ts +56 -0
- package/autoscaling/storage_backend_load_signal.js +73 -0
- package/autoscaling/system_status.d.ts +67 -89
- package/autoscaling/system_status.js +92 -122
- package/autoscaling/weighted_avg.d.ts +5 -0
- package/autoscaling/weighted_avg.js +14 -0
- package/byte_utils.d.ts +17 -0
- package/byte_utils.js +42 -0
- package/configuration.d.ts +96 -223
- package/configuration.js +170 -222
- package/cookie_utils.d.ts +3 -2
- package/cookie_utils.js +18 -7
- package/crawlers/context_pipeline.d.ts +10 -1
- package/crawlers/context_pipeline.js +31 -8
- package/crawlers/crawler_commons.d.ts +90 -129
- package/crawlers/crawler_commons.js +1 -116
- package/crawlers/error_snapshotter.d.ts +2 -5
- package/crawlers/error_snapshotter.js +7 -8
- package/crawlers/error_tracker.d.ts +0 -1
- package/crawlers/error_tracker.js +0 -1
- package/crawlers/index.d.ts +1 -3
- package/crawlers/index.js +0 -3
- package/crawlers/internals/types.d.ts +0 -1
- package/crawlers/internals/types.js +0 -1
- package/crawlers/statistics.d.ts +187 -63
- package/crawlers/statistics.js +354 -164
- package/debug.d.ts +36 -0
- package/debug.js +70 -0
- package/enqueue_links/enqueue_links.d.ts +68 -154
- package/enqueue_links/enqueue_links.js +38 -210
- package/enqueue_links/index.d.ts +0 -1
- package/enqueue_links/index.js +0 -1
- package/enqueue_links/shared.d.ts +52 -26
- package/enqueue_links/shared.js +115 -66
- package/errors.d.ts +72 -4
- package/errors.js +89 -5
- package/events/event_manager.d.ts +35 -9
- package/events/event_manager.js +12 -13
- package/events/index.d.ts +0 -1
- package/events/index.js +0 -1
- package/events/local_event_manager.d.ts +15 -3
- package/events/local_event_manager.js +39 -13
- package/http.d.ts +9 -0
- package/http.js +28 -0
- package/index.d.ts +7 -4
- package/index.js +6 -3
- package/iterables.d.ts +79 -0
- package/iterables.js +134 -0
- package/log.d.ts +82 -3
- package/log.js +106 -1
- package/memory-storage/consts.d.ts +4 -0
- package/memory-storage/consts.js +4 -0
- package/memory-storage/index.d.ts +1 -0
- package/memory-storage/index.js +1 -0
- package/memory-storage/memory-storage.d.ts +38 -0
- package/memory-storage/memory-storage.js +130 -0
- package/memory-storage/resource-clients/common/base-client.d.ts +4 -0
- package/memory-storage/resource-clients/common/base-client.js +6 -0
- package/memory-storage/resource-clients/dataset.d.ts +40 -0
- package/memory-storage/resource-clients/dataset.js +108 -0
- package/memory-storage/resource-clients/key-value-store.d.ts +63 -0
- package/memory-storage/resource-clients/key-value-store.js +201 -0
- package/memory-storage/resource-clients/request-queue.d.ts +77 -0
- package/memory-storage/resource-clients/request-queue.js +409 -0
- package/memory-storage/utils.d.ts +16 -0
- package/memory-storage/utils.js +41 -0
- package/owned_or_injected.d.ts +58 -0
- package/owned_or_injected.js +98 -0
- package/package.json +14 -13
- package/proxy_configuration.d.ts +24 -132
- package/proxy_configuration.js +32 -147
- package/recoverable_state.d.ts +155 -0
- package/recoverable_state.js +231 -0
- package/request.d.ts +80 -16
- package/request.js +147 -68
- package/router.d.ts +193 -21
- package/router.js +188 -43
- package/serialization.d.ts +0 -1
- package/serialization.js +15 -15
- package/service_locator.d.ts +165 -0
- package/service_locator.js +253 -0
- package/session_pool/consts.d.ts +1 -2
- package/session_pool/consts.js +1 -2
- package/session_pool/errors.d.ts +0 -1
- package/session_pool/errors.js +0 -1
- package/session_pool/fingerprint.d.ts +9 -0
- package/session_pool/fingerprint.js +30 -0
- package/session_pool/index.d.ts +0 -2
- package/session_pool/index.js +0 -2
- package/session_pool/session.d.ts +35 -88
- package/session_pool/session.js +101 -159
- package/session_pool/session_pool.d.ts +73 -91
- package/session_pool/session_pool.js +172 -165
- package/storages/batched_adds.d.ts +37 -0
- package/storages/batched_adds.js +73 -0
- package/storages/dataset.d.ts +114 -54
- package/storages/dataset.js +291 -148
- package/storages/index.d.ts +10 -8
- package/storages/index.js +8 -8
- package/storages/key_value_store.d.ts +185 -42
- package/storages/key_value_store.js +445 -169
- package/storages/key_value_store_codec.d.ts +32 -0
- package/storages/key_value_store_codec.js +113 -0
- package/storages/request_dedup_cache.d.ts +22 -0
- package/storages/request_dedup_cache.js +48 -0
- package/storages/request_list.d.ts +52 -115
- package/storages/request_list.js +183 -152
- package/storages/request_loader.d.ts +101 -0
- package/storages/request_loader.js +1 -0
- package/storages/request_manager.d.ts +33 -0
- package/storages/request_manager.js +1 -0
- package/storages/request_manager_tandem.d.ts +97 -0
- package/storages/request_manager_tandem.js +197 -0
- package/storages/request_queue.d.ts +290 -47
- package/storages/request_queue.js +762 -216
- package/storages/{sitemap_request_list.d.ts → sitemap_request_loader.d.ts} +45 -89
- package/storages/sitemap_request_loader.js +438 -0
- package/storages/storage_instance_manager.d.ts +87 -0
- package/storages/storage_instance_manager.js +256 -0
- package/storages/storage_stats.d.ts +48 -0
- package/storages/storage_stats.js +29 -0
- package/storages/throttling_request_manager.d.ts +239 -0
- package/storages/throttling_request_manager.js +646 -0
- package/storages/transaction.d.ts +252 -0
- package/storages/transaction.js +251 -0
- package/storages/utils.d.ts +59 -11
- package/storages/utils.js +75 -15
- package/system-info/cpu-info.d.ts +67 -0
- package/system-info/cpu-info.js +216 -0
- package/system-info/memory-info.d.ts +31 -0
- package/system-info/memory-info.js +115 -0
- package/system-info/ps-tree.d.ts +17 -0
- package/system-info/ps-tree.js +144 -0
- package/system-info/runtime.d.ts +14 -0
- package/system-info/runtime.js +80 -0
- package/typedefs.d.ts +0 -6
- package/typedefs.js +0 -1
- package/url.d.ts +9 -0
- package/url.js +11 -0
- package/validators.d.ts +22 -18
- package/validators.js +13 -18
- package/autoscaling/autoscaled_pool.d.ts.map +0 -1
- package/autoscaling/autoscaled_pool.js.map +0 -1
- package/autoscaling/index.d.ts.map +0 -1
- package/autoscaling/index.js.map +0 -1
- package/autoscaling/snapshotter.d.ts.map +0 -1
- package/autoscaling/snapshotter.js.map +0 -1
- package/autoscaling/system_status.d.ts.map +0 -1
- package/autoscaling/system_status.js.map +0 -1
- package/configuration.d.ts.map +0 -1
- package/configuration.js.map +0 -1
- package/cookie_utils.d.ts.map +0 -1
- package/cookie_utils.js.map +0 -1
- package/crawlers/context_pipeline.d.ts.map +0 -1
- package/crawlers/context_pipeline.js.map +0 -1
- package/crawlers/crawler_commons.d.ts.map +0 -1
- package/crawlers/crawler_commons.js.map +0 -1
- package/crawlers/crawler_utils.d.ts +0 -10
- package/crawlers/crawler_utils.d.ts.map +0 -1
- package/crawlers/crawler_utils.js +0 -12
- package/crawlers/crawler_utils.js.map +0 -1
- package/crawlers/error_snapshotter.d.ts.map +0 -1
- package/crawlers/error_snapshotter.js.map +0 -1
- package/crawlers/error_tracker.d.ts.map +0 -1
- package/crawlers/error_tracker.js.map +0 -1
- package/crawlers/index.d.ts.map +0 -1
- package/crawlers/index.js.map +0 -1
- package/crawlers/internals/types.d.ts.map +0 -1
- package/crawlers/internals/types.js.map +0 -1
- package/crawlers/statistics.d.ts.map +0 -1
- package/crawlers/statistics.js.map +0 -1
- package/enqueue_links/enqueue_links.d.ts.map +0 -1
- package/enqueue_links/enqueue_links.js.map +0 -1
- package/enqueue_links/index.d.ts.map +0 -1
- package/enqueue_links/index.js.map +0 -1
- package/enqueue_links/shared.d.ts.map +0 -1
- package/enqueue_links/shared.js.map +0 -1
- package/errors.d.ts.map +0 -1
- package/errors.js.map +0 -1
- package/events/event_manager.d.ts.map +0 -1
- package/events/event_manager.js.map +0 -1
- package/events/index.d.ts.map +0 -1
- package/events/index.js.map +0 -1
- package/events/local_event_manager.d.ts.map +0 -1
- package/events/local_event_manager.js.map +0 -1
- package/http_clients/base-http-client.d.ts +0 -140
- package/http_clients/base-http-client.d.ts.map +0 -1
- package/http_clients/base-http-client.js +0 -40
- package/http_clients/base-http-client.js.map +0 -1
- package/http_clients/form-data-like.d.ts +0 -67
- package/http_clients/form-data-like.d.ts.map +0 -1
- package/http_clients/form-data-like.js +0 -5
- package/http_clients/form-data-like.js.map +0 -1
- package/http_clients/got-scraping-http-client.d.ts +0 -20
- package/http_clients/got-scraping-http-client.d.ts.map +0 -1
- package/http_clients/got-scraping-http-client.js +0 -82
- package/http_clients/got-scraping-http-client.js.map +0 -1
- package/http_clients/index.d.ts +0 -3
- package/http_clients/index.d.ts.map +0 -1
- package/http_clients/index.js +0 -3
- package/http_clients/index.js.map +0 -1
- package/index.d.ts.map +0 -1
- package/index.js.map +0 -1
- package/log.d.ts.map +0 -1
- package/log.js.map +0 -1
- package/proxy_configuration.d.ts.map +0 -1
- package/proxy_configuration.js.map +0 -1
- package/request.d.ts.map +0 -1
- package/request.js.map +0 -1
- package/router.d.ts.map +0 -1
- package/router.js.map +0 -1
- package/serialization.d.ts.map +0 -1
- package/serialization.js.map +0 -1
- package/session_pool/consts.d.ts.map +0 -1
- package/session_pool/consts.js.map +0 -1
- package/session_pool/errors.d.ts.map +0 -1
- package/session_pool/errors.js.map +0 -1
- package/session_pool/events.d.ts +0 -3
- package/session_pool/events.d.ts.map +0 -1
- package/session_pool/events.js +0 -3
- package/session_pool/events.js.map +0 -1
- package/session_pool/index.d.ts.map +0 -1
- package/session_pool/index.js.map +0 -1
- package/session_pool/session.d.ts.map +0 -1
- package/session_pool/session.js.map +0 -1
- package/session_pool/session_pool.d.ts.map +0 -1
- package/session_pool/session_pool.js.map +0 -1
- package/storages/access_checking.d.ts +0 -13
- package/storages/access_checking.d.ts.map +0 -1
- package/storages/access_checking.js +0 -14
- package/storages/access_checking.js.map +0 -1
- package/storages/dataset.d.ts.map +0 -1
- package/storages/dataset.js.map +0 -1
- package/storages/index.d.ts.map +0 -1
- package/storages/index.js.map +0 -1
- package/storages/key_value_store.d.ts.map +0 -1
- package/storages/key_value_store.js.map +0 -1
- package/storages/request_list.d.ts.map +0 -1
- package/storages/request_list.js.map +0 -1
- package/storages/request_provider.d.ts +0 -308
- package/storages/request_provider.d.ts.map +0 -1
- package/storages/request_provider.js +0 -555
- package/storages/request_provider.js.map +0 -1
- package/storages/request_queue.d.ts.map +0 -1
- package/storages/request_queue.js.map +0 -1
- package/storages/request_queue_v2.d.ts +0 -87
- package/storages/request_queue_v2.d.ts.map +0 -1
- package/storages/request_queue_v2.js +0 -438
- package/storages/request_queue_v2.js.map +0 -1
- package/storages/sitemap_request_list.d.ts.map +0 -1
- package/storages/sitemap_request_list.js +0 -430
- package/storages/sitemap_request_list.js.map +0 -1
- package/storages/storage_manager.d.ts +0 -58
- package/storages/storage_manager.d.ts.map +0 -1
- package/storages/storage_manager.js +0 -105
- package/storages/storage_manager.js.map +0 -1
- package/storages/utils.d.ts.map +0 -1
- package/storages/utils.js.map +0 -1
- package/tsconfig.build.tsbuildinfo +0 -1
- package/typedefs.d.ts.map +0 -1
- package/typedefs.js.map +0 -1
- package/validators.d.ts.map +0 -1
- package/validators.js.map +0 -1
package/storages/request_list.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { downloadListOfUrls } from '@crawlee/utils';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import { log } from '../log.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { EventType } from '../events/event_manager.js';
|
|
5
4
|
import { Request } from '../request.js';
|
|
6
5
|
import { createDeserialize, serializeArray } from '../serialization.js';
|
|
6
|
+
import { serviceLocator } from '../service_locator.js';
|
|
7
|
+
import { parseArgument, schemas, validators } from '../validators.js';
|
|
7
8
|
import { KeyValueStore } from './key_value_store.js';
|
|
8
9
|
import { purgeDefaultStorages } from './utils.js';
|
|
9
10
|
/** @internal */
|
|
@@ -11,6 +12,24 @@ export const STATE_PERSISTENCE_KEY = 'REQUEST_LIST_STATE';
|
|
|
11
12
|
/** @internal */
|
|
12
13
|
export const REQUESTS_PERSISTENCE_KEY = 'REQUEST_LIST_REQUESTS';
|
|
13
14
|
const CONTENT_TYPE_BINARY = 'application/octet-stream';
|
|
15
|
+
const requestListOptionsSchema = z.strictObject({
|
|
16
|
+
sources: schemas.anyArray.optional(), // check only for array and not subtypes to avoid iteration over the whole thing
|
|
17
|
+
sourcesFunction: schemas.anyFunction.optional(),
|
|
18
|
+
persistStateKey: z.string().optional(),
|
|
19
|
+
persistRequestsKey: z.string().optional(),
|
|
20
|
+
state: z
|
|
21
|
+
.strictObject({
|
|
22
|
+
nextIndex: schemas.anyNumber,
|
|
23
|
+
nextUniqueKey: z.string(),
|
|
24
|
+
inProgress: schemas.anyObject, // persisted as an array of unique keys
|
|
25
|
+
})
|
|
26
|
+
.optional(),
|
|
27
|
+
keepDuplicateUrls: z.boolean().default(false),
|
|
28
|
+
proxyConfiguration: validators.proxyConfiguration.optional(),
|
|
29
|
+
httpClient: schemas.httpClient.optional(),
|
|
30
|
+
});
|
|
31
|
+
const listNameSchema = z.string().nullish();
|
|
32
|
+
const openOptionsSchema = z.looseObject({});
|
|
14
33
|
/**
|
|
15
34
|
* Represents a static list of URLs to crawl.
|
|
16
35
|
* The URLs can be provided either in code or parsed from a text file hosted on the web.
|
|
@@ -33,8 +52,8 @@ const CONTENT_TYPE_BINARY = 'application/octet-stream';
|
|
|
33
52
|
* > In practical terms, such a combination can be useful when there is a large number of initial URLs,
|
|
34
53
|
* > but more URLs would be added dynamically by the crawler.
|
|
35
54
|
*
|
|
36
|
-
* `RequestList` has an internal state where it stores information about which requests were already handled
|
|
37
|
-
* which are in progress
|
|
55
|
+
* `RequestList` has an internal state where it stores information about which requests were already handled
|
|
56
|
+
* and which are in progress. The state may be automatically persisted to the default
|
|
38
57
|
* {@link KeyValueStore} by setting the `persistStateKey` option so that if the Node.js process is restarted,
|
|
39
58
|
* the crawling can continue where it left off. The automated persisting is launched upon receiving the `persistState`
|
|
40
59
|
* event that is periodically emitted by {@link EventManager}.
|
|
@@ -73,7 +92,7 @@ const CONTENT_TYPE_BINARY = 'application/octet-stream';
|
|
|
73
92
|
* @category Sources
|
|
74
93
|
*/
|
|
75
94
|
export class RequestList {
|
|
76
|
-
log =
|
|
95
|
+
#log = serviceLocator.getLogger().child({ prefix: 'RequestList' });
|
|
77
96
|
/**
|
|
78
97
|
* Array of all requests from all sources, in the order as they appeared in sources.
|
|
79
98
|
* All requests in the array have distinct uniqueKey!
|
|
@@ -81,19 +100,20 @@ export class RequestList {
|
|
|
81
100
|
*/
|
|
82
101
|
requests = [];
|
|
83
102
|
/** Index to the next item in requests array to fetch. All previous requests are either handled or in progress. */
|
|
84
|
-
nextIndex = 0;
|
|
103
|
+
#nextIndex = 0;
|
|
85
104
|
/** Dictionary, key is Request.uniqueKey, value is corresponding index in the requests array. */
|
|
86
|
-
uniqueKeyToIndex = {};
|
|
105
|
+
#uniqueKeyToIndex = {};
|
|
87
106
|
/**
|
|
88
107
|
* Set of `uniqueKey`s of requests that were returned by fetchNextRequest().
|
|
89
108
|
* @internal
|
|
90
109
|
*/
|
|
91
110
|
inProgress = new Set();
|
|
92
111
|
/**
|
|
93
|
-
*
|
|
112
|
+
* `uniqueKey`s of requests that were in progress when the state was last persisted and thus need to be
|
|
113
|
+
* re-crawled after a restart. They are served before advancing through the rest of the sources.
|
|
94
114
|
* @internal
|
|
95
115
|
*/
|
|
96
|
-
|
|
116
|
+
#requestsToRetry = [];
|
|
97
117
|
/**
|
|
98
118
|
* Starts as true because until we handle the first request, the list is effectively persisted by doing nothing.
|
|
99
119
|
* @internal
|
|
@@ -104,77 +124,66 @@ export class RequestList {
|
|
|
104
124
|
* @internal
|
|
105
125
|
*/
|
|
106
126
|
areRequestsPersisted = false;
|
|
107
|
-
isLoading = false;
|
|
108
|
-
isInitialized = false;
|
|
109
|
-
persistStateKey;
|
|
110
|
-
persistRequestsKey;
|
|
111
|
-
initialState;
|
|
112
|
-
store;
|
|
113
|
-
keepDuplicateUrls;
|
|
127
|
+
#isLoading = false;
|
|
128
|
+
#isInitialized = false;
|
|
129
|
+
#persistStateKey;
|
|
130
|
+
#persistRequestsKey;
|
|
131
|
+
#initialState;
|
|
132
|
+
#store;
|
|
133
|
+
#keepDuplicateUrls;
|
|
134
|
+
// kept as TS-private: request_list tests read this field directly
|
|
114
135
|
sources;
|
|
115
|
-
sourcesFunction;
|
|
116
|
-
proxyConfiguration;
|
|
117
|
-
|
|
136
|
+
#sourcesFunction;
|
|
137
|
+
#proxyConfiguration;
|
|
138
|
+
#httpClient;
|
|
118
139
|
/**
|
|
119
140
|
* To create new instance of `RequestList` we need to use `RequestList.open()` factory method.
|
|
120
141
|
* @param options All `RequestList` configuration options
|
|
121
142
|
* @internal
|
|
122
143
|
*/
|
|
123
144
|
constructor(options = {}) {
|
|
124
|
-
const { sources, sourcesFunction, persistStateKey, persistRequestsKey, state, proxyConfiguration, keepDuplicateUrls
|
|
145
|
+
const { sources, sourcesFunction, persistStateKey, persistRequestsKey, state, proxyConfiguration, keepDuplicateUrls, httpClient, } = parseArgument(options, requestListOptionsSchema);
|
|
125
146
|
if (!(sources || sourcesFunction)) {
|
|
126
|
-
throw new
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
persistRequestsKey: ow.optional.string,
|
|
133
|
-
state: ow.optional.object.exactShape({
|
|
134
|
-
nextIndex: ow.number,
|
|
135
|
-
nextUniqueKey: ow.string,
|
|
136
|
-
inProgress: ow.object,
|
|
137
|
-
}),
|
|
138
|
-
keepDuplicateUrls: ow.optional.boolean,
|
|
139
|
-
proxyConfiguration: ow.optional.object,
|
|
140
|
-
}));
|
|
141
|
-
this.persistStateKey = persistStateKey ? `SDK_${persistStateKey}` : persistStateKey;
|
|
142
|
-
this.persistRequestsKey = persistRequestsKey ? `SDK_${persistRequestsKey}` : persistRequestsKey;
|
|
143
|
-
this.initialState = state;
|
|
144
|
-
this.events = config.getEventManager();
|
|
147
|
+
throw new Error('At least one of "sources" or "sourcesFunction" must be provided.');
|
|
148
|
+
}
|
|
149
|
+
this.#persistStateKey = persistStateKey ? `CRAWLEE_${persistStateKey}` : persistStateKey;
|
|
150
|
+
this.#persistRequestsKey = persistRequestsKey ? `CRAWLEE_${persistRequestsKey}` : persistRequestsKey;
|
|
151
|
+
this.#initialState = state;
|
|
152
|
+
this.#httpClient = httpClient;
|
|
145
153
|
// If this option is set then all requests will get a pre-generated unique ID and duplicate URLs will be kept in the list.
|
|
146
|
-
this
|
|
154
|
+
this.#keepDuplicateUrls = keepDuplicateUrls;
|
|
147
155
|
// Will be empty after initialization to save memory.
|
|
148
156
|
this.sources = sources ? [...sources] : [];
|
|
149
|
-
this
|
|
157
|
+
this.#sourcesFunction = sourcesFunction;
|
|
150
158
|
// The proxy configuration used for `requestsFromUrl` requests.
|
|
151
|
-
this
|
|
159
|
+
this.#proxyConfiguration = proxyConfiguration;
|
|
160
|
+
this.persistState = this.persistState.bind(this);
|
|
152
161
|
}
|
|
153
162
|
/**
|
|
154
163
|
* Loads all remote sources of URLs and potentially starts periodic state persistence.
|
|
155
164
|
* This function must be called before you can start using the instance in a meaningful way.
|
|
156
165
|
*/
|
|
157
166
|
async initialize() {
|
|
158
|
-
if (this
|
|
167
|
+
if (this.#isLoading) {
|
|
159
168
|
throw new Error('RequestList sources are already loading or were loaded.');
|
|
160
169
|
}
|
|
161
|
-
this
|
|
170
|
+
this.#isLoading = true;
|
|
162
171
|
await purgeDefaultStorages({ onlyPurgeOnce: true });
|
|
163
|
-
const [state, persistedRequests] = await this.
|
|
172
|
+
const [state, persistedRequests] = await this.loadStateAndPersistedRequests();
|
|
164
173
|
// Add persisted requests / new sources in a memory efficient way because with very
|
|
165
174
|
// large lists, we were running out of memory.
|
|
166
175
|
if (persistedRequests) {
|
|
167
|
-
await this.
|
|
176
|
+
await this.addPersistedRequests(persistedRequests);
|
|
168
177
|
}
|
|
169
178
|
else {
|
|
170
|
-
await this.
|
|
179
|
+
await this.addRequestsFromSources();
|
|
171
180
|
}
|
|
172
|
-
this.
|
|
173
|
-
this
|
|
174
|
-
if (this
|
|
175
|
-
await this.
|
|
176
|
-
if (this
|
|
177
|
-
|
|
181
|
+
this.restoreState(state);
|
|
182
|
+
this.#isInitialized = true;
|
|
183
|
+
if (this.#persistRequestsKey && !this.areRequestsPersisted)
|
|
184
|
+
await this.persistRequests();
|
|
185
|
+
if (this.#persistStateKey) {
|
|
186
|
+
serviceLocator.getEventManager().on(EventType.PERSIST_STATE, this.persistState);
|
|
178
187
|
}
|
|
179
188
|
return this;
|
|
180
189
|
}
|
|
@@ -183,17 +192,18 @@ export class RequestList {
|
|
|
183
192
|
* This needs to be done in a memory efficient way. We should update the input
|
|
184
193
|
* to a Stream once apify-client supports streams.
|
|
185
194
|
*/
|
|
186
|
-
async
|
|
195
|
+
async addPersistedRequests(persistedRequests) {
|
|
187
196
|
// We don't need the sources so we purge them to
|
|
188
197
|
// prevent them from hanging in memory.
|
|
189
198
|
for (let i = 0; i < this.sources.length; i++) {
|
|
199
|
+
// oxlint-disable-next-line typescript/no-array-delete -- intentional, drop the slot so V8 can collect the object
|
|
190
200
|
delete this.sources[i];
|
|
191
201
|
}
|
|
192
202
|
this.sources = [];
|
|
193
203
|
this.areRequestsPersisted = true;
|
|
194
204
|
const requestStream = createDeserialize(persistedRequests);
|
|
195
205
|
for await (const request of requestStream) {
|
|
196
|
-
this.
|
|
206
|
+
this.addRequest(request);
|
|
197
207
|
}
|
|
198
208
|
}
|
|
199
209
|
/**
|
|
@@ -202,32 +212,36 @@ export class RequestList {
|
|
|
202
212
|
* We need to avoid keeping both sources and requests in memory
|
|
203
213
|
* to reduce memory footprint with very large sources.
|
|
204
214
|
*/
|
|
205
|
-
async
|
|
215
|
+
async addRequestsFromSources() {
|
|
206
216
|
// We'll load all sources in sequence to ensure that they get loaded in the right order.
|
|
207
217
|
const sourcesCount = this.sources.length;
|
|
208
218
|
for (let i = 0; i < sourcesCount; i++) {
|
|
209
219
|
const source = this.sources[i];
|
|
210
220
|
// Using delete here to drop the original object ASAP to free memory
|
|
211
221
|
// .pop would reverse the array and .shift is SLOW.
|
|
222
|
+
// oxlint-disable-next-line typescript/no-array-delete
|
|
212
223
|
delete this.sources[i];
|
|
213
224
|
if (typeof source === 'object' && source.requestsFromUrl) {
|
|
214
|
-
const fetchedRequests = await this.
|
|
215
|
-
await this.
|
|
225
|
+
const fetchedRequests = await this.fetchRequestsFromUrl(source);
|
|
226
|
+
await this.addFetchedRequests(source, fetchedRequests);
|
|
216
227
|
}
|
|
217
228
|
else {
|
|
218
|
-
this.
|
|
229
|
+
this.addRequest(source);
|
|
219
230
|
}
|
|
220
231
|
}
|
|
221
232
|
// Drop the original array full of empty indexes.
|
|
222
233
|
this.sources = [];
|
|
223
|
-
if (this
|
|
234
|
+
if (this.#sourcesFunction) {
|
|
224
235
|
try {
|
|
225
|
-
const sourcesFromFunction = await this
|
|
236
|
+
const sourcesFromFunction = await this.#sourcesFunction();
|
|
226
237
|
const sourcesFromFunctionCount = sourcesFromFunction.length;
|
|
227
238
|
for (let i = 0; i < sourcesFromFunctionCount; i++) {
|
|
228
|
-
const source = sourcesFromFunction
|
|
229
|
-
|
|
239
|
+
const source = sourcesFromFunction[i];
|
|
240
|
+
// oxlint-disable-next-line typescript/no-array-delete -- intentional, drop the slot so V8 can collect the object
|
|
241
|
+
delete sourcesFromFunction[i];
|
|
242
|
+
this.addRequest(source);
|
|
230
243
|
}
|
|
244
|
+
sourcesFromFunction.length = 0;
|
|
231
245
|
}
|
|
232
246
|
catch (e) {
|
|
233
247
|
const err = e;
|
|
@@ -239,19 +253,30 @@ export class RequestList {
|
|
|
239
253
|
* @inheritDoc
|
|
240
254
|
*/
|
|
241
255
|
async persistState() {
|
|
242
|
-
if (!this
|
|
256
|
+
if (!this.#persistStateKey) {
|
|
243
257
|
throw new Error('Cannot persist state. options.persistStateKey is not set.');
|
|
244
258
|
}
|
|
245
259
|
if (this.isStatePersisted)
|
|
246
260
|
return;
|
|
247
261
|
try {
|
|
248
|
-
this
|
|
249
|
-
await this
|
|
262
|
+
this.#store ??= await KeyValueStore.open();
|
|
263
|
+
await this.#store.setValue(this.#persistStateKey, this.getState());
|
|
250
264
|
this.isStatePersisted = true;
|
|
251
265
|
}
|
|
252
266
|
catch (e) {
|
|
253
267
|
const err = e;
|
|
254
|
-
this
|
|
268
|
+
this.#log.exception(err, 'Attempted to persist state, but failed.');
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Removes the `PERSIST_STATE` event listener registered during initialization and persists
|
|
273
|
+
* the current state one last time. Call this when you are done with the `RequestList` to avoid
|
|
274
|
+
* leaking the listener (and the requests it retains) on the shared event manager.
|
|
275
|
+
*/
|
|
276
|
+
async teardown() {
|
|
277
|
+
serviceLocator.getEventManager().off(EventType.PERSIST_STATE, this.persistState);
|
|
278
|
+
if (this.#persistStateKey) {
|
|
279
|
+
await this.persistState();
|
|
255
280
|
}
|
|
256
281
|
}
|
|
257
282
|
/**
|
|
@@ -259,16 +284,16 @@ export class RequestList {
|
|
|
259
284
|
* are automatically persisted at RequestList initialization (if the persistRequestsKey is set),
|
|
260
285
|
* but there's no reason to persist it again afterwards, because RequestList is immutable.
|
|
261
286
|
*/
|
|
262
|
-
async
|
|
287
|
+
async persistRequests() {
|
|
263
288
|
const serializedRequests = await serializeArray(this.requests);
|
|
264
|
-
this
|
|
265
|
-
await this
|
|
289
|
+
this.#store ??= await KeyValueStore.open();
|
|
290
|
+
await this.#store.setValue(this.#persistRequestsKey, serializedRequests, { contentType: CONTENT_TYPE_BINARY });
|
|
266
291
|
this.areRequestsPersisted = true;
|
|
267
292
|
}
|
|
268
293
|
/**
|
|
269
294
|
* Restores RequestList state from a state object.
|
|
270
295
|
*/
|
|
271
|
-
|
|
296
|
+
restoreState(state) {
|
|
272
297
|
// If there's no state it means we've not persisted any (yet).
|
|
273
298
|
if (!state)
|
|
274
299
|
return;
|
|
@@ -285,7 +310,7 @@ export class RequestList {
|
|
|
285
310
|
}
|
|
286
311
|
const deleteFromInProgress = [];
|
|
287
312
|
state.inProgress.forEach((uniqueKey) => {
|
|
288
|
-
const index = this
|
|
313
|
+
const index = this.#uniqueKeyToIndex[uniqueKey];
|
|
289
314
|
if (typeof index !== 'number') {
|
|
290
315
|
throw new Error('The state object is not consistent with RequestList. Unknown uniqueKey is present in the state.');
|
|
291
316
|
}
|
|
@@ -293,7 +318,7 @@ export class RequestList {
|
|
|
293
318
|
deleteFromInProgress.push(uniqueKey);
|
|
294
319
|
}
|
|
295
320
|
});
|
|
296
|
-
this
|
|
321
|
+
this.#nextIndex = state.nextIndex;
|
|
297
322
|
this.inProgress = new Set(state.inProgress);
|
|
298
323
|
// WORKAROUND:
|
|
299
324
|
// It happened to some users that state object contained something like:
|
|
@@ -309,36 +334,36 @@ export class RequestList {
|
|
|
309
334
|
// As a workaround, we just remove all inProgress requests whose index >= nextIndex,
|
|
310
335
|
// since they will be crawled again.
|
|
311
336
|
if (deleteFromInProgress.length) {
|
|
312
|
-
this
|
|
337
|
+
this.#log.warning("RequestList's in-progress field is not consistent, skipping invalid in-progress entries", {
|
|
313
338
|
deleteFromInProgress,
|
|
314
339
|
});
|
|
315
340
|
for (const uniqueKey of deleteFromInProgress) {
|
|
316
341
|
this.inProgress.delete(uniqueKey);
|
|
317
342
|
}
|
|
318
343
|
}
|
|
319
|
-
// All in-progress requests need to be re-crawled
|
|
320
|
-
this
|
|
344
|
+
// All in-progress requests were interrupted and need to be re-crawled.
|
|
345
|
+
this.#requestsToRetry = [...this.inProgress];
|
|
321
346
|
}
|
|
322
347
|
/**
|
|
323
348
|
* Attempts to load state and requests using the `RequestList` configuration
|
|
324
349
|
* and returns a tuple of [state, requests] where each may be null if not loaded.
|
|
325
350
|
*/
|
|
326
|
-
async
|
|
351
|
+
async loadStateAndPersistedRequests() {
|
|
327
352
|
let state;
|
|
328
353
|
let persistedRequests;
|
|
329
|
-
if (this
|
|
330
|
-
state = this
|
|
331
|
-
this
|
|
354
|
+
if (this.#initialState) {
|
|
355
|
+
state = this.#initialState;
|
|
356
|
+
this.#log.debug('Loaded state from options.state argument.');
|
|
332
357
|
}
|
|
333
|
-
else if (this
|
|
334
|
-
state = await this.
|
|
358
|
+
else if (this.#persistStateKey) {
|
|
359
|
+
state = await this.getPersistedState(this.#persistStateKey);
|
|
335
360
|
if (state)
|
|
336
|
-
this
|
|
361
|
+
this.#log.debug('Loaded state from key value store using the persistStateKey.');
|
|
337
362
|
}
|
|
338
|
-
if (this
|
|
339
|
-
persistedRequests = await this.
|
|
363
|
+
if (this.#persistRequestsKey) {
|
|
364
|
+
persistedRequests = await this.getPersistedState(this.#persistRequestsKey);
|
|
340
365
|
if (persistedRequests)
|
|
341
|
-
this
|
|
366
|
+
this.#log.debug('Loaded requests from key value store using the persistRequestsKey.');
|
|
342
367
|
}
|
|
343
368
|
return [state, persistedRequests];
|
|
344
369
|
}
|
|
@@ -347,10 +372,10 @@ export class RequestList {
|
|
|
347
372
|
* Note that the object's fields can change in future releases.
|
|
348
373
|
*/
|
|
349
374
|
getState() {
|
|
350
|
-
this.
|
|
375
|
+
this.ensureIsInitialized();
|
|
351
376
|
return {
|
|
352
|
-
nextIndex: this
|
|
353
|
-
nextUniqueKey: this
|
|
377
|
+
nextIndex: this.#nextIndex,
|
|
378
|
+
nextUniqueKey: this.#nextIndex < this.requests.length ? this.requests[this.#nextIndex].uniqueKey : null,
|
|
354
379
|
inProgress: [...this.inProgress],
|
|
355
380
|
};
|
|
356
381
|
}
|
|
@@ -358,34 +383,33 @@ export class RequestList {
|
|
|
358
383
|
* @inheritDoc
|
|
359
384
|
*/
|
|
360
385
|
async isEmpty() {
|
|
361
|
-
this.
|
|
362
|
-
return this.
|
|
386
|
+
this.ensureIsInitialized();
|
|
387
|
+
return this.#requestsToRetry.length === 0 && this.#nextIndex >= this.requests.length;
|
|
363
388
|
}
|
|
364
389
|
/**
|
|
365
390
|
* @inheritDoc
|
|
366
391
|
*/
|
|
367
392
|
async isFinished() {
|
|
368
|
-
this.
|
|
369
|
-
return this.inProgress.size === 0 && this
|
|
393
|
+
this.ensureIsInitialized();
|
|
394
|
+
return this.inProgress.size === 0 && this.#nextIndex >= this.requests.length;
|
|
370
395
|
}
|
|
371
396
|
/**
|
|
372
397
|
* @inheritDoc
|
|
373
398
|
*/
|
|
374
399
|
async fetchNextRequest() {
|
|
375
|
-
this.
|
|
376
|
-
// First
|
|
377
|
-
const uniqueKey = this.
|
|
400
|
+
this.ensureIsInitialized();
|
|
401
|
+
// First re-serve any requests that were interrupted before the last state persist.
|
|
402
|
+
const uniqueKey = this.#requestsToRetry.shift();
|
|
378
403
|
if (uniqueKey) {
|
|
379
|
-
this
|
|
380
|
-
const index = this.uniqueKeyToIndex[uniqueKey];
|
|
404
|
+
const index = this.#uniqueKeyToIndex[uniqueKey];
|
|
381
405
|
return this.ensureRequest(this.requests[index], index);
|
|
382
406
|
}
|
|
383
407
|
// Otherwise return next request.
|
|
384
|
-
if (this
|
|
385
|
-
const index = this
|
|
408
|
+
if (this.#nextIndex < this.requests.length) {
|
|
409
|
+
const index = this.#nextIndex;
|
|
386
410
|
const request = this.requests[index];
|
|
387
411
|
this.inProgress.add(request.uniqueKey);
|
|
388
|
-
this
|
|
412
|
+
this.#nextIndex++;
|
|
389
413
|
this.isStatePersisted = false;
|
|
390
414
|
return this.ensureRequest(request, index);
|
|
391
415
|
}
|
|
@@ -412,34 +436,24 @@ export class RequestList {
|
|
|
412
436
|
/**
|
|
413
437
|
* @inheritDoc
|
|
414
438
|
*/
|
|
415
|
-
async
|
|
439
|
+
async markRequestAsHandled(request) {
|
|
416
440
|
const { uniqueKey } = request;
|
|
417
|
-
this.
|
|
418
|
-
this.
|
|
419
|
-
this.
|
|
441
|
+
this.ensureUniqueKeyValid(uniqueKey);
|
|
442
|
+
this.ensureInProgress(uniqueKey);
|
|
443
|
+
this.ensureIsInitialized();
|
|
420
444
|
this.inProgress.delete(uniqueKey);
|
|
421
445
|
this.isStatePersisted = false;
|
|
422
446
|
}
|
|
423
|
-
/**
|
|
424
|
-
* @inheritDoc
|
|
425
|
-
*/
|
|
426
|
-
async reclaimRequest(request) {
|
|
427
|
-
const { uniqueKey } = request;
|
|
428
|
-
this._ensureUniqueKeyValid(uniqueKey);
|
|
429
|
-
this._ensureInProgressAndNotReclaimed(uniqueKey);
|
|
430
|
-
this._ensureIsInitialized();
|
|
431
|
-
this.reclaimed.add(uniqueKey);
|
|
432
|
-
}
|
|
433
447
|
/**
|
|
434
448
|
* Adds all fetched requests from a URL from a remote resource.
|
|
435
449
|
*/
|
|
436
|
-
async
|
|
450
|
+
async addFetchedRequests(source, fetchedRequests) {
|
|
437
451
|
const { requestsFromUrl, regex } = source;
|
|
438
452
|
const originalLength = this.requests.length;
|
|
439
|
-
fetchedRequests.forEach((request) => this.
|
|
453
|
+
fetchedRequests.forEach((request) => this.addRequest(request));
|
|
440
454
|
const fetchedCount = fetchedRequests.length;
|
|
441
455
|
const importedCount = this.requests.length - originalLength;
|
|
442
|
-
this
|
|
456
|
+
this.#log.info('Fetched and loaded Requests from a remote resource.', {
|
|
443
457
|
requestsFromUrl,
|
|
444
458
|
regex,
|
|
445
459
|
fetchedCount,
|
|
@@ -448,23 +462,23 @@ export class RequestList {
|
|
|
448
462
|
sample: JSON.stringify(fetchedRequests.slice(0, 5)),
|
|
449
463
|
});
|
|
450
464
|
}
|
|
451
|
-
async
|
|
452
|
-
this
|
|
453
|
-
const state = await this
|
|
465
|
+
async getPersistedState(key) {
|
|
466
|
+
this.#store ??= await KeyValueStore.open();
|
|
467
|
+
const state = await this.#store.getValue(key);
|
|
454
468
|
return state;
|
|
455
469
|
}
|
|
456
470
|
/**
|
|
457
471
|
* Fetches URLs from requestsFromUrl and returns them in format of list of requests
|
|
458
472
|
*/
|
|
459
|
-
async
|
|
473
|
+
async fetchRequestsFromUrl(source) {
|
|
460
474
|
const { requestsFromUrl, regex, ...sharedOpts } = source;
|
|
461
475
|
// Download remote resource and parse URLs.
|
|
462
476
|
let urlsArr;
|
|
463
477
|
try {
|
|
464
|
-
urlsArr = await this.
|
|
478
|
+
urlsArr = await this.downloadListOfUrls({
|
|
465
479
|
url: requestsFromUrl,
|
|
466
480
|
urlRegExp: regex,
|
|
467
|
-
proxyUrl: await this
|
|
481
|
+
proxyUrl: (await this.#proxyConfiguration?.newProxyInfo())?.url,
|
|
468
482
|
});
|
|
469
483
|
}
|
|
470
484
|
catch (err) {
|
|
@@ -472,7 +486,7 @@ export class RequestList {
|
|
|
472
486
|
}
|
|
473
487
|
// Skip if resource contained no URLs.
|
|
474
488
|
if (!urlsArr.length) {
|
|
475
|
-
this
|
|
489
|
+
this.#log.warning('The fetched list contains no valid URLs.', { requestsFromUrl, regex });
|
|
476
490
|
return [];
|
|
477
491
|
}
|
|
478
492
|
return urlsArr.map((url) => ({ url, ...sharedOpts }));
|
|
@@ -482,7 +496,7 @@ export class RequestList {
|
|
|
482
496
|
* If the `source` parameter is a string or plain object and not an instance
|
|
483
497
|
* of a `Request`, then the function creates a `Request` instance.
|
|
484
498
|
*/
|
|
485
|
-
|
|
499
|
+
addRequest(source) {
|
|
486
500
|
let request;
|
|
487
501
|
const type = typeof source;
|
|
488
502
|
if (type === 'string') {
|
|
@@ -500,61 +514,76 @@ export class RequestList {
|
|
|
500
514
|
const hasUniqueKey = Reflect.has(Object(source), 'uniqueKey');
|
|
501
515
|
request.uniqueKey ??= Request.computeUniqueKey(request);
|
|
502
516
|
// Add index to uniqueKey if duplicates are to be kept
|
|
503
|
-
if (this
|
|
517
|
+
if (this.#keepDuplicateUrls && !hasUniqueKey) {
|
|
504
518
|
request.uniqueKey += `-${this.requests.length}`;
|
|
505
519
|
}
|
|
506
520
|
const { uniqueKey } = request;
|
|
507
|
-
this.
|
|
521
|
+
this.ensureUniqueKeyValid(uniqueKey);
|
|
508
522
|
// Skip requests with duplicate uniqueKey
|
|
509
|
-
if (!Object.hasOwn(this
|
|
510
|
-
this
|
|
523
|
+
if (!Object.hasOwn(this.#uniqueKeyToIndex, uniqueKey)) {
|
|
524
|
+
this.#uniqueKeyToIndex[uniqueKey] = this.requests.length;
|
|
511
525
|
this.requests.push(request);
|
|
512
526
|
}
|
|
513
|
-
else if (this
|
|
514
|
-
this
|
|
527
|
+
else if (this.#keepDuplicateUrls) {
|
|
528
|
+
this.#log.warning(`Duplicate uniqueKey: ${uniqueKey} found while the keepDuplicateUrls option was set. Check your sources' unique keys.`);
|
|
515
529
|
}
|
|
516
530
|
}
|
|
517
531
|
/**
|
|
518
532
|
* Helper function that validates unique key.
|
|
519
533
|
* Throws an error if uniqueKey is not a non-empty string.
|
|
520
534
|
*/
|
|
521
|
-
|
|
535
|
+
ensureUniqueKeyValid(uniqueKey) {
|
|
522
536
|
if (typeof uniqueKey !== 'string' || !uniqueKey) {
|
|
523
537
|
throw new Error("Request object's uniqueKey must be a non-empty string");
|
|
524
538
|
}
|
|
525
539
|
}
|
|
526
540
|
/**
|
|
527
|
-
* Checks that request is
|
|
541
|
+
* Checks that a request is currently being processed and throws an error if not.
|
|
528
542
|
*/
|
|
529
|
-
|
|
543
|
+
ensureInProgress(uniqueKey) {
|
|
530
544
|
if (!this.inProgress.has(uniqueKey)) {
|
|
531
545
|
throw new Error(`The request is not being processed (uniqueKey: ${uniqueKey})`);
|
|
532
546
|
}
|
|
533
|
-
if (this.reclaimed.has(uniqueKey)) {
|
|
534
|
-
throw new Error(`The request was already reclaimed (uniqueKey: ${uniqueKey})`);
|
|
535
|
-
}
|
|
536
547
|
}
|
|
537
548
|
/**
|
|
538
549
|
* Throws an error if request list wasn't initialized.
|
|
539
550
|
*/
|
|
540
|
-
|
|
541
|
-
if (!this
|
|
551
|
+
ensureIsInitialized() {
|
|
552
|
+
if (!this.#isInitialized) {
|
|
542
553
|
throw new Error('RequestList is not initialized; you must call "await requestList.initialize()" before using it!');
|
|
543
554
|
}
|
|
544
555
|
}
|
|
545
556
|
/**
|
|
546
557
|
* Returns the total number of unique requests present in the `RequestList`.
|
|
547
558
|
*/
|
|
548
|
-
|
|
549
|
-
this.
|
|
559
|
+
async getTotalCount() {
|
|
560
|
+
this.ensureIsInitialized();
|
|
550
561
|
return this.requests.length;
|
|
551
562
|
}
|
|
563
|
+
/**
|
|
564
|
+
* Returns the number of pending requests in the `RequestList`.
|
|
565
|
+
*/
|
|
566
|
+
async getPendingCount() {
|
|
567
|
+
this.ensureIsInitialized();
|
|
568
|
+
return this.requests.length - (this.#nextIndex - this.inProgress.size);
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Combines this list with a request manager (a {@link RequestQueue} by default) into a
|
|
572
|
+
* {@link RequestManagerTandem}, allowing requests to be added and reclaimed while still
|
|
573
|
+
* being read from this list first.
|
|
574
|
+
*/
|
|
575
|
+
async toTandem(requestManager) {
|
|
576
|
+
// Import here to avoid circular imports.
|
|
577
|
+
const { RequestManagerTandem } = await import('./request_manager_tandem.js');
|
|
578
|
+
const { RequestQueue } = await import('./request_queue.js');
|
|
579
|
+
return new RequestManagerTandem(this, requestManager ?? (await RequestQueue.open()));
|
|
580
|
+
}
|
|
552
581
|
/**
|
|
553
582
|
* @inheritDoc
|
|
554
583
|
*/
|
|
555
|
-
|
|
556
|
-
this.
|
|
557
|
-
return this
|
|
584
|
+
async getHandledCount() {
|
|
585
|
+
this.ensureIsInitialized();
|
|
586
|
+
return this.#nextIndex - this.inProgress.size;
|
|
558
587
|
}
|
|
559
588
|
/**
|
|
560
589
|
* Opens a request list and returns a promise resolving to an instance
|
|
@@ -617,9 +646,9 @@ export class RequestList {
|
|
|
617
646
|
return rl;
|
|
618
647
|
}
|
|
619
648
|
const listName = listNameOrOptions;
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
649
|
+
parseArgument(listName, listNameSchema);
|
|
650
|
+
parseArgument(sources, schemas.anyArray);
|
|
651
|
+
parseArgument(options, openOptionsSchema);
|
|
623
652
|
const rl = new RequestList({
|
|
624
653
|
...options,
|
|
625
654
|
persistStateKey: listName ? `${listName}-${STATE_PERSISTENCE_KEY}` : options.persistStateKey,
|
|
@@ -632,8 +661,10 @@ export class RequestList {
|
|
|
632
661
|
/**
|
|
633
662
|
* @internal wraps public utility for mocking purposes
|
|
634
663
|
*/
|
|
635
|
-
async
|
|
636
|
-
return downloadListOfUrls(
|
|
664
|
+
async downloadListOfUrls(options) {
|
|
665
|
+
return downloadListOfUrls({
|
|
666
|
+
...options,
|
|
667
|
+
httpClient: this.#httpClient,
|
|
668
|
+
});
|
|
637
669
|
}
|
|
638
670
|
}
|
|
639
|
-
//# sourceMappingURL=request_list.js.map
|