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

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 (109) hide show
  1. package/autoscaling/autoscaled_pool.d.ts +3 -21
  2. package/autoscaling/autoscaled_pool.js +105 -97
  3. package/autoscaling/concurrency_system.d.ts +7 -22
  4. package/autoscaling/concurrency_system.js +112 -100
  5. package/autoscaling/cpu_load_signal.d.ts +1 -2
  6. package/autoscaling/cpu_load_signal.js +11 -10
  7. package/autoscaling/event_loop_load_signal.d.ts +1 -4
  8. package/autoscaling/event_loop_load_signal.js +18 -18
  9. package/autoscaling/index.d.ts +1 -1
  10. package/autoscaling/index.js +1 -1
  11. package/autoscaling/load_signal.d.ts +8 -7
  12. package/autoscaling/load_signal.js +14 -12
  13. package/autoscaling/memory_load_signal.d.ts +3 -12
  14. package/autoscaling/memory_load_signal.js +41 -41
  15. package/autoscaling/snapshotter.d.ts +7 -10
  16. package/autoscaling/snapshotter.js +18 -18
  17. package/autoscaling/{client_load_signal.d.ts → storage_backend_load_signal.d.ts} +14 -17
  18. package/autoscaling/{client_load_signal.js → storage_backend_load_signal.js} +27 -27
  19. package/autoscaling/system_status.d.ts +9 -11
  20. package/autoscaling/system_status.js +13 -13
  21. package/configuration.d.ts +16 -16
  22. package/configuration.js +6 -6
  23. package/crawlers/context_pipeline.js +6 -6
  24. package/crawlers/crawler_commons.d.ts +14 -112
  25. package/crawlers/crawler_commons.js +1 -107
  26. package/crawlers/error_snapshotter.d.ts +2 -4
  27. package/crawlers/error_snapshotter.js +5 -5
  28. package/crawlers/index.d.ts +1 -1
  29. package/crawlers/index.js +0 -1
  30. package/crawlers/statistics.d.ts +164 -45
  31. package/crawlers/statistics.js +339 -153
  32. package/debug.js +4 -4
  33. package/enqueue_links/enqueue_links.d.ts +51 -159
  34. package/enqueue_links/enqueue_links.js +38 -231
  35. package/enqueue_links/shared.d.ts +34 -24
  36. package/enqueue_links/shared.js +54 -36
  37. package/errors.d.ts +43 -12
  38. package/errors.js +48 -9
  39. package/events/event_manager.d.ts +2 -2
  40. package/events/event_manager.js +7 -6
  41. package/events/local_event_manager.d.ts +1 -1
  42. package/events/local_event_manager.js +5 -5
  43. package/http.d.ts +9 -0
  44. package/http.js +28 -0
  45. package/index.d.ts +1 -1
  46. package/index.js +1 -1
  47. package/log.js +5 -1
  48. package/memory-storage/memory-storage.d.ts +3 -11
  49. package/memory-storage/memory-storage.js +42 -48
  50. package/memory-storage/resource-clients/dataset.d.ts +1 -1
  51. package/memory-storage/resource-clients/dataset.js +8 -13
  52. package/memory-storage/resource-clients/key-value-store.d.ts +1 -1
  53. package/memory-storage/resource-clients/key-value-store.js +36 -38
  54. package/memory-storage/resource-clients/request-queue.d.ts +4 -23
  55. package/memory-storage/resource-clients/request-queue.js +68 -80
  56. package/owned_or_injected.d.ts +1 -3
  57. package/owned_or_injected.js +17 -17
  58. package/package.json +8 -9
  59. package/proxy_configuration.d.ts +1 -3
  60. package/proxy_configuration.js +18 -14
  61. package/recoverable_state.d.ts +80 -45
  62. package/recoverable_state.js +163 -75
  63. package/request.d.ts +3 -4
  64. package/request.js +57 -44
  65. package/router.d.ts +6 -9
  66. package/router.js +23 -23
  67. package/serialization.js +14 -13
  68. package/service_locator.d.ts +19 -10
  69. package/service_locator.js +57 -48
  70. package/session_pool/session.d.ts +3 -14
  71. package/session_pool/session.js +76 -74
  72. package/session_pool/session_pool.d.ts +6 -12
  73. package/session_pool/session_pool.js +85 -77
  74. package/storages/batched_adds.d.ts +37 -0
  75. package/storages/batched_adds.js +73 -0
  76. package/storages/dataset.d.ts +12 -1
  77. package/storages/dataset.js +133 -32
  78. package/storages/index.d.ts +2 -1
  79. package/storages/index.js +2 -1
  80. package/storages/key_value_store.d.ts +19 -4
  81. package/storages/key_value_store.js +204 -75
  82. package/storages/request_dedup_cache.d.ts +1 -2
  83. package/storages/request_dedup_cache.js +9 -9
  84. package/storages/request_list.d.ts +4 -23
  85. package/storages/request_list.js +103 -96
  86. package/storages/request_loader.d.ts +5 -0
  87. package/storages/request_manager_tandem.d.ts +1 -10
  88. package/storages/request_manager_tandem.js +27 -27
  89. package/storages/request_queue.d.ts +21 -18
  90. package/storages/request_queue.js +318 -177
  91. package/storages/sitemap_request_loader.d.ts +22 -70
  92. package/storages/sitemap_request_loader.js +122 -116
  93. package/storages/storage_instance_manager.d.ts +1 -2
  94. package/storages/storage_instance_manager.js +17 -17
  95. package/storages/storage_stats.d.ts +1 -1
  96. package/storages/storage_stats.js +4 -4
  97. package/storages/throttling_request_manager.d.ts +239 -0
  98. package/storages/throttling_request_manager.js +646 -0
  99. package/storages/transaction.d.ts +252 -0
  100. package/storages/transaction.js +251 -0
  101. package/storages/utils.d.ts +6 -3
  102. package/storages/utils.js +11 -2
  103. package/system-info/runtime.js +7 -7
  104. package/url.d.ts +9 -0
  105. package/url.js +11 -0
  106. package/validators.d.ts +22 -25
  107. package/validators.js +13 -25
  108. package/storages/access_checking.d.ts +0 -12
  109. package/storages/access_checking.js +0 -17
