diff --git a/index.ts b/index.ts index 9a43aac..4505977 100644 --- a/index.ts +++ b/index.ts @@ -65,7 +65,7 @@ router.get('/ask/stream', async (ctx) => { app.use(router.routes()); (async () => { - await freeBrowserPool.init(1, process.env.DEBUG === '1'); + await freeBrowserPool.init(5, process.env.DEBUG === '1'); const server = app.listen(3000, () => { console.log("Now listening: 127.0.0.1:3000"); }); diff --git a/model/forefront/index.ts b/model/forefront/index.ts index e1acd0f..19449f9 100644 --- a/model/forefront/index.ts +++ b/model/forefront/index.ts @@ -10,6 +10,7 @@ export class Forefrontnew extends Chat { private page: Page | undefined = undefined; private url: string = 'https://chat.forefront.ai/'; private writing: NodeJS.Timer | undefined = undefined; + private msgSize: number = 0; constructor(options?: ChatOptions) { super(options); @@ -37,6 +38,13 @@ export class Forefrontnew extends Chat { pt.end(); return {text: pt} } + if (this.msgSize === 2) { + await freeBrowserPool.remove(this.browser?.id||""); + this.browser = undefined; + this.page = undefined; + this.msgSize = 0; + } + this.msgSize++; if (!this.browser) { this.browser = freeBrowserPool.getRandom(); } @@ -105,8 +113,7 @@ export class Forefrontnew extends Chat { const mdList = await this.page.$('#__next > .flex > .relative > .relative > .w-full:nth-child(1) > div'); const md = mdList; // get latest markdown id - let id: number = (await md?.evaluate(el => el.children.length)) || 0 - id = id * 4; + let id: number = this.msgSize * 4; const selector = `div > .w-full:nth-child(${id}) > .flex > .flex > .post-markdown`; await this.page.waitForSelector(selector); const result = await this.page.$(selector) diff --git a/pool/puppeteer.ts b/pool/puppeteer.ts index e6c25cf..f01cf11 100644 --- a/pool/puppeteer.ts +++ b/pool/puppeteer.ts @@ -2,6 +2,8 @@ import puppeteer, {Browser, Page, PuppeteerLaunchOptions} from "puppeteer"; import fs from 'fs'; import path from "path"; import run from "node:test"; +import {randomUUID} from "crypto"; +import {v4} from "uuid"; const runPath = path.join(__dirname, 'run'); @@ -10,7 +12,7 @@ export class FreeBrowser { private readonly options: PuppeteerLaunchOptions | undefined; private urls: Set = new Set(); private pages: Record = {}; - private readonly id: string; + public readonly id: string; constructor(id: string, options?: PuppeteerLaunchOptions) { this.options = { @@ -38,37 +40,62 @@ export class FreeBrowser { this.pages[url] = page; return page; } + + public async close() { + this.browser?.close(); + } } class FreeBrowserPool { private size: number = 0; private readonly pool: FreeBrowser[]; + private debug: boolean = false; constructor() { this.pool = []; } - public async init(size: number, debug: boolean) { + public async init(size: number,debug:boolean) { + this.debug = debug; console.log(`browser pool init size:${size}`) if (!fs.existsSync(runPath)) { fs.mkdirSync(runPath); } this.size = size; - const options: PuppeteerLaunchOptions = { - headless: !debug, - args: ['--no-sandbox'] - }; for (let i = 0; i < size; i++) { - const browser = new FreeBrowser(`${i}`, options); - await browser.init(); - this.pool.push(browser); + this.pool.push(await this.newBrowser()); } } public getRandom(): FreeBrowser { return this.pool[Math.floor(Math.random() * this.pool.length)] } + + private async newBrowser(): Promise { + const options: PuppeteerLaunchOptions = { + headless: !this.debug, + args: ['--no-sandbox'] + }; + const browser = new FreeBrowser(v4(), options); + await browser.init(); + return browser; + } + + public async remove(id: string) { + let removed = false; + this.pool.filter(item => { + if (item.id === id) { + item.close(); + removed = true; + return false; + } + return true; + }) + if (removed) { + this.pool.push(await this.newBrowser()); + } + } } export const freeBrowserPool = new FreeBrowserPool();