Merge pull request 'update worktracking' (#3) from main into staging

Reviewed-on: #3
This commit is contained in:
zelda 2025-03-25 14:54:02 +11:00
commit 7ee24d5613
7 changed files with 134 additions and 39 deletions

View File

@ -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,58 +178,125 @@ 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
// 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
for (const context of contexts) {
const pages = context.pages(); // Lấy tất cả pages trong context
console.log(
'🔍 Page URLs:',
pages.map((page) => page.url()),
);
// Lấy danh sách URL từ flattenedArray
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();
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 (!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);
if (!activeUrls.includes(pageUrl)) {
if (!page.isClosed()) {
try {
await page.close();
console.log(`🛑 Closing unused tab: ${pageUrl}`);
} catch (err) {
console.warn(`⚠️ Error closing tab ${pageUrl}:`, err.message);
}
}
}
}
// 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.error(`[❌ ERROR] Snapshot failed for Product ID: ${item.id}`, error);
} finally {
activeTasks.delete(item.id);
}
}),
),
);
} catch (error) {
console.log('Lỗi rồi:', error);
console.error(`[❌ ERROR] Work tracking failed: ${error.message}\n`, error.stack);
}
};

View File

@ -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);
}

View File

@ -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);

View File

@ -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",

View File

@ -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",

View File

@ -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;

View File

@ -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.
],
});