@@ -25,7 +25,8 @@ const API_END_POINTS = {
2525
2626// --- Browser pool ---
2727const browserPool : Array < { browser : any ; activePages : number ; totalPagesServed : number } > = [ ]
28- const MAX_PAGES_BEFORE_RECYCLE = Number ( process . env . MAX_PAGES_BEFORE_RECYCLE ) || 500
28+ const MAX_PAGES_BEFORE_RECYCLE = Number ( process . env . MAX_PAGES_BEFORE_RECYCLE ) || 200
29+ const RECYCLE_CHECK_INTERVAL = 60000 // check every 60 seconds
2930
3031async function createBrowserEntry ( ) : Promise < { browser : any ; activePages : number ; totalPagesServed : number } > {
3132 const browser = await puppeteer . launch ( {
@@ -59,6 +60,29 @@ async function initBrowserPool() {
5960 }
6061}
6162
63+ // Periodic recycling: recycles idle browsers that have served pages, even when no traffic
64+ async function recycleIdleBrowsers ( ) {
65+ for ( let i = browserPool . length - 1 ; i >= 0 ; i -- ) {
66+ const entry = browserPool [ i ]
67+ if ( entry . activePages === 0 && entry . totalPagesServed >= MAX_PAGES_BEFORE_RECYCLE ) {
68+ logInfo ( `Recycling idle browser after ${ entry . totalPagesServed } pages served` )
69+ browserPool . splice ( i , 1 )
70+ try { await entry . browser . close ( ) } catch ( _ ) { }
71+ try {
72+ const newEntry = await createBrowserEntry ( )
73+ browserPool . push ( newEntry )
74+ logInfo ( 'Replacement browser launched, pool size:' , String ( browserPool . length ) )
75+ } catch ( err ) {
76+ logError ( 'Failed to create replacement browser:' , err )
77+ }
78+ }
79+ }
80+ }
81+
82+ setInterval ( ( ) => {
83+ recycleIdleBrowsers ( ) . catch ( err => logError ( 'Recycle check failed:' , err ) )
84+ } , RECYCLE_CHECK_INTERVAL )
85+
6286async function acquirePage ( ) : Promise < { page : any ; entry : { browser : any ; activePages : number ; totalPagesServed : number } } > {
6387 while ( browserPool . length < BROWSER_POOL_SIZE ) {
6488 try {
@@ -86,7 +110,7 @@ async function releasePage(page: any, entry: { browser: any; activePages: number
86110 }
87111 entry . activePages = Math . max ( 0 , entry . activePages - 1 )
88112
89- // Recycle browser after serving too many pages to prevent memory fragmentation
113+ // Recycle browser inline if threshold reached and no active pages
90114 if ( entry . totalPagesServed >= MAX_PAGES_BEFORE_RECYCLE && entry . activePages === 0 ) {
91115 logInfo ( `Recycling browser after ${ entry . totalPagesServed } pages served` )
92116 const idx = browserPool . indexOf ( entry )
0 commit comments