@crawlee/core 4.0.0-beta.115 → 4.0.0-beta.116
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/autoscaling/cpu_load_signal.js +3 -2
- package/autoscaling/memory_load_signal.js +3 -2
- package/crawlers/statistics.js +3 -2
- package/events/event_manager.d.ts +1 -1
- package/events/event_manager.js +2 -2
- package/events/local_event_manager.js +2 -2
- package/package.json +5 -5
- package/recoverable_state.js +3 -3
- package/session_pool/session_pool.js +3 -2
- package/storages/request_list.js +3 -2
- package/storages/request_queue.js +2 -1
- package/storages/sitemap_request_loader.js +3 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EventType } from '../events/event_manager.js';
|
|
1
2
|
import { serviceLocator } from '../service_locator.js';
|
|
2
3
|
import { SnapshotStore } from './load_signal.js';
|
|
3
4
|
/**
|
|
@@ -24,10 +25,10 @@ export class CpuLoadSignal {
|
|
|
24
25
|
// Resolved here rather than in the constructor, so an instance built ahead of time (to be wrapped, or shared
|
|
25
26
|
// between systems) cannot capture whichever event manager happened to be registered at that moment.
|
|
26
27
|
this.#events = serviceLocator.getEventManager();
|
|
27
|
-
this.#events.on(
|
|
28
|
+
this.#events.on(EventType.SYSTEM_INFO, this.handle);
|
|
28
29
|
}
|
|
29
30
|
async stop() {
|
|
30
|
-
this.#events?.off(
|
|
31
|
+
this.#events?.off(EventType.SYSTEM_INFO, this.handle);
|
|
31
32
|
this.#events = undefined;
|
|
32
33
|
}
|
|
33
34
|
getSample(sampleDurationMillis) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EventType } from '../events/event_manager.js';
|
|
1
2
|
import { serviceLocator } from '../service_locator.js';
|
|
2
3
|
import { getMemoryInfo } from '../system-info/memory-info.js';
|
|
3
4
|
import { isContainerized } from '../system-info/runtime.js';
|
|
@@ -54,10 +55,10 @@ export class MemoryLoadSignal {
|
|
|
54
55
|
// Fallback memory measurement in case memTotalBytes is missing from SystemInfo.
|
|
55
56
|
this.#maxMemoryBytes = await this.getTotalMemoryBytes();
|
|
56
57
|
}
|
|
57
|
-
this.#events.on(
|
|
58
|
+
this.#events.on(EventType.SYSTEM_INFO, this.handle);
|
|
58
59
|
}
|
|
59
60
|
async stop() {
|
|
60
|
-
this.#events?.off(
|
|
61
|
+
this.#events?.off(EventType.SYSTEM_INFO, this.handle);
|
|
61
62
|
this.#events = undefined;
|
|
62
63
|
}
|
|
63
64
|
getSample(sampleDurationMillis) {
|
package/crawlers/statistics.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import ow from 'ow';
|
|
2
|
+
import { EventType } from '../events/event_manager.js';
|
|
2
3
|
import { serviceLocator } from '../service_locator.js';
|
|
3
4
|
import { KeyValueStore } from '../storages/key_value_store.js';
|
|
4
5
|
import { ErrorTracker } from './error_tracker.js';
|
|
@@ -238,7 +239,7 @@ export class Statistics {
|
|
|
238
239
|
}
|
|
239
240
|
if (this.#persistenceOptions.enable) {
|
|
240
241
|
await this.maybeLoadStatistics();
|
|
241
|
-
this.events.on(
|
|
242
|
+
this.events.on(EventType.PERSIST_STATE, this.#listener);
|
|
242
243
|
}
|
|
243
244
|
this.#logInterval = setInterval(() => {
|
|
244
245
|
this.log.info(this.#logMessage, {
|
|
@@ -320,7 +321,7 @@ export class Statistics {
|
|
|
320
321
|
// this can be called before a call to startCapturing happens (or in a 'finally' block)
|
|
321
322
|
// Only unsubscribe if event manager was already resolved — avoid eagerly resolving it
|
|
322
323
|
// (e.g. during the constructor's reset() call, which would capture the wrong context)
|
|
323
|
-
this.#events?.off(
|
|
324
|
+
this.#events?.off(EventType.PERSIST_STATE, this.#listener);
|
|
324
325
|
if (this.#logInterval) {
|
|
325
326
|
clearInterval(this.#logInterval);
|
|
326
327
|
this.#logInterval = null;
|
|
@@ -4,7 +4,7 @@ export interface EventManagerOptions {
|
|
|
4
4
|
/** Interval between emitted `persistState` events in milliseconds. */
|
|
5
5
|
persistStateIntervalMillis: number;
|
|
6
6
|
}
|
|
7
|
-
export declare
|
|
7
|
+
export declare enum EventType {
|
|
8
8
|
PERSIST_STATE = "persistState",
|
|
9
9
|
SYSTEM_INFO = "systemInfo",
|
|
10
10
|
MIGRATING = "migrating",
|
package/events/event_manager.js
CHANGED
|
@@ -29,7 +29,7 @@ export class EventManager {
|
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
31
|
this.intervals.persistState = betterSetInterval((intervalCallback) => {
|
|
32
|
-
this.emit(
|
|
32
|
+
this.emit(EventType.PERSIST_STATE, { isMigrating: false });
|
|
33
33
|
intervalCallback();
|
|
34
34
|
}, this.#persistStateIntervalMillis);
|
|
35
35
|
this.initialized = true;
|
|
@@ -45,7 +45,7 @@ export class EventManager {
|
|
|
45
45
|
betterClearInterval(this.intervals.persistState);
|
|
46
46
|
this.initialized = false;
|
|
47
47
|
// Emit final PERSIST_STATE event
|
|
48
|
-
this.emit(
|
|
48
|
+
this.emit(EventType.PERSIST_STATE, { isMigrating: false });
|
|
49
49
|
// Wait for PERSIST_STATE to process
|
|
50
50
|
await this.waitForAllListenersToComplete();
|
|
51
51
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { betterClearInterval, betterSetInterval } from '@apify/utilities';
|
|
2
2
|
import { serviceLocator } from '../service_locator.js';
|
|
3
|
-
import { EventManager } from './event_manager.js';
|
|
3
|
+
import { EventManager, EventType } from './event_manager.js';
|
|
4
4
|
export class LocalEventManager extends EventManager {
|
|
5
5
|
#systemInfoIntervalMillis;
|
|
6
6
|
constructor(options) {
|
|
@@ -47,7 +47,7 @@ export class LocalEventManager extends EventManager {
|
|
|
47
47
|
const info = await this.createSystemInfo({
|
|
48
48
|
maxUsedCpuRatio: serviceLocator.getConfiguration().maxUsedCpuRatio,
|
|
49
49
|
});
|
|
50
|
-
this.events.emit(
|
|
50
|
+
this.events.emit(EventType.SYSTEM_INFO, info);
|
|
51
51
|
intervalCallback();
|
|
52
52
|
}
|
|
53
53
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crawlee/core",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.116",
|
|
4
4
|
"description": "The scalable web crawling and scraping library for JavaScript/Node.js. Enables development of data extraction and web automation jobs (not only) with headless Chrome and Puppeteer.",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22.0.0"
|
|
@@ -52,9 +52,9 @@
|
|
|
52
52
|
"@apify/log": "^2.5.18",
|
|
53
53
|
"@apify/timeout": "^0.4.4",
|
|
54
54
|
"@apify/utilities": "^2.15.5",
|
|
55
|
-
"@crawlee/fs-storage": "4.0.0-beta.
|
|
56
|
-
"@crawlee/types": "4.0.0-beta.
|
|
57
|
-
"@crawlee/utils": "4.0.0-beta.
|
|
55
|
+
"@crawlee/fs-storage": "4.0.0-beta.116",
|
|
56
|
+
"@crawlee/types": "4.0.0-beta.116",
|
|
57
|
+
"@crawlee/utils": "4.0.0-beta.116",
|
|
58
58
|
"@sapphire/async-queue": "^1.5.5",
|
|
59
59
|
"@sapphire/shapeshift": "^4.0.0",
|
|
60
60
|
"@vladfrangu/async_event_emitter": "^2.4.6",
|
|
@@ -78,5 +78,5 @@
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
},
|
|
81
|
-
"gitHead": "
|
|
81
|
+
"gitHead": "2bdc17928f47674f08fff7a83de861d881b7947a"
|
|
82
82
|
}
|
package/recoverable_state.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { KeyValueStore, serviceLocator } from '@crawlee/core';
|
|
1
|
+
import { EventType, KeyValueStore, serviceLocator } from '@crawlee/core';
|
|
2
2
|
/**
|
|
3
3
|
* A class for managing persistent recoverable state using a plain JavaScript object.
|
|
4
4
|
*
|
|
@@ -65,7 +65,7 @@ export class RecoverableState {
|
|
|
65
65
|
await this.loadSavedState();
|
|
66
66
|
// Register for persist state events
|
|
67
67
|
const eventManager = serviceLocator.getEventManager();
|
|
68
|
-
eventManager.on(
|
|
68
|
+
eventManager.on(EventType.PERSIST_STATE, this.persistState);
|
|
69
69
|
return this.currentValue;
|
|
70
70
|
}
|
|
71
71
|
/**
|
|
@@ -79,7 +79,7 @@ export class RecoverableState {
|
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
81
|
const eventManager = serviceLocator.getEventManager();
|
|
82
|
-
eventManager.off(
|
|
82
|
+
eventManager.off(EventType.PERSIST_STATE, this.persistState);
|
|
83
83
|
await this.persistState();
|
|
84
84
|
}
|
|
85
85
|
/**
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AsyncQueue } from '@sapphire/async-queue';
|
|
2
2
|
import ow from 'ow';
|
|
3
|
+
import { EventType } from '../events/event_manager.js';
|
|
3
4
|
import { serviceLocator } from '../service_locator.js';
|
|
4
5
|
import { KeyValueStore } from '../storages/key_value_store.js';
|
|
5
6
|
import { MAX_POOL_SIZE, PERSIST_STATE_KEY } from './consts.js';
|
|
@@ -150,7 +151,7 @@ export class SessionPool {
|
|
|
150
151
|
// in case of migration happened and SessionPool state should be restored from the keyValueStore.
|
|
151
152
|
await this.maybeLoadSessionPool();
|
|
152
153
|
this.#listener = this.persistState.bind(this);
|
|
153
|
-
this.#events.on(
|
|
154
|
+
this.#events.on(EventType.PERSIST_STATE, this.#listener);
|
|
154
155
|
}
|
|
155
156
|
/**
|
|
156
157
|
* Adds a new session to the session pool. The pool automatically creates sessions up to the maximum size of the pool,
|
|
@@ -265,7 +266,7 @@ export class SessionPool {
|
|
|
265
266
|
return;
|
|
266
267
|
await this.ensureInitialized();
|
|
267
268
|
if (this.#listener) {
|
|
268
|
-
this.#events.off(
|
|
269
|
+
this.#events.off(EventType.PERSIST_STATE, this.#listener);
|
|
269
270
|
}
|
|
270
271
|
await this.persistState();
|
|
271
272
|
}
|
package/storages/request_list.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { downloadListOfUrls } from '@crawlee/utils';
|
|
2
2
|
import ow, { ArgumentError } from 'ow';
|
|
3
|
+
import { EventType } from '../events/event_manager.js';
|
|
3
4
|
import { Request } from '../request.js';
|
|
4
5
|
import { createDeserialize, serializeArray } from '../serialization.js';
|
|
5
6
|
import { serviceLocator } from '../service_locator.js';
|
|
@@ -177,7 +178,7 @@ export class RequestList {
|
|
|
177
178
|
if (this.#persistRequestsKey && !this.areRequestsPersisted)
|
|
178
179
|
await this.persistRequests();
|
|
179
180
|
if (this.#persistStateKey) {
|
|
180
|
-
serviceLocator.getEventManager().on(
|
|
181
|
+
serviceLocator.getEventManager().on(EventType.PERSIST_STATE, this.persistState);
|
|
181
182
|
}
|
|
182
183
|
return this;
|
|
183
184
|
}
|
|
@@ -268,7 +269,7 @@ export class RequestList {
|
|
|
268
269
|
* leaking the listener (and the requests it retains) on the shared event manager.
|
|
269
270
|
*/
|
|
270
271
|
async teardown() {
|
|
271
|
-
serviceLocator.getEventManager().off(
|
|
272
|
+
serviceLocator.getEventManager().off(EventType.PERSIST_STATE, this.persistState);
|
|
272
273
|
if (this.#persistStateKey) {
|
|
273
274
|
await this.persistState();
|
|
274
275
|
}
|
|
@@ -6,6 +6,7 @@ import { LruCache } from '@apify/datastructures';
|
|
|
6
6
|
import { tryCancel } from '@apify/timeout';
|
|
7
7
|
import { Configuration } from '../configuration.js';
|
|
8
8
|
import { getObjectType } from '../debug.js';
|
|
9
|
+
import { EventType } from '../events/event_manager.js';
|
|
9
10
|
import { Request } from '../request.js';
|
|
10
11
|
import { serviceLocator } from '../service_locator.js';
|
|
11
12
|
import { activeStorageTransaction, rejectOperationInTransaction } from './transaction.js';
|
|
@@ -101,7 +102,7 @@ export class RequestQueue {
|
|
|
101
102
|
this.requestCache = new LruCache({ maxLength: MAX_CACHED_REQUESTS });
|
|
102
103
|
this.#requestSeenCache = new RequestDeduplicationCache();
|
|
103
104
|
this.log = serviceLocator.getLogger().child({ prefix: `RequestQueue(${this.id}, ${this.name ?? 'no-name'})` });
|
|
104
|
-
this.#events.on(
|
|
105
|
+
this.#events.on(EventType.MIGRATING, async () => {
|
|
105
106
|
this.#queuePausedForMigration = true;
|
|
106
107
|
});
|
|
107
108
|
}
|
|
@@ -3,6 +3,7 @@ import { parseSitemap } from '@crawlee/utils';
|
|
|
3
3
|
import { minimatch } from 'minimatch';
|
|
4
4
|
import ow from 'ow';
|
|
5
5
|
import { constructUrlPatternObjects } from '../enqueue_links/shared.js';
|
|
6
|
+
import { EventType } from '../events/event_manager.js';
|
|
6
7
|
import { Request } from '../request.js';
|
|
7
8
|
import { serviceLocator } from '../service_locator.js';
|
|
8
9
|
import { KeyValueStore } from './key_value_store.js';
|
|
@@ -251,7 +252,7 @@ export class SitemapRequestLoader {
|
|
|
251
252
|
parseSitemapOptions: { logger: serviceLocator.getLogger(), ...options.parseSitemapOptions, httpClient },
|
|
252
253
|
});
|
|
253
254
|
if (requestList.#persistenceOptions.enable) {
|
|
254
|
-
requestList.#events.on(
|
|
255
|
+
requestList.#events.on(EventType.PERSIST_STATE, requestList.persistState);
|
|
255
256
|
}
|
|
256
257
|
options?.signal?.addEventListener('abort', () => {
|
|
257
258
|
requestList.#abortLoading = true;
|
|
@@ -402,7 +403,7 @@ export class SitemapRequestLoader {
|
|
|
402
403
|
async teardown() {
|
|
403
404
|
this.#closed = true;
|
|
404
405
|
this.#abortLoading = true;
|
|
405
|
-
this.#events.off(
|
|
406
|
+
this.#events.off(EventType.PERSIST_STATE, this.persistState);
|
|
406
407
|
await this.persistState();
|
|
407
408
|
this.#urlQueueStream.emit('readdata'); // unblocks the potentially waiting `pushNextUrl` call
|
|
408
409
|
}
|