mx-cloud 0.0.21 → 0.0.23
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/build/interpret.d.ts +6 -1
- package/build/interpret.js +75 -3
- package/build/selector.d.ts +1 -1
- package/build/types/workflow.d.ts +1 -1
- package/package.json +2 -4
package/build/interpret.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Page } from 'playwright';
|
|
1
|
+
import { Page } from 'playwright-core';
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
3
|
import { WorkflowFile, ParamType } from './types/workflow';
|
|
4
4
|
/**
|
|
@@ -160,5 +160,10 @@ export default class Interpreter extends EventEmitter {
|
|
|
160
160
|
*/
|
|
161
161
|
run(page: Page, params?: ParamType): Promise<void>;
|
|
162
162
|
stop(): Promise<void>;
|
|
163
|
+
/**
|
|
164
|
+
* Cleanup method to release resources and prevent memory leaks
|
|
165
|
+
* Call this when the interpreter is no longer needed
|
|
166
|
+
*/
|
|
167
|
+
cleanup(): Promise<void>;
|
|
163
168
|
}
|
|
164
169
|
export {};
|
package/build/interpret.js
CHANGED
|
@@ -394,8 +394,9 @@ class Interpreter extends events_1.EventEmitter {
|
|
|
394
394
|
for (const link of links) {
|
|
395
395
|
// eslint-disable-next-line
|
|
396
396
|
this.concurrency.addJob(() => __awaiter(this, void 0, void 0, function* () {
|
|
397
|
+
let newPage = null;
|
|
397
398
|
try {
|
|
398
|
-
|
|
399
|
+
newPage = yield context.newPage();
|
|
399
400
|
yield newPage.goto(link);
|
|
400
401
|
yield newPage.waitForLoadState('networkidle');
|
|
401
402
|
yield this.runLoop(newPage, this.initializedWorkflow);
|
|
@@ -406,6 +407,16 @@ class Interpreter extends events_1.EventEmitter {
|
|
|
406
407
|
// the interpreter by throwing).
|
|
407
408
|
this.log(e, logger_1.Level.ERROR);
|
|
408
409
|
}
|
|
410
|
+
finally {
|
|
411
|
+
if (newPage && !newPage.isClosed()) {
|
|
412
|
+
try {
|
|
413
|
+
yield newPage.close();
|
|
414
|
+
}
|
|
415
|
+
catch (closeError) {
|
|
416
|
+
this.log('Failed to close enqueued page', logger_1.Level.WARN);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
409
420
|
}));
|
|
410
421
|
}
|
|
411
422
|
yield page.close();
|
|
@@ -2224,9 +2235,10 @@ class Interpreter extends events_1.EventEmitter {
|
|
|
2224
2235
|
* User-requested concurrency should be entirely managed by the concurrency manager,
|
|
2225
2236
|
* e.g. via `enqueueLinks`.
|
|
2226
2237
|
*/
|
|
2227
|
-
|
|
2238
|
+
const popupHandler = (popup) => {
|
|
2228
2239
|
this.concurrency.addJob(() => this.runLoop(popup, workflowCopy));
|
|
2229
|
-
}
|
|
2240
|
+
};
|
|
2241
|
+
p.on('popup', popupHandler);
|
|
2230
2242
|
/* eslint no-constant-condition: ["warn", { "checkLoops": false }] */
|
|
2231
2243
|
let loopIterations = 0;
|
|
2232
2244
|
const MAX_LOOP_ITERATIONS = 1000; // Circuit breaker
|
|
@@ -2234,41 +2246,58 @@ class Interpreter extends events_1.EventEmitter {
|
|
|
2234
2246
|
const MAX_CONSECUTIVE_FAILURES = 10;
|
|
2235
2247
|
const startTime = Date.now();
|
|
2236
2248
|
const MAX_EXECUTION_TIME = 30 * 60 * 1000; // 30 minutes max
|
|
2249
|
+
// Cleanup function to remove popup listener
|
|
2250
|
+
const cleanup = () => {
|
|
2251
|
+
try {
|
|
2252
|
+
if (!p.isClosed()) {
|
|
2253
|
+
p.removeListener('popup', popupHandler);
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
catch (cleanupError) {
|
|
2257
|
+
}
|
|
2258
|
+
};
|
|
2237
2259
|
while (true) {
|
|
2238
2260
|
// Multiple circuit breakers to prevent infinite loops
|
|
2239
2261
|
if (++loopIterations > MAX_LOOP_ITERATIONS) {
|
|
2240
2262
|
this.log('Maximum loop iterations reached, terminating to prevent infinite loop', logger_1.Level.ERROR);
|
|
2263
|
+
cleanup();
|
|
2241
2264
|
return;
|
|
2242
2265
|
}
|
|
2243
2266
|
// Time-based circuit breaker
|
|
2244
2267
|
if (Date.now() - startTime > MAX_EXECUTION_TIME) {
|
|
2245
2268
|
this.log('Maximum execution time reached (30 minutes), terminating workflow', logger_1.Level.ERROR);
|
|
2269
|
+
cleanup();
|
|
2246
2270
|
return;
|
|
2247
2271
|
}
|
|
2248
2272
|
// Failure-based circuit breaker
|
|
2249
2273
|
if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
|
|
2250
2274
|
this.log('Too many consecutive failures, terminating to prevent hang', logger_1.Level.ERROR);
|
|
2275
|
+
cleanup();
|
|
2251
2276
|
return;
|
|
2252
2277
|
}
|
|
2253
2278
|
// Check abort flag immediately
|
|
2254
2279
|
if (this.isAborted) {
|
|
2255
2280
|
this.log('Workflow aborted in runLoop', logger_1.Level.WARN);
|
|
2281
|
+
cleanup();
|
|
2256
2282
|
return;
|
|
2257
2283
|
}
|
|
2258
2284
|
// Checks whether the page was closed from outside,
|
|
2259
2285
|
// or the workflow execution has been stopped via `interpreter.stop()`
|
|
2260
2286
|
if (p.isClosed() || !this.stopper) {
|
|
2287
|
+
cleanup();
|
|
2261
2288
|
return;
|
|
2262
2289
|
}
|
|
2263
2290
|
try {
|
|
2264
2291
|
yield p.waitForLoadState();
|
|
2265
2292
|
}
|
|
2266
2293
|
catch (e) {
|
|
2294
|
+
cleanup();
|
|
2267
2295
|
yield p.close();
|
|
2268
2296
|
return;
|
|
2269
2297
|
}
|
|
2270
2298
|
if (workflowCopy.length === 0) {
|
|
2271
2299
|
this.log('All actions completed. Workflow finished.', logger_1.Level.LOG);
|
|
2300
|
+
cleanup();
|
|
2272
2301
|
return;
|
|
2273
2302
|
}
|
|
2274
2303
|
// const newSelectors = this.getSelectors(workflowCopy);
|
|
@@ -2359,6 +2388,7 @@ class Interpreter extends events_1.EventEmitter {
|
|
|
2359
2388
|
}
|
|
2360
2389
|
else {
|
|
2361
2390
|
//await this.disableAdBlocker(p);
|
|
2391
|
+
cleanup();
|
|
2362
2392
|
return;
|
|
2363
2393
|
}
|
|
2364
2394
|
}
|
|
@@ -2444,5 +2474,47 @@ class Interpreter extends events_1.EventEmitter {
|
|
|
2444
2474
|
}
|
|
2445
2475
|
});
|
|
2446
2476
|
}
|
|
2477
|
+
/**
|
|
2478
|
+
* Cleanup method to release resources and prevent memory leaks
|
|
2479
|
+
* Call this when the interpreter is no longer needed
|
|
2480
|
+
*/
|
|
2481
|
+
cleanup() {
|
|
2482
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2483
|
+
try {
|
|
2484
|
+
// Stop any running workflows first
|
|
2485
|
+
if (this.stopper) {
|
|
2486
|
+
try {
|
|
2487
|
+
yield this.stop();
|
|
2488
|
+
}
|
|
2489
|
+
catch (error) {
|
|
2490
|
+
this.log(`Error stopping workflow during cleanup: ${error.message}`, logger_1.Level.WARN);
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2493
|
+
// Clear ad-blocker resources
|
|
2494
|
+
if (this.blocker) {
|
|
2495
|
+
try {
|
|
2496
|
+
this.blocker = null;
|
|
2497
|
+
this.log('Ad-blocker resources cleared', logger_1.Level.DEBUG);
|
|
2498
|
+
}
|
|
2499
|
+
catch (error) {
|
|
2500
|
+
this.log(`Error cleaning up ad-blocker: ${error.message}`, logger_1.Level.WARN);
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
// Clear accumulated data to free memory
|
|
2504
|
+
this.cumulativeResults = [];
|
|
2505
|
+
this.autohealFailures = [];
|
|
2506
|
+
this.namedResults = {};
|
|
2507
|
+
this.serializableDataByType = { scrapeList: {}, scrapeSchema: {} };
|
|
2508
|
+
// Reset state
|
|
2509
|
+
this.isAborted = false;
|
|
2510
|
+
this.initializedWorkflow = null;
|
|
2511
|
+
this.log('Interpreter cleanup completed', logger_1.Level.DEBUG);
|
|
2512
|
+
}
|
|
2513
|
+
catch (error) {
|
|
2514
|
+
this.log(`Error during interpreter cleanup: ${error.message}`, logger_1.Level.ERROR);
|
|
2515
|
+
throw error;
|
|
2516
|
+
}
|
|
2517
|
+
});
|
|
2518
|
+
}
|
|
2447
2519
|
}
|
|
2448
2520
|
exports.default = Interpreter;
|
package/build/selector.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mx-cloud",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.23",
|
|
4
4
|
"description": "mx cloud",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"typings": "build/index.d.ts",
|
|
@@ -20,8 +20,6 @@
|
|
|
20
20
|
"cross-fetch": "^4.0.0",
|
|
21
21
|
"joi": "^17.6.0",
|
|
22
22
|
"nodemailer": "^6.10.0",
|
|
23
|
-
"playwright": "^1.
|
|
24
|
-
"playwright-extra": "^4.3.6",
|
|
25
|
-
"puppeteer-extra-plugin-stealth": "^2.11.2"
|
|
23
|
+
"playwright-core": "^1.57.0"
|
|
26
24
|
}
|
|
27
25
|
}
|