@crawlee/core 4.0.0-beta.8 → 4.0.0-beta.81
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 +14 -15
- package/autoscaling/autoscaled_pool.js +37 -36
- package/autoscaling/client_load_signal.d.ts +25 -0
- package/autoscaling/client_load_signal.js +36 -0
- package/autoscaling/cpu_load_signal.d.ts +28 -0
- package/autoscaling/cpu_load_signal.js +24 -0
- package/autoscaling/event_loop_load_signal.d.ts +23 -0
- package/autoscaling/event_loop_load_signal.js +35 -0
- package/autoscaling/index.d.ts +5 -1
- package/autoscaling/index.js +5 -1
- package/autoscaling/load_signal.d.ts +99 -0
- package/autoscaling/load_signal.js +135 -0
- package/autoscaling/memory_load_signal.d.ts +43 -0
- package/autoscaling/memory_load_signal.js +102 -0
- package/autoscaling/snapshotter.d.ts +29 -91
- package/autoscaling/snapshotter.js +65 -204
- package/autoscaling/system_status.d.ts +22 -37
- package/autoscaling/system_status.js +49 -87
- package/configuration.d.ts +88 -228
- package/configuration.js +162 -224
- package/cookie_utils.d.ts +4 -3
- package/cookie_utils.js +20 -13
- package/crawlers/context_pipeline.d.ts +70 -0
- package/crawlers/context_pipeline.js +122 -0
- package/crawlers/crawler_commons.d.ts +20 -30
- package/crawlers/crawler_commons.js +12 -21
- package/crawlers/crawler_utils.d.ts +2 -3
- package/crawlers/crawler_utils.js +1 -2
- package/crawlers/error_snapshotter.d.ts +3 -3
- package/crawlers/error_snapshotter.js +2 -3
- package/crawlers/error_tracker.d.ts +2 -2
- package/crawlers/error_tracker.js +0 -1
- package/crawlers/index.d.ts +1 -2
- package/crawlers/index.js +1 -2
- package/crawlers/internals/types.d.ts +7 -0
- package/crawlers/internals/types.js +1 -0
- package/crawlers/statistics.d.ts +28 -23
- package/crawlers/statistics.js +38 -34
- package/enqueue_links/enqueue_links.d.ts +44 -22
- package/enqueue_links/enqueue_links.js +51 -30
- package/enqueue_links/index.d.ts +0 -1
- package/enqueue_links/index.js +0 -1
- package/enqueue_links/shared.d.ts +25 -9
- package/enqueue_links/shared.js +69 -38
- package/errors.d.ts +53 -4
- package/errors.js +70 -5
- package/events/event_manager.d.ts +34 -8
- package/events/event_manager.js +8 -10
- package/events/index.d.ts +0 -1
- package/events/index.js +0 -1
- package/events/local_event_manager.d.ts +15 -5
- package/events/local_event_manager.js +37 -40
- package/index.d.ts +4 -3
- package/index.js +3 -2
- package/log.d.ts +82 -3
- package/log.js +102 -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 +46 -0
- package/memory-storage/memory-storage.js +136 -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 +113 -0
- package/memory-storage/resource-clients/key-value-store.d.ts +63 -0
- package/memory-storage/resource-clients/key-value-store.js +203 -0
- package/memory-storage/resource-clients/request-queue.d.ts +96 -0
- package/memory-storage/resource-clients/request-queue.js +421 -0
- package/memory-storage/utils.d.ts +17 -0
- package/memory-storage/utils.js +42 -0
- package/package.json +12 -10
- package/proxy_configuration.d.ts +29 -152
- package/proxy_configuration.js +21 -173
- package/recoverable_state.d.ts +120 -0
- package/recoverable_state.js +141 -0
- package/request.d.ts +84 -13
- package/request.js +107 -28
- package/router.d.ts +118 -16
- package/router.js +124 -30
- package/serialization.d.ts +0 -1
- package/serialization.js +1 -2
- package/service_locator.d.ts +156 -0
- package/service_locator.js +238 -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 +37 -75
- package/session_pool/session.js +49 -102
- package/session_pool/session_pool.d.ts +85 -90
- package/session_pool/session_pool.js +131 -120
- package/storages/access_checking.d.ts +0 -1
- package/storages/access_checking.js +5 -2
- package/storages/dataset.d.ts +101 -51
- package/storages/dataset.js +168 -126
- package/storages/index.d.ts +8 -7
- package/storages/index.js +6 -7
- package/storages/key_value_store.d.ts +165 -36
- package/storages/key_value_store.js +269 -122
- 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 +23 -0
- package/storages/request_dedup_cache.js +48 -0
- package/storages/request_list.d.ts +53 -97
- package/storages/request_list.js +99 -75
- package/storages/request_loader.d.ts +96 -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 +106 -0
- package/storages/request_manager_tandem.js +197 -0
- package/storages/request_queue.d.ts +290 -47
- package/storages/request_queue.js +628 -215
- package/storages/{sitemap_request_list.d.ts → sitemap_request_loader.d.ts} +28 -24
- package/storages/{sitemap_request_list.js → sitemap_request_loader.js} +49 -46
- package/storages/storage_instance_manager.d.ts +91 -0
- package/storages/storage_instance_manager.js +258 -0
- package/storages/storage_stats.d.ts +48 -0
- package/storages/storage_stats.js +29 -0
- package/storages/utils.d.ts +51 -6
- package/storages/utils.js +60 -9
- 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 +1 -2
- package/typedefs.js +0 -1
- package/validators.d.ts +8 -1
- package/validators.js +10 -3
- 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/crawler_commons.d.ts.map +0 -1
- package/crawlers/crawler_commons.js.map +0 -1
- package/crawlers/crawler_extension.d.ts +0 -12
- package/crawlers/crawler_extension.d.ts.map +0 -1
- package/crawlers/crawler_extension.js +0 -14
- package/crawlers/crawler_extension.js.map +0 -1
- package/crawlers/crawler_utils.d.ts.map +0 -1
- 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/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 -134
- package/http_clients/base-http-client.d.ts.map +0 -1
- package/http_clients/base-http-client.js +0 -33
- 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 -15
- package/http_clients/got-scraping-http-client.d.ts.map +0 -1
- package/http_clients/got-scraping-http-client.js +0 -69
- 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.map +0 -1
- 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 -307
- 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.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/README.md
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
<h1 align="center">
|
|
2
2
|
<a href="https://crawlee.dev">
|
|
3
3
|
<picture>
|
|
4
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/apify/crawlee/master/website/static/img/crawlee-dark.svg?sanitize=true"
|
|
5
|
-
<img alt="Crawlee" src="https://raw.githubusercontent.com/apify/crawlee/master/website/static/img/crawlee-light.svg?sanitize=true" width="500"
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/apify/crawlee/master/website/static/img/crawlee-dark.svg?sanitize=true" />
|
|
5
|
+
<img alt="Crawlee" src="https://raw.githubusercontent.com/apify/crawlee/master/website/static/img/crawlee-light.svg?sanitize=true" width="500" />
|
|
6
6
|
</picture>
|
|
7
7
|
</a>
|
|
8
|
-
<br
|
|
8
|
+
<br />
|
|
9
9
|
<small>A web scraping and browser automation library</small>
|
|
10
10
|
</h1>
|
|
11
11
|
|
|
12
|
-
<p align=center>
|
|
13
|
-
<a href="https://
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://trendshift.io/repositories/5179" target="_blank"><img src="https://trendshift.io/api/badge/repositories/5179" alt="apify%2Fcrawlee | Trendshift" width="250" height="55"/></a>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<a href="https://www.npmjs.com/package/@crawlee/core" rel="nofollow"><img src="https://img.shields.io/npm/v/@crawlee/core.svg" alt="NPM latest version" data-canonical-src="https://img.shields.io/npm/v/@crawlee/core/next.svg" /></a>
|
|
18
|
+
<a href="https://www.npmjs.com/package/@crawlee/core" rel="nofollow"><img src="https://img.shields.io/npm/dm/@crawlee/core.svg" alt="Downloads" data-canonical-src="https://img.shields.io/npm/dm/@crawlee/core.svg" /></a>
|
|
19
|
+
<a href="https://discord.gg/jyEM2PRvMU" rel="nofollow"><img src="https://img.shields.io/discord/801163717915574323?label=discord" alt="Chat on discord" data-canonical-src="https://img.shields.io/discord/801163717915574323?label=discord" /></a>
|
|
20
|
+
<a href="https://github.com/apify/crawlee/actions/workflows/test-ci.yml"><img src="https://github.com/apify/crawlee/actions/workflows/test-ci.yml/badge.svg?branch=master" alt="Build Status" /></a>
|
|
17
21
|
</p>
|
|
18
22
|
|
|
19
23
|
Crawlee covers your crawling and scraping end-to-end and **helps you build reliable scrapers. Fast.**
|
|
@@ -24,7 +28,7 @@ Crawlee is available as the [`crawlee`](https://www.npmjs.com/package/crawlee) N
|
|
|
24
28
|
|
|
25
29
|
> 👉 **View full documentation, guides and examples on the [Crawlee project website](https://crawlee.dev)** 👈
|
|
26
30
|
|
|
27
|
-
>
|
|
31
|
+
> Do you prefer 🐍 Python instead of JavaScript? [👉 Checkout Crawlee for Python 👈](https://github.com/apify/crawlee-python).
|
|
28
32
|
|
|
29
33
|
## Installation
|
|
30
34
|
|
|
@@ -85,7 +89,7 @@ By default, Crawlee stores data to `./storage` in the current working directory.
|
|
|
85
89
|
We provide automated beta builds for every merged code change in Crawlee. You can find them in the npm [list of releases](https://www.npmjs.com/package/crawlee?activeTab=versions). If you want to test new features or bug fixes before we release them, feel free to install a beta build like this:
|
|
86
90
|
|
|
87
91
|
```bash
|
|
88
|
-
npm install crawlee@
|
|
92
|
+
npm install crawlee@next
|
|
89
93
|
```
|
|
90
94
|
|
|
91
95
|
If you also use the [Apify SDK](https://github.com/apify/apify-sdk-js), you need to specify dependency overrides in your `package.json` file so that you don't end up with multiple versions of Crawlee installed:
|
|
@@ -94,9 +98,9 @@ If you also use the [Apify SDK](https://github.com/apify/apify-sdk-js), you need
|
|
|
94
98
|
{
|
|
95
99
|
"overrides": {
|
|
96
100
|
"apify": {
|
|
97
|
-
"@crawlee/core": "
|
|
98
|
-
"@crawlee/types": "
|
|
99
|
-
"@crawlee/utils": "
|
|
101
|
+
"@crawlee/core": "$crawlee",
|
|
102
|
+
"@crawlee/types": "$crawlee",
|
|
103
|
+
"@crawlee/utils": "$crawlee"
|
|
100
104
|
}
|
|
101
105
|
}
|
|
102
106
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import { Configuration } from '../configuration.js';
|
|
1
|
+
import type { CrawleeLogger } from '../log.js';
|
|
3
2
|
import type { SnapshotterOptions } from './snapshotter.js';
|
|
4
|
-
import type {
|
|
3
|
+
import type { SystemStatusOptions } from './system_status.js';
|
|
5
4
|
export interface AutoscaledPoolOptions {
|
|
6
5
|
/**
|
|
7
6
|
* A function that performs an asynchronous resource-intensive task.
|
|
@@ -99,7 +98,7 @@ export interface AutoscaledPoolOptions {
|
|
|
99
98
|
* By default, this is set to `Infinity`, but you can pass any positive, non-zero integer.
|
|
100
99
|
*/
|
|
101
100
|
maxTasksPerMinute?: number;
|
|
102
|
-
log?:
|
|
101
|
+
log?: CrawleeLogger;
|
|
103
102
|
}
|
|
104
103
|
/**
|
|
105
104
|
* Manages a pool of asynchronous resource-intensive tasks that are executed in parallel.
|
|
@@ -150,7 +149,6 @@ export interface AutoscaledPoolOptions {
|
|
|
150
149
|
* @category Scaling
|
|
151
150
|
*/
|
|
152
151
|
export declare class AutoscaledPool {
|
|
153
|
-
private readonly config;
|
|
154
152
|
private readonly log;
|
|
155
153
|
private readonly desiredConcurrencyRatio;
|
|
156
154
|
private readonly scaleUpStepRatio;
|
|
@@ -172,6 +170,8 @@ export declare class AutoscaledPool {
|
|
|
172
170
|
private resolve;
|
|
173
171
|
private reject;
|
|
174
172
|
private snapshotter;
|
|
173
|
+
/** Additional SystemStatus loadSignals - tracked here for initialization and cleanup */
|
|
174
|
+
private loadSignals;
|
|
175
175
|
private systemStatus;
|
|
176
176
|
private autoscaleInterval;
|
|
177
177
|
private maybeRunInterval;
|
|
@@ -179,7 +179,7 @@ export declare class AutoscaledPool {
|
|
|
179
179
|
private queryingIsFinished;
|
|
180
180
|
private tasksDonePerSecondInterval?;
|
|
181
181
|
private _tasksPerMinute;
|
|
182
|
-
constructor(options: AutoscaledPoolOptions
|
|
182
|
+
constructor(options: AutoscaledPoolOptions);
|
|
183
183
|
/**
|
|
184
184
|
* Gets the minimum number of tasks running in parallel.
|
|
185
185
|
*/
|
|
@@ -262,39 +262,38 @@ export declare class AutoscaledPool {
|
|
|
262
262
|
*
|
|
263
263
|
* It doesn't allow multiple concurrent runs of this method.
|
|
264
264
|
*/
|
|
265
|
-
|
|
265
|
+
private maybeRunTask;
|
|
266
266
|
/**
|
|
267
267
|
* Gets called every autoScaleIntervalSecs and evaluates the current system status.
|
|
268
268
|
* If the system IS NOT overloaded and the settings allow it, it scales up.
|
|
269
269
|
* If the system IS overloaded and the settings allow it, it scales down.
|
|
270
270
|
*/
|
|
271
|
-
|
|
271
|
+
private autoscale;
|
|
272
272
|
/**
|
|
273
273
|
* Scales the pool up by increasing
|
|
274
274
|
* the desired concurrency by the scaleUpStepRatio.
|
|
275
275
|
*
|
|
276
276
|
* @param systemStatus for logging
|
|
277
277
|
*/
|
|
278
|
-
|
|
278
|
+
private scaleUp;
|
|
279
279
|
/**
|
|
280
280
|
* Scales the pool down by decreasing
|
|
281
281
|
* the desired concurrency by the scaleDownStepRatio.
|
|
282
282
|
*
|
|
283
283
|
* @param systemStatus for logging
|
|
284
284
|
*/
|
|
285
|
-
|
|
285
|
+
private scaleDown;
|
|
286
286
|
/**
|
|
287
287
|
* If there are no running tasks and this.isFinishedFunction() returns true then closes
|
|
288
288
|
* the pool and resolves the pool's promise returned by the run() method.
|
|
289
289
|
*
|
|
290
290
|
* It doesn't allow multiple concurrent runs of this method.
|
|
291
291
|
*/
|
|
292
|
-
|
|
292
|
+
private maybeFinish;
|
|
293
293
|
/**
|
|
294
294
|
* Cleans up resources.
|
|
295
295
|
*/
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
296
|
+
private destroy;
|
|
297
|
+
private incrementTasksDonePerSecond;
|
|
298
|
+
private get isOverMaxRequestLimit();
|
|
299
299
|
}
|
|
300
|
-
//# sourceMappingURL=autoscaled_pool.d.ts.map
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import ow from 'ow';
|
|
2
2
|
import { addTimeoutToPromise } from '@apify/timeout';
|
|
3
3
|
import { betterClearInterval, betterSetInterval } from '@apify/utilities';
|
|
4
|
-
import { Configuration } from '../configuration.js';
|
|
5
4
|
import { CriticalError } from '../errors.js';
|
|
6
|
-
import {
|
|
5
|
+
import { serviceLocator } from '../service_locator.js';
|
|
7
6
|
import { Snapshotter } from './snapshotter.js';
|
|
8
7
|
import { SystemStatus } from './system_status.js';
|
|
9
8
|
/**
|
|
@@ -55,7 +54,6 @@ import { SystemStatus } from './system_status.js';
|
|
|
55
54
|
* @category Scaling
|
|
56
55
|
*/
|
|
57
56
|
export class AutoscaledPool {
|
|
58
|
-
config;
|
|
59
57
|
log;
|
|
60
58
|
// Configurable properties.
|
|
61
59
|
desiredConcurrencyRatio;
|
|
@@ -79,6 +77,8 @@ export class AutoscaledPool {
|
|
|
79
77
|
resolve = null;
|
|
80
78
|
reject = null;
|
|
81
79
|
snapshotter;
|
|
80
|
+
/** Additional SystemStatus loadSignals - tracked here for initialization and cleanup */
|
|
81
|
+
loadSignals;
|
|
82
82
|
systemStatus;
|
|
83
83
|
autoscaleInterval;
|
|
84
84
|
maybeRunInterval;
|
|
@@ -86,8 +86,7 @@ export class AutoscaledPool {
|
|
|
86
86
|
queryingIsFinished;
|
|
87
87
|
tasksDonePerSecondInterval;
|
|
88
88
|
_tasksPerMinute = Array.from({ length: 60 }, () => 0);
|
|
89
|
-
constructor(options
|
|
90
|
-
this.config = config;
|
|
89
|
+
constructor(options) {
|
|
91
90
|
ow(options, ow.object.exactShape({
|
|
92
91
|
runTaskFunction: ow.function,
|
|
93
92
|
isFinishedFunction: ow.function,
|
|
@@ -107,7 +106,7 @@ export class AutoscaledPool {
|
|
|
107
106
|
log: ow.optional.object,
|
|
108
107
|
maxTasksPerMinute: ow.optional.number.integerOrInfinite.greaterThanOrEqual(1),
|
|
109
108
|
}));
|
|
110
|
-
const { runTaskFunction, isFinishedFunction, isTaskReadyFunction, maxConcurrency = 200, minConcurrency = 1, desiredConcurrency, desiredConcurrencyRatio = 0.9, scaleUpStepRatio = 0.05, scaleDownStepRatio = 0.05, maybeRunIntervalSecs = 0.5, loggingIntervalSecs = 60, taskTimeoutSecs = 0, autoscaleIntervalSecs = 10, systemStatusOptions, snapshotterOptions, log =
|
|
109
|
+
const { runTaskFunction, isFinishedFunction, isTaskReadyFunction, maxConcurrency = 200, minConcurrency = 1, desiredConcurrency, desiredConcurrencyRatio = 0.9, scaleUpStepRatio = 0.05, scaleDownStepRatio = 0.05, maybeRunIntervalSecs = 0.5, loggingIntervalSecs = 60, taskTimeoutSecs = 0, autoscaleIntervalSecs = 10, systemStatusOptions, snapshotterOptions, log = serviceLocator.getLogger(), maxTasksPerMinute = Infinity, } = options;
|
|
111
110
|
this.log = log.child({ prefix: 'AutoscaledPool' });
|
|
112
111
|
// Configurable properties.
|
|
113
112
|
this.desiredConcurrencyRatio = desiredConcurrencyRatio;
|
|
@@ -129,19 +128,17 @@ export class AutoscaledPool {
|
|
|
129
128
|
this.isStopped = false;
|
|
130
129
|
this.resolve = null;
|
|
131
130
|
this.reject = null;
|
|
132
|
-
this.
|
|
133
|
-
this.
|
|
134
|
-
this.
|
|
131
|
+
this.autoscale = this.autoscale.bind(this);
|
|
132
|
+
this.maybeRunTask = this.maybeRunTask.bind(this);
|
|
133
|
+
this.incrementTasksDonePerSecond = this.incrementTasksDonePerSecond.bind(this);
|
|
135
134
|
// Create instances with correct options.
|
|
136
135
|
const ssoCopy = { ...systemStatusOptions };
|
|
137
136
|
ssoCopy.snapshotter ??= new Snapshotter({
|
|
138
137
|
...snapshotterOptions,
|
|
139
138
|
log: this.log,
|
|
140
|
-
config: this.config,
|
|
141
|
-
client: this.config.getStorageClient(),
|
|
142
139
|
});
|
|
143
|
-
ssoCopy.config ??= this.config;
|
|
144
140
|
this.snapshotter = ssoCopy.snapshotter;
|
|
141
|
+
this.loadSignals = ssoCopy.loadSignals ?? [];
|
|
145
142
|
this.systemStatus = new SystemStatus(ssoCopy);
|
|
146
143
|
}
|
|
147
144
|
/**
|
|
@@ -204,15 +201,16 @@ export class AutoscaledPool {
|
|
|
204
201
|
this.reject = reject;
|
|
205
202
|
});
|
|
206
203
|
await this.snapshotter.start();
|
|
204
|
+
await Promise.all(this.loadSignals.map((s) => s.start()));
|
|
207
205
|
// This interval checks the system status and updates the desired concurrency accordingly.
|
|
208
|
-
this.autoscaleInterval = betterSetInterval(this.
|
|
206
|
+
this.autoscaleInterval = betterSetInterval(this.autoscale, this.autoscaleIntervalMillis);
|
|
209
207
|
// This is here because if we scale down to let's say 1, then after each promise is finished
|
|
210
|
-
// this.
|
|
208
|
+
// this.maybeRunTask() doesn't trigger another one. So if that 1 instance gets stuck it results
|
|
211
209
|
// in the crawler getting stuck and even after scaling up it never triggers another promise.
|
|
212
|
-
this.maybeRunInterval = betterSetInterval(this.
|
|
210
|
+
this.maybeRunInterval = betterSetInterval(this.maybeRunTask, this.maybeRunIntervalMillis);
|
|
213
211
|
if (this.maxTasksPerMinute !== Infinity) {
|
|
214
212
|
// Start the interval that resets the counter of tasks per minute.
|
|
215
|
-
this.tasksDonePerSecondInterval = betterSetInterval(this.
|
|
213
|
+
this.tasksDonePerSecondInterval = betterSetInterval(this.incrementTasksDonePerSecond, 1000);
|
|
216
214
|
}
|
|
217
215
|
try {
|
|
218
216
|
await poolPromise;
|
|
@@ -220,7 +218,7 @@ export class AutoscaledPool {
|
|
|
220
218
|
finally {
|
|
221
219
|
// If resolve is null, the pool is already destroyed.
|
|
222
220
|
if (this.resolve)
|
|
223
|
-
await this.
|
|
221
|
+
await this.destroy();
|
|
224
222
|
}
|
|
225
223
|
}
|
|
226
224
|
/**
|
|
@@ -238,7 +236,7 @@ export class AutoscaledPool {
|
|
|
238
236
|
this.isStopped = true;
|
|
239
237
|
if (this.resolve) {
|
|
240
238
|
this.resolve();
|
|
241
|
-
await this.
|
|
239
|
+
await this.destroy();
|
|
242
240
|
}
|
|
243
241
|
}
|
|
244
242
|
/**
|
|
@@ -258,14 +256,17 @@ export class AutoscaledPool {
|
|
|
258
256
|
this.isStopped = true;
|
|
259
257
|
await new Promise((resolve, reject) => {
|
|
260
258
|
let timeout;
|
|
259
|
+
let interval;
|
|
261
260
|
if (timeoutSecs) {
|
|
262
261
|
timeout = setTimeout(() => {
|
|
262
|
+
// Clean up the polling interval to prevent it from leaking on timeout.
|
|
263
|
+
clearInterval(interval);
|
|
263
264
|
const err = new Error("The pool's running tasks did not finish" +
|
|
264
265
|
`in ${timeoutSecs} secs after pool.pause() invocation.`);
|
|
265
266
|
reject(err);
|
|
266
267
|
}, timeoutSecs);
|
|
267
268
|
}
|
|
268
|
-
|
|
269
|
+
interval = setInterval(() => {
|
|
269
270
|
if (this._currentConcurrency <= 0) {
|
|
270
271
|
// Clean up timeout and interval to prevent process hanging.
|
|
271
272
|
if (timeout)
|
|
@@ -290,7 +291,7 @@ export class AutoscaledPool {
|
|
|
290
291
|
* every `maybeRunIntervalSecs` seconds. If you want to trigger the processing immediately, use this method.
|
|
291
292
|
*/
|
|
292
293
|
async notify() {
|
|
293
|
-
setImmediate(this.
|
|
294
|
+
setImmediate(this.maybeRunTask);
|
|
294
295
|
}
|
|
295
296
|
/**
|
|
296
297
|
* Starts a new task
|
|
@@ -300,7 +301,7 @@ export class AutoscaledPool {
|
|
|
300
301
|
*
|
|
301
302
|
* It doesn't allow multiple concurrent runs of this method.
|
|
302
303
|
*/
|
|
303
|
-
async
|
|
304
|
+
async maybeRunTask(intervalCallback) {
|
|
304
305
|
this.log.perf('Attempting to run a task.');
|
|
305
306
|
// Check if the function was invoked by the maybeRunInterval and use an empty function if not.
|
|
306
307
|
const done = intervalCallback || (() => { });
|
|
@@ -351,12 +352,12 @@ export class AutoscaledPool {
|
|
|
351
352
|
this.log.perf('Task will not run. No tasks are ready.');
|
|
352
353
|
done();
|
|
353
354
|
// No tasks could mean that we're finished with all tasks.
|
|
354
|
-
return this.
|
|
355
|
+
return this.maybeFinish();
|
|
355
356
|
}
|
|
356
357
|
// - we have already reached the maximum tasks per minute
|
|
357
358
|
// we need to check this *after* checking if a task is ready to prevent hanging the pool
|
|
358
359
|
// for an extra minute if there are no more tasks
|
|
359
|
-
if (this.
|
|
360
|
+
if (this.isOverMaxRequestLimit) {
|
|
360
361
|
this.log.perf('Task will not run. Maximum tasks per minute reached.');
|
|
361
362
|
return done();
|
|
362
363
|
}
|
|
@@ -366,7 +367,7 @@ export class AutoscaledPool {
|
|
|
366
367
|
this._tasksPerMinute[0]++;
|
|
367
368
|
// Try to run next task to build up concurrency,
|
|
368
369
|
// but defer it so it doesn't create a cycle.
|
|
369
|
-
setImmediate(this.
|
|
370
|
+
setImmediate(this.maybeRunTask);
|
|
370
371
|
// We need to restart interval here, so that it doesn't get blocked by a stalled task.
|
|
371
372
|
done();
|
|
372
373
|
// Execute the current task.
|
|
@@ -380,7 +381,7 @@ export class AutoscaledPool {
|
|
|
380
381
|
this.log.perf('Task finished.');
|
|
381
382
|
this._currentConcurrency--;
|
|
382
383
|
// Run task after the previous one finished.
|
|
383
|
-
setImmediate(this.
|
|
384
|
+
setImmediate(this.maybeRunTask);
|
|
384
385
|
}
|
|
385
386
|
catch (e) {
|
|
386
387
|
const err = e;
|
|
@@ -403,12 +404,12 @@ export class AutoscaledPool {
|
|
|
403
404
|
* If the system IS NOT overloaded and the settings allow it, it scales up.
|
|
404
405
|
* If the system IS overloaded and the settings allow it, it scales down.
|
|
405
406
|
*/
|
|
406
|
-
|
|
407
|
+
autoscale(intervalCallback) {
|
|
407
408
|
// Don't scale if paused.
|
|
408
409
|
if (this.isStopped)
|
|
409
410
|
return intervalCallback();
|
|
410
411
|
// Don't scale if we've hit the maximum requests per minute
|
|
411
|
-
if (this.
|
|
412
|
+
if (this.isOverMaxRequestLimit)
|
|
412
413
|
return intervalCallback();
|
|
413
414
|
// Only scale up if:
|
|
414
415
|
// - system has not been overloaded lately.
|
|
@@ -420,14 +421,14 @@ export class AutoscaledPool {
|
|
|
420
421
|
const minCurrentConcurrency = Math.floor(this._desiredConcurrency * this.desiredConcurrencyRatio);
|
|
421
422
|
const weAreReachingDesiredConcurrency = this._currentConcurrency >= minCurrentConcurrency;
|
|
422
423
|
if (isSystemIdle && weAreNotAtMax && weAreReachingDesiredConcurrency)
|
|
423
|
-
this.
|
|
424
|
+
this.scaleUp(systemStatus);
|
|
424
425
|
// Always scale down if:
|
|
425
426
|
// - the system has been overloaded lately.
|
|
426
427
|
const isSystemOverloaded = !isSystemIdle;
|
|
427
428
|
// - we're over min concurrency.
|
|
428
429
|
const weAreNotAtMin = this._desiredConcurrency > this._minConcurrency;
|
|
429
430
|
if (isSystemOverloaded && weAreNotAtMin)
|
|
430
|
-
this.
|
|
431
|
+
this.scaleDown(systemStatus);
|
|
431
432
|
// On periodic intervals, print comprehensive log information
|
|
432
433
|
if (this.loggingIntervalMillis > 0) {
|
|
433
434
|
const now = Date.now();
|
|
@@ -452,7 +453,7 @@ export class AutoscaledPool {
|
|
|
452
453
|
*
|
|
453
454
|
* @param systemStatus for logging
|
|
454
455
|
*/
|
|
455
|
-
|
|
456
|
+
scaleUp(systemStatus) {
|
|
456
457
|
const step = Math.ceil(this._desiredConcurrency * this.scaleUpStepRatio);
|
|
457
458
|
this._desiredConcurrency = Math.min(this._maxConcurrency, this._desiredConcurrency + step);
|
|
458
459
|
this.log.debug('scaling up', {
|
|
@@ -467,7 +468,7 @@ export class AutoscaledPool {
|
|
|
467
468
|
*
|
|
468
469
|
* @param systemStatus for logging
|
|
469
470
|
*/
|
|
470
|
-
|
|
471
|
+
scaleDown(systemStatus) {
|
|
471
472
|
const step = Math.ceil(this._desiredConcurrency * this.scaleDownStepRatio);
|
|
472
473
|
this._desiredConcurrency = Math.max(this._minConcurrency, this._desiredConcurrency - step);
|
|
473
474
|
this.log.debug('scaling down', {
|
|
@@ -482,7 +483,7 @@ export class AutoscaledPool {
|
|
|
482
483
|
*
|
|
483
484
|
* It doesn't allow multiple concurrent runs of this method.
|
|
484
485
|
*/
|
|
485
|
-
async
|
|
486
|
+
async maybeFinish() {
|
|
486
487
|
if (this.queryingIsFinished)
|
|
487
488
|
return;
|
|
488
489
|
if (this._currentConcurrency > 0)
|
|
@@ -508,7 +509,7 @@ export class AutoscaledPool {
|
|
|
508
509
|
/**
|
|
509
510
|
* Cleans up resources.
|
|
510
511
|
*/
|
|
511
|
-
async
|
|
512
|
+
async destroy() {
|
|
512
513
|
this.resolve = null;
|
|
513
514
|
this.reject = null;
|
|
514
515
|
betterClearInterval(this.autoscaleInterval);
|
|
@@ -517,17 +518,17 @@ export class AutoscaledPool {
|
|
|
517
518
|
betterClearInterval(this.tasksDonePerSecondInterval);
|
|
518
519
|
if (this.snapshotter)
|
|
519
520
|
await this.snapshotter.stop();
|
|
521
|
+
await Promise.all(this.loadSignals.map((s) => s.stop()));
|
|
520
522
|
}
|
|
521
|
-
|
|
523
|
+
incrementTasksDonePerSecond(intervalCallback) {
|
|
522
524
|
this._tasksPerMinute.unshift(0);
|
|
523
525
|
this._tasksPerMinute.pop();
|
|
524
526
|
return intervalCallback();
|
|
525
527
|
}
|
|
526
|
-
get
|
|
528
|
+
get isOverMaxRequestLimit() {
|
|
527
529
|
if (this.maxTasksPerMinute === Infinity) {
|
|
528
530
|
return false;
|
|
529
531
|
}
|
|
530
532
|
return this._tasksPerMinute.reduce((acc, curr) => acc + curr, 0) >= this.maxTasksPerMinute;
|
|
531
533
|
}
|
|
532
534
|
}
|
|
533
|
-
//# sourceMappingURL=autoscaled_pool.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { StorageBackend } from '@crawlee/types';
|
|
2
|
+
import type { LoadSnapshot } from './load_signal.js';
|
|
3
|
+
import { SnapshotStore } from './load_signal.js';
|
|
4
|
+
export interface ClientSnapshot extends LoadSnapshot {
|
|
5
|
+
rateLimitErrorCount: number;
|
|
6
|
+
}
|
|
7
|
+
export interface ClientLoadSignalOptions {
|
|
8
|
+
client: StorageBackend;
|
|
9
|
+
clientSnapshotIntervalSecs?: number;
|
|
10
|
+
maxClientErrors?: number;
|
|
11
|
+
overloadedRatio?: number;
|
|
12
|
+
snapshotHistoryMillis?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Periodically checks the storage client for rate-limit errors (HTTP 429)
|
|
16
|
+
* and reports overload when the error delta exceeds a threshold.
|
|
17
|
+
*/
|
|
18
|
+
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
19
|
+
export declare function createClientLoadSignal(options: ClientLoadSignalOptions): Omit<import("./load_signal.js").LoadSignal, "getSample"> & {
|
|
20
|
+
store: SnapshotStore<ClientSnapshot>;
|
|
21
|
+
handle: (cb: () => unknown) => void;
|
|
22
|
+
getSample(sampleDurationMillis?: number): ClientSnapshot[];
|
|
23
|
+
};
|
|
24
|
+
/** @internal Return type for backward compat in Snapshotter facade */
|
|
25
|
+
export type ClientLoadSignal = ReturnType<typeof createClientLoadSignal>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { SnapshotStore } from './load_signal.js';
|
|
2
|
+
const CLIENT_RATE_LIMIT_ERROR_RETRY_COUNT = 2;
|
|
3
|
+
/**
|
|
4
|
+
* Periodically checks the storage client for rate-limit errors (HTTP 429)
|
|
5
|
+
* and reports overload when the error delta exceeds a threshold.
|
|
6
|
+
*/
|
|
7
|
+
export function createClientLoadSignal(options) {
|
|
8
|
+
const maxClientErrors = options.maxClientErrors ?? 3;
|
|
9
|
+
const signal = SnapshotStore.fromInterval({
|
|
10
|
+
name: 'clientInfo',
|
|
11
|
+
overloadedRatio: options.overloadedRatio ?? 0.3,
|
|
12
|
+
intervalMillis: (options.clientSnapshotIntervalSecs ?? 1) * 1000,
|
|
13
|
+
snapshotHistoryMillis: options.snapshotHistoryMillis,
|
|
14
|
+
handler(store, intervalCallback) {
|
|
15
|
+
const now = new Date();
|
|
16
|
+
const allErrorCounts = options.client.stats?.rateLimitErrors ?? [];
|
|
17
|
+
const currentErrCount = allErrorCounts[CLIENT_RATE_LIMIT_ERROR_RETRY_COUNT] || 0;
|
|
18
|
+
const snapshot = {
|
|
19
|
+
createdAt: now,
|
|
20
|
+
isOverloaded: false,
|
|
21
|
+
rateLimitErrorCount: currentErrCount,
|
|
22
|
+
};
|
|
23
|
+
const all = store.getAll();
|
|
24
|
+
const previousSnapshot = all[all.length - 1];
|
|
25
|
+
if (previousSnapshot) {
|
|
26
|
+
const { rateLimitErrorCount } = previousSnapshot;
|
|
27
|
+
const delta = currentErrCount - rateLimitErrorCount;
|
|
28
|
+
if (delta > maxClientErrors)
|
|
29
|
+
snapshot.isOverloaded = true;
|
|
30
|
+
}
|
|
31
|
+
store.push(snapshot, now);
|
|
32
|
+
intervalCallback();
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
return signal;
|
|
36
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Configuration } from '../configuration.js';
|
|
2
|
+
import type { LoadSnapshot } from './load_signal.js';
|
|
3
|
+
import { SnapshotStore } from './load_signal.js';
|
|
4
|
+
import type { SystemInfo } from './system_status.js';
|
|
5
|
+
export interface CpuSnapshot extends LoadSnapshot {
|
|
6
|
+
usedRatio: number;
|
|
7
|
+
ticks?: {
|
|
8
|
+
idle: number;
|
|
9
|
+
total: number;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export interface CpuLoadSignalOptions {
|
|
13
|
+
overloadedRatio?: number;
|
|
14
|
+
snapshotHistoryMillis?: number;
|
|
15
|
+
config: Configuration;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Tracks CPU usage via `SYSTEM_INFO` events and reports overload when
|
|
19
|
+
* the platform or local OS metrics indicate the CPU is overloaded.
|
|
20
|
+
*/
|
|
21
|
+
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
22
|
+
export declare function createCpuLoadSignal(options: CpuLoadSignalOptions): Omit<import("./load_signal.js").LoadSignal, "getSample"> & {
|
|
23
|
+
store: SnapshotStore<CpuSnapshot>;
|
|
24
|
+
handle: (payload: SystemInfo) => void;
|
|
25
|
+
getSample(sampleDurationMillis?: number): CpuSnapshot[];
|
|
26
|
+
};
|
|
27
|
+
/** @internal Return type for backward compat in Snapshotter facade */
|
|
28
|
+
export type CpuLoadSignal = ReturnType<typeof createCpuLoadSignal>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { serviceLocator } from '../service_locator.js';
|
|
2
|
+
import { SnapshotStore } from './load_signal.js';
|
|
3
|
+
/**
|
|
4
|
+
* Tracks CPU usage via `SYSTEM_INFO` events and reports overload when
|
|
5
|
+
* the platform or local OS metrics indicate the CPU is overloaded.
|
|
6
|
+
*/
|
|
7
|
+
export function createCpuLoadSignal(options) {
|
|
8
|
+
return SnapshotStore.fromEvent({
|
|
9
|
+
name: 'cpuInfo',
|
|
10
|
+
overloadedRatio: options.overloadedRatio ?? 0.4,
|
|
11
|
+
events: serviceLocator.getEventManager(),
|
|
12
|
+
event: "systemInfo" /* EventType.SYSTEM_INFO */,
|
|
13
|
+
snapshotHistoryMillis: options.snapshotHistoryMillis,
|
|
14
|
+
handler(store, systemInfo) {
|
|
15
|
+
const { cpuCurrentUsage, isCpuOverloaded } = systemInfo;
|
|
16
|
+
const createdAt = systemInfo.createdAt ? new Date(systemInfo.createdAt) : new Date();
|
|
17
|
+
store.push({
|
|
18
|
+
createdAt,
|
|
19
|
+
isOverloaded: isCpuOverloaded,
|
|
20
|
+
usedRatio: Math.ceil(cpuCurrentUsage / 100),
|
|
21
|
+
}, createdAt);
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { LoadSnapshot } from './load_signal.js';
|
|
2
|
+
import { SnapshotStore } from './load_signal.js';
|
|
3
|
+
export interface EventLoopSnapshot extends LoadSnapshot {
|
|
4
|
+
exceededMillis: number;
|
|
5
|
+
}
|
|
6
|
+
export interface EventLoopLoadSignalOptions {
|
|
7
|
+
eventLoopSnapshotIntervalSecs?: number;
|
|
8
|
+
maxBlockedMillis?: number;
|
|
9
|
+
overloadedRatio?: number;
|
|
10
|
+
snapshotHistoryMillis?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Periodically measures event loop delay and reports overload when the
|
|
14
|
+
* delay exceeds a configured threshold.
|
|
15
|
+
*/
|
|
16
|
+
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
17
|
+
export declare function createEventLoopLoadSignal(options?: EventLoopLoadSignalOptions): Omit<import("./load_signal.js").LoadSignal, "getSample"> & {
|
|
18
|
+
store: SnapshotStore<EventLoopSnapshot>;
|
|
19
|
+
handle: (cb: () => unknown) => void;
|
|
20
|
+
getSample(sampleDurationMillis?: number): EventLoopSnapshot[];
|
|
21
|
+
};
|
|
22
|
+
/** @internal Return type for backward compat in Snapshotter facade */
|
|
23
|
+
export type EventLoopLoadSignal = ReturnType<typeof createEventLoopLoadSignal>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { SnapshotStore } from './load_signal.js';
|
|
2
|
+
/**
|
|
3
|
+
* Periodically measures event loop delay and reports overload when the
|
|
4
|
+
* delay exceeds a configured threshold.
|
|
5
|
+
*/
|
|
6
|
+
export function createEventLoopLoadSignal(options = {}) {
|
|
7
|
+
const intervalMillis = (options.eventLoopSnapshotIntervalSecs ?? 0.5) * 1000;
|
|
8
|
+
const maxBlockedMillis = options.maxBlockedMillis ?? 50;
|
|
9
|
+
const signal = SnapshotStore.fromInterval({
|
|
10
|
+
name: 'eventLoopInfo',
|
|
11
|
+
overloadedRatio: options.overloadedRatio ?? 0.6,
|
|
12
|
+
intervalMillis,
|
|
13
|
+
snapshotHistoryMillis: options.snapshotHistoryMillis,
|
|
14
|
+
handler(store, intervalCallback) {
|
|
15
|
+
const now = new Date();
|
|
16
|
+
const snapshot = {
|
|
17
|
+
createdAt: now,
|
|
18
|
+
isOverloaded: false,
|
|
19
|
+
exceededMillis: 0,
|
|
20
|
+
};
|
|
21
|
+
const all = store.getAll();
|
|
22
|
+
const previousSnapshot = all[all.length - 1];
|
|
23
|
+
if (previousSnapshot) {
|
|
24
|
+
const { createdAt } = previousSnapshot;
|
|
25
|
+
const delta = now.getTime() - +createdAt - intervalMillis;
|
|
26
|
+
if (delta > maxBlockedMillis)
|
|
27
|
+
snapshot.isOverloaded = true;
|
|
28
|
+
snapshot.exceededMillis = Math.max(delta - maxBlockedMillis, 0);
|
|
29
|
+
}
|
|
30
|
+
store.push(snapshot, now);
|
|
31
|
+
intervalCallback();
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
return signal;
|
|
35
|
+
}
|
package/autoscaling/index.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export * from './autoscaled_pool.js';
|
|
2
|
+
export * from './client_load_signal.js';
|
|
3
|
+
export * from './cpu_load_signal.js';
|
|
4
|
+
export * from './event_loop_load_signal.js';
|
|
5
|
+
export * from './load_signal.js';
|
|
6
|
+
export * from './memory_load_signal.js';
|
|
2
7
|
export * from './snapshotter.js';
|
|
3
8
|
export * from './system_status.js';
|
|
4
|
-
//# sourceMappingURL=index.d.ts.map
|
package/autoscaling/index.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export * from './autoscaled_pool.js';
|
|
2
|
+
export * from './client_load_signal.js';
|
|
3
|
+
export * from './cpu_load_signal.js';
|
|
4
|
+
export * from './event_loop_load_signal.js';
|
|
5
|
+
export * from './load_signal.js';
|
|
6
|
+
export * from './memory_load_signal.js';
|
|
2
7
|
export * from './snapshotter.js';
|
|
3
8
|
export * from './system_status.js';
|
|
4
|
-
//# sourceMappingURL=index.js.map
|