update worktracking #3
|
|
@ -5,14 +5,11 @@ import { createApiBid, createBidProduct, deleteProfile, shouldUpdateProductTab }
|
|||
import browser from './system/browser.js';
|
||||
import configs from './system/config.js';
|
||||
import { delay, isTimeReached, safeClosePage } from './system/utils.js';
|
||||
import pLimit from 'p-limit';
|
||||
|
||||
let MANAGER_BIDS = [];
|
||||
|
||||
let _INTERVAL_TRACKING_ID = null;
|
||||
let _CLEAR_LAZY_TAB_ID = null;
|
||||
let _WORK_TRACKING_ID = null;
|
||||
|
||||
global.IS_CLEANING = false;
|
||||
const activeTasks = new Set();
|
||||
|
||||
const handleUpdateProductTabs = (data) => {
|
||||
if (!Array.isArray(data)) {
|
||||
|
|
@ -181,33 +178,81 @@ const tracking = async () => {
|
|||
}
|
||||
};
|
||||
|
||||
const clearLazyTab = async () => {
|
||||
if (!global.IS_CLEANING) return;
|
||||
// const clearLazyTab = async () => {
|
||||
// if (!browser) {
|
||||
// console.warn('⚠️ Browser is not available or disconnected.');
|
||||
// return;
|
||||
// }
|
||||
|
||||
// try {
|
||||
// const pages = await browser.pages();
|
||||
|
||||
// // Lấy danh sách URL từ flattenedArray
|
||||
// const activeUrls = _.flatMap(MANAGER_BIDS, (item) => [item.url, ...item.children.map((child) => child.url)]).filter(Boolean); // Lọc bỏ null hoặc undefined
|
||||
|
||||
// console.log(
|
||||
// '🔍 Page URLs:',
|
||||
// pages.map((page) => page.url()),
|
||||
// );
|
||||
|
||||
// for (const page of pages) {
|
||||
// const pageUrl = page.url();
|
||||
|
||||
// // 🔥 Bỏ qua tab 'about:blank' hoặc tab không có URL
|
||||
// if (!pageUrl || pageUrl === 'about:blank') continue;
|
||||
|
||||
// if (!activeUrls.includes(pageUrl)) {
|
||||
// if (!page.isClosed() && browser.isConnected()) {
|
||||
// try {
|
||||
// await page.close();
|
||||
// console.log(`🛑 Closing unused tab: ${pageUrl}`);
|
||||
// } catch (err) {
|
||||
// console.warn(`⚠️ Error closing tab ${pageUrl}:`, err.message);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } catch (err) {
|
||||
// console.error('❌ Error in clearLazyTab:', err.message);
|
||||
// }
|
||||
// };
|
||||
|
||||
// const workTracking = async () => {
|
||||
// try {
|
||||
// const activeData = _.flatMap(MANAGER_BIDS, (item) => [item, ...item.children]);
|
||||
|
||||
// for (const item of activeData) {
|
||||
// if (item.page_context && !item.page_context.isClosed()) {
|
||||
// item.handleTakeWorkSnapshot();
|
||||
// }
|
||||
// }
|
||||
// } catch (error) {
|
||||
// console.log('Lỗi rồi:', error);
|
||||
// }
|
||||
// };
|
||||
|
||||
const clearLazyTab = async () => {
|
||||
if (!browser) {
|
||||
console.warn('⚠️ Browser is not available or disconnected.');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const pages = await browser.pages();
|
||||
const contexts = browser.contexts(); // Lấy tất cả contexts
|
||||
|
||||
for (const context of contexts) {
|
||||
const pages = context.pages(); // Lấy tất cả pages trong context
|
||||
|
||||
// Lấy danh sách URL từ flattenedArray
|
||||
const activeUrls = _.flatMap(MANAGER_BIDS, (item) => [item.url, ...item.children.map((child) => child.url)]).filter(Boolean); // Lọc bỏ null hoặc undefined
|
||||
|
||||
console.log(
|
||||
'🔍 Page URLs:',
|
||||
pages.map((page) => page.url()),
|
||||
);
|
||||
const activeUrls = _.flatMap(MANAGER_BIDS, (item) => [item.url, ...item.children.map((child) => child.url)]).filter(Boolean);
|
||||
|
||||
for (const page of pages) {
|
||||
const pageUrl = page.url();
|
||||
|
||||
// 🔥 Bỏ qua tab 'about:blank' hoặc tab không có URL
|
||||
if (!pageUrl || pageUrl === 'about:blank') continue;
|
||||
|
||||
if (!activeUrls.includes(pageUrl)) {
|
||||
if (!page.isClosed() && browser.isConnected()) {
|
||||
if (!page.isClosed()) {
|
||||
try {
|
||||
await page.close();
|
||||
console.log(`🛑 Closing unused tab: ${pageUrl}`);
|
||||
|
|
@ -217,22 +262,41 @@ const clearLazyTab = async () => {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Nếu context không còn page nào thì đóng luôn
|
||||
if (context.pages().length === 0) {
|
||||
await context.close();
|
||||
console.log(`🗑️ Closing unused context`);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('❌ Error in clearLazyTab:', err.message);
|
||||
}
|
||||
};
|
||||
|
||||
const workTracking = async () => {
|
||||
try {
|
||||
const activeData = _.flatMap(MANAGER_BIDS, (item) => [item, ...item.children]);
|
||||
const limit = pLimit(5);
|
||||
|
||||
for (const item of activeData) {
|
||||
if (item.page_context && !item.page_context.isClosed()) {
|
||||
item.handleTakeWorkSnapshot();
|
||||
}
|
||||
}
|
||||
await Promise.allSettled(
|
||||
activeData
|
||||
.filter((item) => item.page_context && !item.page_context.isClosed())
|
||||
.filter((item) => !activeTasks.has(item.id))
|
||||
.map((item) =>
|
||||
limit(async () => {
|
||||
activeTasks.add(item.id);
|
||||
try {
|
||||
await item.handleTakeWorkSnapshot();
|
||||
} catch (error) {
|
||||
console.log('Lỗi rồi:', error);
|
||||
console.error(`[❌ ERROR] Snapshot failed for Product ID: ${item.id}`, error);
|
||||
} finally {
|
||||
activeTasks.delete(item.id);
|
||||
}
|
||||
}),
|
||||
),
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(`[❌ ERROR] Work tracking failed: ${error.message}\n`, error.stack);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -19,10 +19,11 @@ export class Bid {
|
|||
if (!this.page_context) return;
|
||||
|
||||
try {
|
||||
console.log(`✅ Page loaded. Taking snapshot for Product ID: ${this.id}`);
|
||||
await this.page_context.waitForSelector('#pageContainer', { timeout: 10000 });
|
||||
console.log(`✅ Page fully loaded. Taking snapshot for Product ID: ${this.id}`);
|
||||
takeSnapshot(this.page_context, this, 'working', CONSTANTS.TYPE_IMAGE.WORK);
|
||||
} catch (error) {
|
||||
console.error(`❌ Error taking snapshot for Product ID: ${this.id}:`, error.message);
|
||||
}
|
||||
}, 500);
|
||||
}, 1000);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,14 +134,12 @@ export class GrayApiBid extends ApiBid {
|
|||
// 🔍 Check if already logged in (login input should not be visible)
|
||||
if (!(await page.$('input[name="username"]')) || fs.existsSync(filePath)) {
|
||||
console.log('✅ Already logged in, skipping login.');
|
||||
global.IS_CLEANING = true;
|
||||
|
||||
this.retry_login = 0; // Reset retry count
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('🔑 Starting login process...');
|
||||
global.IS_CLEANING = false;
|
||||
|
||||
try {
|
||||
await page.type('input[name="username"]', this.username, { delay: 100 });
|
||||
|
|
@ -156,7 +154,6 @@ export class GrayApiBid extends ApiBid {
|
|||
if (!(await page.$('input[name="username"]'))) {
|
||||
console.log('✅ Login successful!');
|
||||
this.retry_login = 0; // Reset retry count after success
|
||||
global.IS_CLEANING = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -211,7 +208,7 @@ export class GrayApiBid extends ApiBid {
|
|||
});
|
||||
|
||||
page.on('load', async () => {
|
||||
console.log('🔄 Trang đã reload, khởi động lại polling...');
|
||||
console.log('🔄 The page has reloaded, restarting polling...');
|
||||
|
||||
// await takeSnapshot(this.page_context, this, 'working', CONSTANTS.TYPE_IMAGE.WORK);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
"axios": "^1.8.2",
|
||||
"dotenv": "^16.4.7",
|
||||
"lodash": "^4.17.21",
|
||||
"p-limit": "^6.2.0",
|
||||
"puppeteer": "^24.4.0",
|
||||
"puppeteer-extra": "^3.3.6",
|
||||
"puppeteer-extra-plugin-stealth": "^2.11.2",
|
||||
|
|
@ -1294,6 +1295,21 @@
|
|||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/p-limit": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.2.0.tgz",
|
||||
"integrity": "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"yocto-queue": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/pac-proxy-agent": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz",
|
||||
|
|
@ -1992,6 +2008,18 @@
|
|||
"fd-slicer": "~1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/yocto-queue": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz",
|
||||
"integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.20"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "3.24.2",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz",
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
"axios": "^1.8.2",
|
||||
"dotenv": "^16.4.7",
|
||||
"lodash": "^4.17.21",
|
||||
"p-limit": "^6.2.0",
|
||||
"puppeteer": "^24.4.0",
|
||||
"puppeteer-extra": "^3.3.6",
|
||||
"puppeteer-extra-plugin-stealth": "^2.11.2",
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import configs from '../system/config.js';
|
|||
import CONSTANTS from '../system/constants.js';
|
||||
import { sanitizeFileName } from '../system/utils.js';
|
||||
import * as fs from 'fs';
|
||||
import _ from 'lodash';
|
||||
|
||||
const ONE_MINUTE = 60 * 1000;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,10 @@ const browser = await puppeteer.launch({
|
|||
'--disable-threaded-animation', // Giảm animation chạy trên nhiều thread
|
||||
'--disable-threaded-scrolling', // Tắt cuộn trang đa luồng
|
||||
'--disable-logging', // Tắt log debug
|
||||
'--blink-settings=imagesEnabled=false', // Không tải hình ảnh
|
||||
'--blink-settings=imagesEnabled=false', // Không tải hình ảnh,
|
||||
'--disable-background-timer-throttling', // Tránh việc throttling các timer khi chạy nền.
|
||||
'--disable-webrtc',
|
||||
'--disable-ipc-flooding-protection', // Nếu có extension cần IPC, cái này giúp tối ưu.
|
||||
],
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue