From 1fc6e75be205c5da6100cc16fc729a25a0e16959 Mon Sep 17 00:00:00 2001 From: nkhangg Date: Tue, 25 Mar 2025 10:53:13 +0700 Subject: [PATCH] update worktracking --- auto-bid-tool/index.js | 128 +++++++++++++----- auto-bid-tool/models/bid.js | 5 +- .../models/grays.com/grays-api-bid.js | 5 +- auto-bid-tool/package-lock.json | 28 ++++ auto-bid-tool/package.json | 1 + auto-bid-tool/service/app-service.js | 1 + auto-bid-tool/system/browser.js | 5 +- 7 files changed, 134 insertions(+), 39 deletions(-) diff --git a/auto-bid-tool/index.js b/auto-bid-tool/index.js index 435e28f..96f1e8d 100644 --- a/auto-bid-tool/index.js +++ b/auto-bid-tool/index.js @@ -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); } }; diff --git a/auto-bid-tool/models/bid.js b/auto-bid-tool/models/bid.js index 1f2111e..08164a7 100644 --- a/auto-bid-tool/models/bid.js +++ b/auto-bid-tool/models/bid.js @@ -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); } diff --git a/auto-bid-tool/models/grays.com/grays-api-bid.js b/auto-bid-tool/models/grays.com/grays-api-bid.js index 370d69a..3da2809 100644 --- a/auto-bid-tool/models/grays.com/grays-api-bid.js +++ b/auto-bid-tool/models/grays.com/grays-api-bid.js @@ -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); diff --git a/auto-bid-tool/package-lock.json b/auto-bid-tool/package-lock.json index 9ce2e4f..2414118 100644 --- a/auto-bid-tool/package-lock.json +++ b/auto-bid-tool/package-lock.json @@ -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", diff --git a/auto-bid-tool/package.json b/auto-bid-tool/package.json index cbe78b9..9776209 100644 --- a/auto-bid-tool/package.json +++ b/auto-bid-tool/package.json @@ -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", diff --git a/auto-bid-tool/service/app-service.js b/auto-bid-tool/service/app-service.js index f32fd42..f01c4b8 100644 --- a/auto-bid-tool/service/app-service.js +++ b/auto-bid-tool/service/app-service.js @@ -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; diff --git a/auto-bid-tool/system/browser.js b/auto-bid-tool/system/browser.js index 95d3a7d..00114d6 100644 --- a/auto-bid-tool/system/browser.js +++ b/auto-bid-tool/system/browser.js @@ -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. ], }); -- 2.39.2