@@ -65,20 +65,9 @@ export interface SessionOptions {
65
65
  * @category Scaling
66
66
  */
67
67
  export declare class Session implements ISession {
68
+ #private;
68
69
  readonly id: string;
69
70
  readonly userData: Dictionary;
70
- private _maxErrorScore;
71
- private _errorScoreDecrement;
72
- private _createdAt;
73
- private _expiresAt;
74
- private _usageCount;
75
- private _maxUsageCount;
76
- private _errorScore;
77
- private _retired;
78
- private _proxyInfo?;
79
- private _cookieJar;
80
- private _fingerprint?;
81
- private log;
82
71
  get errorScore(): number;
83
72
  get usageCount(): number;
84
73
  get maxErrorScore(): number;
@@ -149,11 +138,11 @@ export declare class Session implements ISession {
149
138
  * a cookie header or elsewhere.
150
139
  * @returns Represents `Cookie` header.
151
140
  */
152
- getCookieString(url: string): string;
141
+ getCookieString(url: string): Promise<string>;
153
142
  /**
154
143
  * Sets a cookie within this session for the specific URL.
155
144
  */
156
- setCookie(rawCookie: string, url: string): void;
145
+ setCookie(rawCookie: string, url: string): Promise<void>;
157
146
  /**
158
147
  * Checks if session is not usable. if it is not retires the session.
159
148
  */
@@ -1,8 +1,28 @@
1
- import ow from 'ow';
2
1
  import { CookieJar } from 'tough-cookie';
2
+ import { z } from 'zod';
3
3
  import { cryptoRandomObjectId } from '@apify/utilities';
4
4
  import { getDefaultCookieExpirationDate } from '../cookie_utils.js';
5
5
  import { serviceLocator } from '../service_locator.js';
6
+ import { parseArgument, schemas, validators } from '../validators.js';
7
+ // `schemas.anyObject` passes values through by reference (object schemas return a pruned plain
8
+ // copy), so class instances like cookie jars and loggers keep their prototype.
9
+ const sessionOptionsSchema = z.strictObject({
10
+ id: z.string().default(() => `session_${cryptoRandomObjectId(10)}`),
11
+ cookieJar: schemas.anyObject.default(() => new CookieJar()),
12
+ proxyInfo: schemas.anyObject.optional(),
13
+ maxAgeSecs: schemas.anyNumber.default(3000),
14
+ userData: schemas.anyObject.default(() => ({})),
15
+ maxErrorScore: schemas.anyNumber.default(3),
16
+ errorScoreDecrement: schemas.anyNumber.default(0.5),
17
+ createdAt: z.date().default(() => new Date()),
18
+ expiresAt: z.date().optional(),
19
+ usageCount: schemas.anyNumber.default(0),
20
+ errorScore: schemas.anyNumber.default(0),
21
+ maxUsageCount: schemas.anyNumber.default(50),
22
+ retired: z.boolean().default(false),
23
+ log: validators.logger.default(() => serviceLocator.getLogger()),
24
+ fingerprint: schemas.anyObject.optional(),
25
+ });
6
26
  /**
7
27
  * Sessions are used to store information such as cookies and can be used for generating fingerprints and proxy sessions.
8
28
  * You can imagine each session as a specific user, with its own cookies, IP (via proxy) and potentially a unique browser fingerprint.
@@ -12,96 +32,78 @@ import { serviceLocator } from '../service_locator.js';
12
32
  export class Session {
13
33
  id;
14
34
  userData;
15
- _maxErrorScore;
16
- _errorScoreDecrement;
17
- _createdAt;
18
- _expiresAt;
19
- _usageCount;
20
- _maxUsageCount;
21
- _errorScore;
22
- _retired = false;
23
- _proxyInfo;
24
- _cookieJar;
25
- _fingerprint;
26
- log;
35
+ #maxErrorScore;
36
+ #errorScoreDecrement;
37
+ #createdAt;
38
+ #expiresAt;
39
+ #usageCount;
40
+ #maxUsageCount;
41
+ #errorScore;
42
+ #retired = false;
43
+ #proxyInfo;
44
+ #cookieJar;
45
+ #fingerprint;
46
+ #log;
27
47
  get errorScore() {
28
- return this._errorScore;
48
+ return this.#errorScore;
29
49
  }
30
50
  get usageCount() {
31
- return this._usageCount;
51
+ return this.#usageCount;
32
52
  }
33
53
  get maxErrorScore() {
34
- return this._maxErrorScore;
54
+ return this.#maxErrorScore;
35
55
  }
36
56
  get errorScoreDecrement() {
37
- return this._errorScoreDecrement;
57
+ return this.#errorScoreDecrement;
38
58
  }
39
59
  get expiresAt() {
40
- return this._expiresAt;
60
+ return this.#expiresAt;
41
61
  }
42
62
  get createdAt() {
43
- return this._createdAt;
63
+ return this.#createdAt;
44
64
  }
45
65
  get maxUsageCount() {
46
- return this._maxUsageCount;
66
+ return this.#maxUsageCount;
47
67
  }
48
68
  get cookieJar() {
49
- return this._cookieJar;
69
+ return this.#cookieJar;
50
70
  }
51
71
  get proxyInfo() {
52
- return this._proxyInfo;
72
+ return this.#proxyInfo;
53
73
  }
54
74
  get fingerprint() {
55
- return this._fingerprint;
75
+ return this.#fingerprint;
56
76
  }
57
77
  set fingerprint(fingerprint) {
58
- this._fingerprint = fingerprint;
78
+ this.#fingerprint = fingerprint;
59
79
  }
60
80
  /**
61
81
  * `true` once {@link Session.retire|`retire()`} has been called. Retirement is terminal:
62
82
  * a retired session is never picked by the pool and cannot be revived via `markGood()`.
63
83
  */
64
84
  get retired() {
65
- return this._retired;
85
+ return this.#retired;
66
86
  }
67
87
  /**
68
88
  * Session configuration.
69
89
  */
70
90
  constructor(options = {}) {
71
- ow(options, ow.object.exactShape({
72
- id: ow.optional.string,
73
- cookieJar: ow.optional.object,
74
- proxyInfo: ow.optional.object,
75
- maxAgeSecs: ow.optional.number,
76
- userData: ow.optional.object,
77
- maxErrorScore: ow.optional.number,
78
- errorScoreDecrement: ow.optional.number,
79
- createdAt: ow.optional.date,
80
- expiresAt: ow.optional.date,
81
- usageCount: ow.optional.number,
82
- errorScore: ow.optional.number,
83
- maxUsageCount: ow.optional.number,
84
- retired: ow.optional.boolean,
85
- log: ow.optional.object,
86
- fingerprint: ow.optional.object,
87
- }));
88
- const { id = `session_${cryptoRandomObjectId(10)}`, cookieJar = new CookieJar(), proxyInfo = undefined, maxAgeSecs = 3000, userData = {}, maxErrorScore = 3, errorScoreDecrement = 0.5, createdAt = new Date(), usageCount = 0, errorScore = 0, maxUsageCount = 50, retired = false, log = serviceLocator.getLogger(), fingerprint, } = options;
89
- const { expiresAt = getDefaultCookieExpirationDate(maxAgeSecs) } = options;
90
- this.log = log.child({ prefix: 'Session' });
91
- this._cookieJar = cookieJar.setCookie ? cookieJar : CookieJar.fromJSON(JSON.stringify(cookieJar));
92
- this._proxyInfo = proxyInfo;
93
- this._fingerprint = fingerprint;
91
+ const { id, cookieJar, proxyInfo, maxAgeSecs, userData, maxErrorScore, errorScoreDecrement, createdAt, usageCount, errorScore, maxUsageCount, retired, log, fingerprint, expiresAt = getDefaultCookieExpirationDate(maxAgeSecs), } = parseArgument(options, sessionOptionsSchema);
92
+ this.#log = log.child({ prefix: 'Session' });
93
+ this.#cookieJar = cookieJar.setCookie ? cookieJar : CookieJar.fromJSON(JSON.stringify(cookieJar));
94
+ this.#proxyInfo = proxyInfo;
95
+ this.#fingerprint = fingerprint;
94
96
  this.id = id;
95
97
  this.userData = userData;
96
- this._maxErrorScore = maxErrorScore;
97
- this._errorScoreDecrement = errorScoreDecrement;
98
+ this.#maxErrorScore = maxErrorScore;
99
+ this.#errorScoreDecrement = errorScoreDecrement;
98
100
  // Internal
99
- this._expiresAt = expiresAt;
100
- this._createdAt = createdAt;
101
- this._usageCount = usageCount; // indicates how many times the session has been used
102
- this._errorScore = errorScore; // indicates number of markBaded request with the session
103
- this._maxUsageCount = maxUsageCount;
104
- this._retired = retired;
101
+ this.#expiresAt = expiresAt;
102
+ this.#createdAt = createdAt;
103
+ this.#usageCount = usageCount; // indicates how many times the session has been used
104
+ this.#errorScore = errorScore; // indicates number of markBaded request with the session
105
+ this.#maxUsageCount = maxUsageCount;
106
+ this.#retired = retired;
105
107
  }
106
108
  /**
107
109
  * Indicates whether the session is blocked.
@@ -130,16 +132,16 @@ export class Session {
130
132
  * Session is usable when it is not retired, not expired, not blocked and the maximum usage count has not be reached.
131
133
  */
132
134
  isUsable() {
133
- return !this._retired && !this.isBlocked() && !this.isExpired() && !this.isMaxUsageCountReached();
135
+ return !this.#retired && !this.isBlocked() && !this.isExpired() && !this.isMaxUsageCountReached();
134
136
  }
135
137
  /**
136
138
  * This method should be called after a successful session usage.
137
139
  * It increases `usageCount` and potentially lowers the `errorScore` by the `errorScoreDecrement`.
138
140
  */
139
141
  markGood() {
140
- this._usageCount += 1;
141
- if (this._errorScore > 0) {
142
- this._errorScore -= this._errorScoreDecrement;
142
+ this.#usageCount += 1;
143
+ if (this.#errorScore > 0) {
144
+ this.#errorScore -= this.#errorScoreDecrement;
143
145
  }
144
146
  this.maybeSelfRetire();
145
147
  }
@@ -151,9 +153,9 @@ export class Session {
151
153
  return {
152
154
  id: this.id,
153
155
  cookieJar: this.cookieJar.toJSON(),
154
- proxyInfo: this._proxyInfo,
156
+ proxyInfo: this.#proxyInfo,
155
157
  userData: this.userData,
156
- fingerprint: this._fingerprint,
158
+ fingerprint: this.#fingerprint,
157
159
  maxErrorScore: this.maxErrorScore,
158
160
  errorScoreDecrement: this.errorScoreDecrement,
159
161
  expiresAt: this.expiresAt.toISOString(),
@@ -161,7 +163,7 @@ export class Session {
161
163
  usageCount: this.usageCount,
162
164
  maxUsageCount: this.maxUsageCount,
163
165
  errorScore: this.errorScore,
164
- retired: this._retired,
166
+ retired: this.#retired,
165
167
  };
166
168
  }
167
169
  /**
@@ -172,19 +174,19 @@ export class Session {
172
174
  * For transient external failures (such as `5XX` responses), use `markBad()` instead.
173
175
  */
174
176
  retire() {
175
- if (this._retired)
177
+ if (this.#retired)
176
178
  return;
177
- this._errorScore += this._maxErrorScore;
178
- this._usageCount += 1;
179
- this._retired = true;
179
+ this.#errorScore += this.#maxErrorScore;
180
+ this.#usageCount += 1;
181
+ this.#retired = true;
180
182
  }
181
183
  /**
182
184
  * Increases usage and error count.
183
185
  * Should be used when the session has been used unsuccessfully. For example because of timeouts.
184
186
  */
185
187
  markBad() {
186
- this._errorScore += 1;
187
- this._usageCount += 1;
188
+ this.#errorScore += 1;
189
+ this.#usageCount += 1;
188
190
  this.maybeSelfRetire();
189
191
  }
190
192
  /**
@@ -193,18 +195,18 @@ export class Session {
193
195
  * a cookie header or elsewhere.
194
196
  * @returns Represents `Cookie` header.
195
197
  */
196
- getCookieString(url) {
197
- return this.cookieJar.getCookieStringSync(url, {});
198
+ async getCookieString(url) {
199
+ return this.cookieJar.getCookieString(url, {});
198
200
  }
199
201
  /**
200
202
  * Sets a cookie within this session for the specific URL.
201
203
  */
202
- setCookie(rawCookie, url) {
204
+ async setCookie(rawCookie, url) {
203
205
  try {
204
- this.cookieJar.setCookieSync(rawCookie, url);
206
+ await this.cookieJar.setCookie(rawCookie, url);
205
207
  }
206
208
  catch (e) {
207
- this.log.warning('Could not set cookie.', { url, error: e.message });
209
+ this.#log.warning('Could not set cookie.', { url, error: e.message });
208
210
  }
209
211
  }
210
212
  /**
@@ -112,24 +112,15 @@ export interface SessionPoolOptions {
112
112
  * @category Scaling
113
113
  */
114
114
  export declare class SessionPool implements ISessionPool {
115
- private static nextId;
115
+ #private;
116
116
  readonly id: string;
117
- private log;
118
117
  private maxPoolSize;
119
118
  private createSessionFunction;
120
119
  private keyValueStore?;
121
- private sessions;
122
120
  private sessionMap;
123
121
  private sessionOptions;
124
122
  private persistStateKeyValueStoreId?;
125
123
  private persistStateKey;
126
- private listener?;
127
- private events;
128
- private persistenceOptions;
129
- private sessionReuseStrategy;
130
- private initPromise?;
131
- private queue;
132
- private roundRobinIndex;
133
124
  constructor(options?: SessionPoolOptions);
134
125
  /**
135
126
  * Gets count of usable sessions in the pool.
@@ -190,8 +181,11 @@ export declare class SessionPool implements ISessionPool {
190
181
  /**
191
182
  * Removes listener from `persistState` event.
192
183
  * This function should be called after you are done with using the `SessionPool` instance.
184
+ * @param options - Set `persistState` to false when the final state was already persisted by the event manager.
193
185
  */
194
- teardown(): Promise<void>;
186
+ teardown({ persistState }?: {
187
+ persistState?: boolean;
188
+ }): Promise<void>;
195
189
  /**
196
190
  * Removes retired `Session` instances from `SessionPool`.
197
191
  */
@@ -222,7 +216,7 @@ export declare class SessionPool implements ISessionPool {
222
216
  * through `maybeLoadSessionPool` naturally wins because it arrives in
223
217
  * `perCallOptions`.
224
218
  */
225
- private _invokeCreateSessionFunction;
219
+ private invokeCreateSessionFunction;
226
220
  /**
227
221
  * Creates new session and adds it to the pool.
228
222
  * @returns Newly created `Session` instance.