@purepageio/fetch-engines 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +205 -0
- package/dist/FetchEngine.d.ts +46 -0
- package/dist/FetchEngine.d.ts.map +1 -0
- package/dist/FetchEngine.js +137 -0
- package/dist/FetchEngine.js.map +1 -0
- package/dist/FetchEngine.test.d.ts +2 -0
- package/dist/FetchEngine.test.d.ts.map +1 -0
- package/dist/FetchEngine.test.js +44 -0
- package/dist/FetchEngine.test.js.map +1 -0
- package/dist/HybridEngine.d.ts +15 -0
- package/dist/HybridEngine.d.ts.map +1 -0
- package/dist/HybridEngine.js +45 -0
- package/dist/HybridEngine.js.map +1 -0
- package/dist/IEngine.d.ts +22 -0
- package/dist/IEngine.d.ts.map +1 -0
- package/dist/IEngine.js +2 -0
- package/dist/IEngine.js.map +1 -0
- package/dist/PlaywrightEngine.d.ts +88 -0
- package/dist/PlaywrightEngine.d.ts.map +1 -0
- package/dist/PlaywrightEngine.js +484 -0
- package/dist/PlaywrightEngine.js.map +1 -0
- package/dist/PlaywrightEngine.test.d.ts +2 -0
- package/dist/PlaywrightEngine.test.d.ts.map +1 -0
- package/dist/PlaywrightEngine.test.js +299 -0
- package/dist/PlaywrightEngine.test.js.map +1 -0
- package/dist/PuppeteerEngine.d.ts +21 -0
- package/dist/PuppeteerEngine.d.ts.map +1 -0
- package/dist/PuppeteerEngine.js +412 -0
- package/dist/PuppeteerEngine.js.map +1 -0
- package/dist/browser/BrowserPool.d.ts +29 -0
- package/dist/browser/BrowserPool.d.ts.map +1 -0
- package/dist/browser/BrowserPool.js +378 -0
- package/dist/browser/BrowserPool.js.map +1 -0
- package/dist/browser/PlaywrightBrowserPool.d.ts +78 -0
- package/dist/browser/PlaywrightBrowserPool.d.ts.map +1 -0
- package/dist/browser/PlaywrightBrowserPool.js +429 -0
- package/dist/browser/PlaywrightBrowserPool.js.map +1 -0
- package/dist/browser/PlaywrightBrowserPool.test.d.ts +2 -0
- package/dist/browser/PlaywrightBrowserPool.test.d.ts.map +1 -0
- package/dist/browser/PlaywrightBrowserPool.test.js +422 -0
- package/dist/browser/PlaywrightBrowserPool.test.js.map +1 -0
- package/dist/errors.d.ts +20 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +30 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +151 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { chromium } from "playwright";
|
|
2
|
+
// Puppeteer-extra and stealth plugin are removed as Playwright handles this differently or it's not directly needed.
|
|
3
|
+
export class BrowserPool {
|
|
4
|
+
pool = [];
|
|
5
|
+
maxBrowsers;
|
|
6
|
+
maxPagesPerBrowser; // This might map to pages per context in Playwright
|
|
7
|
+
maxBrowserAge; // Max age in ms
|
|
8
|
+
healthCheckInterval; // Interval in ms
|
|
9
|
+
healthCheckTimer;
|
|
10
|
+
maxIdleTime = 5 * 60 * 1000; // 5 minutes idle timeout
|
|
11
|
+
isCleaningUp = false; // Flag to prevent operations during cleanup
|
|
12
|
+
constructor(maxBrowsers = 2, maxPagesPerBrowser = 4, // Revisit how this limit is applied with Playwright contexts
|
|
13
|
+
maxBrowserAge = 30 * 60 * 1000, // 30 minutes
|
|
14
|
+
healthCheckInterval = 30 * 1000 // 30 seconds
|
|
15
|
+
) {
|
|
16
|
+
this.maxBrowsers = maxBrowsers;
|
|
17
|
+
this.maxPagesPerBrowser = maxPagesPerBrowser;
|
|
18
|
+
this.maxBrowserAge = maxBrowserAge;
|
|
19
|
+
this.healthCheckInterval = healthCheckInterval;
|
|
20
|
+
// Initialization moved to async initialize() method
|
|
21
|
+
}
|
|
22
|
+
// Create a Playwright Browser (using Chromium for now)
|
|
23
|
+
async createBrowser() {
|
|
24
|
+
console.log("Creating new Playwright browser instance (Chromium)...");
|
|
25
|
+
// Map Puppeteer args to Playwright launch options where applicable
|
|
26
|
+
const options = {
|
|
27
|
+
headless: true,
|
|
28
|
+
args: [
|
|
29
|
+
"--no-sandbox",
|
|
30
|
+
"--disable-setuid-sandbox",
|
|
31
|
+
"--disable-dev-shm-usage",
|
|
32
|
+
"--disable-gpu",
|
|
33
|
+
// Playwright manages many flags automatically, fewer needed explicitly
|
|
34
|
+
"--mute-audio",
|
|
35
|
+
"--disable-background-networking",
|
|
36
|
+
"--disable-background-timer-throttling",
|
|
37
|
+
"--disable-breakpad",
|
|
38
|
+
"--disable-client-side-phishing-detection",
|
|
39
|
+
"--disable-component-update",
|
|
40
|
+
"--disable-default-apps",
|
|
41
|
+
"--disable-domain-reliability",
|
|
42
|
+
"--disable-features=AudioServiceOutOfProcess",
|
|
43
|
+
"--disable-hang-monitor",
|
|
44
|
+
"--disable-ipc-flooding-protection",
|
|
45
|
+
"--disable-notifications",
|
|
46
|
+
"--disable-offer-store-unmasked-wallet-cards",
|
|
47
|
+
"--disable-popup-blocking",
|
|
48
|
+
"--disable-print-preview",
|
|
49
|
+
"--disable-prompt-on-repost",
|
|
50
|
+
"--disable-renderer-backgrounding",
|
|
51
|
+
"--disable-sync",
|
|
52
|
+
"--disable-translate",
|
|
53
|
+
"--metrics-recording-only",
|
|
54
|
+
"--no-default-browser-check",
|
|
55
|
+
"--password-store=basic",
|
|
56
|
+
"--use-mock-keychain",
|
|
57
|
+
],
|
|
58
|
+
// Consider proxy settings, viewport, user agent etc. if needed
|
|
59
|
+
};
|
|
60
|
+
let browser;
|
|
61
|
+
try {
|
|
62
|
+
// Launch Chromium browser using Playwright
|
|
63
|
+
browser = await chromium.launch(options);
|
|
64
|
+
}
|
|
65
|
+
catch (launchError) {
|
|
66
|
+
console.error("Playwright launch failed:", launchError);
|
|
67
|
+
throw launchError; // Re-throw after logging
|
|
68
|
+
}
|
|
69
|
+
// Create a default context for simplicity, could manage multiple contexts later
|
|
70
|
+
const context = await browser.newContext();
|
|
71
|
+
const instance = {
|
|
72
|
+
browser,
|
|
73
|
+
context, // Store the context
|
|
74
|
+
metrics: {
|
|
75
|
+
id: `playwright-${Date.now()}-${Math.random().toString(16).slice(2)}`, // Unique ID for Playwright
|
|
76
|
+
pagesCreated: 0,
|
|
77
|
+
activePages: 0,
|
|
78
|
+
lastUsed: new Date(),
|
|
79
|
+
errors: 0,
|
|
80
|
+
totalRequests: 0,
|
|
81
|
+
avgResponseTime: 0,
|
|
82
|
+
createdAt: new Date(),
|
|
83
|
+
isHealthy: true,
|
|
84
|
+
engine: "playwright", // Identify engine as Playwright
|
|
85
|
+
},
|
|
86
|
+
isHealthy: true,
|
|
87
|
+
};
|
|
88
|
+
console.log(`Playwright browser instance created (ID: ${instance.metrics.id})`);
|
|
89
|
+
// Handle disconnection gracefully using Playwright's event
|
|
90
|
+
browser.on("disconnected", () => {
|
|
91
|
+
console.warn(`Browser disconnected (ID: ${instance.metrics.id}), marking as unhealthy.`);
|
|
92
|
+
instance.isHealthy = false;
|
|
93
|
+
instance.metrics.isHealthy = false; // Ensure metric reflects state
|
|
94
|
+
// Health check will handle removal
|
|
95
|
+
});
|
|
96
|
+
return instance;
|
|
97
|
+
}
|
|
98
|
+
// Close browser and its context
|
|
99
|
+
async closeAndRemoveBrowser(instance) {
|
|
100
|
+
if (!instance || this.isCleaningUp)
|
|
101
|
+
return; // Prevent removal during cleanup
|
|
102
|
+
console.log(`Closing and removing browser instance (ID: ${instance.metrics.id})`);
|
|
103
|
+
// Remove from pool immediately to prevent reuse
|
|
104
|
+
this.pool = this.pool.filter((b) => b !== instance);
|
|
105
|
+
try {
|
|
106
|
+
// Ensure context is closed before browser
|
|
107
|
+
if (instance.context) {
|
|
108
|
+
await instance.context.close();
|
|
109
|
+
}
|
|
110
|
+
await instance.browser.close();
|
|
111
|
+
console.log(`Browser instance (ID: ${instance.metrics.id}) closed successfully.`);
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
console.error(`Error closing browser (ID: ${instance.metrics.id}):`, error);
|
|
115
|
+
// Mark as unhealthy even if close fails, though it's already removed from pool
|
|
116
|
+
instance.isHealthy = false;
|
|
117
|
+
instance.metrics.isHealthy = false;
|
|
118
|
+
}
|
|
119
|
+
// Attempt to maintain pool size if not cleaning up
|
|
120
|
+
if (!this.isCleaningUp && this.pool.length < this.maxBrowsers) {
|
|
121
|
+
console.log("Attempting to create replacement browser...");
|
|
122
|
+
this.ensureMinimumBrowsers().catch((err) => {
|
|
123
|
+
console.error("Failed to ensure minimum browser count after removal:", err);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Health check adapted for Playwright
|
|
128
|
+
async healthCheck() {
|
|
129
|
+
if (this.isCleaningUp)
|
|
130
|
+
return; // Skip health check during cleanup
|
|
131
|
+
console.log(`Running health check on ${this.pool.length} browser(s)...`);
|
|
132
|
+
const now = Date.now();
|
|
133
|
+
let browsersChanged = false;
|
|
134
|
+
// Iterate backwards for safe removal
|
|
135
|
+
for (let i = this.pool.length - 1; i >= 0; i--) {
|
|
136
|
+
const instance = this.pool[i];
|
|
137
|
+
let shouldRemove = false;
|
|
138
|
+
let reason = "";
|
|
139
|
+
// 1. Check browser age
|
|
140
|
+
const browserAge = now - instance.metrics.createdAt.getTime();
|
|
141
|
+
if (browserAge > this.maxBrowserAge) {
|
|
142
|
+
shouldRemove = true;
|
|
143
|
+
reason = "Browser max age exceeded";
|
|
144
|
+
}
|
|
145
|
+
// 2. Check idle time (only if pool size > 1)
|
|
146
|
+
const idleTime = now - instance.metrics.lastUsed.getTime();
|
|
147
|
+
// Check active pages using the context's pages
|
|
148
|
+
const currentPages = instance.context?.pages() ?? [];
|
|
149
|
+
instance.metrics.activePages = currentPages.length; // Update metric
|
|
150
|
+
if (!shouldRemove && this.pool.length > 1 && instance.metrics.activePages === 0 && idleTime > this.maxIdleTime) {
|
|
151
|
+
shouldRemove = true;
|
|
152
|
+
reason = "Browser idle timeout exceeded";
|
|
153
|
+
}
|
|
154
|
+
// 3. Check explicit health status (e.g., disconnected event)
|
|
155
|
+
if (!shouldRemove && !instance.isHealthy) {
|
|
156
|
+
shouldRemove = true;
|
|
157
|
+
reason = "Browser marked as unhealthy"; // Generic reason if already marked
|
|
158
|
+
}
|
|
159
|
+
// 4. Check responsiveness (using isConnected)
|
|
160
|
+
if (!shouldRemove && instance.isHealthy) {
|
|
161
|
+
try {
|
|
162
|
+
if (!instance.browser.isConnected()) {
|
|
163
|
+
shouldRemove = true;
|
|
164
|
+
reason = "Browser responsiveness check failed (not connected)";
|
|
165
|
+
instance.isHealthy = false; // Mark as unhealthy
|
|
166
|
+
instance.metrics.isHealthy = false;
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
// Update active page count based on reality from the context
|
|
170
|
+
const pages = instance.context?.pages() ?? [];
|
|
171
|
+
instance.metrics.activePages = pages.length;
|
|
172
|
+
// Optionally add a more robust check like browser.version()
|
|
173
|
+
// await instance.browser.version();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
console.error(`Browser responsiveness check failed (ID: ${instance.metrics.id}):`, error);
|
|
178
|
+
shouldRemove = true;
|
|
179
|
+
reason = "Browser responsiveness check failed (error)";
|
|
180
|
+
instance.isHealthy = false; // Mark as unhealthy
|
|
181
|
+
instance.metrics.isHealthy = false;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (shouldRemove) {
|
|
185
|
+
console.log(`${reason}. Removing browser (ID: ${instance.metrics.id}).`);
|
|
186
|
+
// Use closeAndRemoveBrowser which handles removal from pool and closing
|
|
187
|
+
this.closeAndRemoveBrowser(instance).catch((err) => console.error(`Error during async browser removal: ${err}`));
|
|
188
|
+
browsersChanged = true;
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
// If not removed, ensure metric health status matches instance status
|
|
192
|
+
instance.metrics.isHealthy = instance.isHealthy;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Ensure minimum browser count if changes occurred or pool is empty
|
|
196
|
+
if (browsersChanged || this.pool.length === 0) {
|
|
197
|
+
await this.ensureMinimumBrowsers();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// ensureMinimumBrowsers remains largely the same, relies on createBrowser
|
|
201
|
+
async ensureMinimumBrowsers() {
|
|
202
|
+
if (this.isCleaningUp)
|
|
203
|
+
return;
|
|
204
|
+
// Ensure at least one, or half max browsers (configurable maybe?)
|
|
205
|
+
const minBrowsers = Math.max(1, Math.floor(this.maxBrowsers / 2));
|
|
206
|
+
const browsersNeeded = minBrowsers - this.pool.filter((b) => b.isHealthy).length;
|
|
207
|
+
if (browsersNeeded > 0) {
|
|
208
|
+
console.log(`Healthy browsers below minimum (${minBrowsers}), attempting to create ${browsersNeeded} browser(s)...`);
|
|
209
|
+
for (let i = 0; i < browsersNeeded; i++) {
|
|
210
|
+
if (this.pool.length >= this.maxBrowsers) {
|
|
211
|
+
console.log("Reached max browser limit during replenishment.");
|
|
212
|
+
break; // Stop if we hit the overall max
|
|
213
|
+
}
|
|
214
|
+
try {
|
|
215
|
+
const newInstance = await this.createBrowser();
|
|
216
|
+
this.pool.push(newInstance);
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
console.error("Failed to create browser during pool replenishment:", error);
|
|
220
|
+
// Maybe add a delay before next attempt or stop trying after failures?
|
|
221
|
+
break; // Stop trying if one fails
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// startHealthChecks remains the same logic
|
|
227
|
+
startHealthChecks() {
|
|
228
|
+
if (this.healthCheckTimer) {
|
|
229
|
+
clearInterval(this.healthCheckTimer); // Clear existing timer if any - Cast to NodeJS.Timeout
|
|
230
|
+
}
|
|
231
|
+
console.log(`Starting browser pool health checks every ${this.healthCheckInterval / 1000} seconds.`);
|
|
232
|
+
this.healthCheckTimer = setInterval(() => this.healthCheck().catch((err) => {
|
|
233
|
+
console.error("Unhandled error in healthCheck:", err);
|
|
234
|
+
}), this.healthCheckInterval);
|
|
235
|
+
this.healthCheckTimer.unref(); // Allow Node.js process to exit if this is the only timer
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Asynchronously initializes the browser pool, creating the first browser instance
|
|
239
|
+
* and starting health checks. Should be called before acquiring pages.
|
|
240
|
+
*/
|
|
241
|
+
async initialize() {
|
|
242
|
+
if (this.pool.length > 0 || this.isCleaningUp) {
|
|
243
|
+
console.log("Browser pool already initialized or cleaning up.");
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
console.log("Initializing browser pool...");
|
|
247
|
+
await this.ensureMinimumBrowsers(); // Create initial browser(s)
|
|
248
|
+
this.startHealthChecks(); // Start checks after initial browser is created
|
|
249
|
+
console.log("Browser pool initialized.");
|
|
250
|
+
}
|
|
251
|
+
// Acquire page adapted for Playwright using context
|
|
252
|
+
async acquirePage() {
|
|
253
|
+
if (this.isCleaningUp) {
|
|
254
|
+
throw new Error("Cannot acquire page: Browser pool is cleaning up.");
|
|
255
|
+
}
|
|
256
|
+
// Find a healthy browser/context with capacity
|
|
257
|
+
let targetInstance;
|
|
258
|
+
// Prioritize instances with fewer pages
|
|
259
|
+
const sortedPool = this.pool
|
|
260
|
+
.filter((instance) => instance.isHealthy)
|
|
261
|
+
.sort((a, b) => (a.context?.pages()?.length ?? Infinity) - (b.context?.pages()?.length ?? Infinity));
|
|
262
|
+
for (const instance of sortedPool) {
|
|
263
|
+
const currentPages = instance.context?.pages()?.length ?? Infinity;
|
|
264
|
+
if (currentPages < this.maxPagesPerBrowser) {
|
|
265
|
+
targetInstance = instance;
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// If no suitable browser/context found, and pool size is below max, try creating one
|
|
270
|
+
if (!targetInstance && this.pool.length < this.maxBrowsers) {
|
|
271
|
+
console.log("No available browser with capacity, attempting to create a new one...");
|
|
272
|
+
try {
|
|
273
|
+
const newInstance = await this.createBrowser();
|
|
274
|
+
this.pool.push(newInstance);
|
|
275
|
+
// Check if the new instance has capacity (should always be true initially)
|
|
276
|
+
if ((newInstance.context?.pages()?.length ?? Infinity) < this.maxPagesPerBrowser) {
|
|
277
|
+
targetInstance = newInstance;
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
console.warn("Newly created browser instance unexpectedly has no page capacity.");
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
console.error("Failed to create new browser instance on demand:", error);
|
|
285
|
+
// Fallback strategy if creation fails (optional): use least loaded regardless of limit
|
|
286
|
+
if (!targetInstance && sortedPool.length > 0) {
|
|
287
|
+
targetInstance = sortedPool[0]; // Least loaded existing healthy one
|
|
288
|
+
console.warn(`Using potentially overloaded browser (ID: ${targetInstance.metrics.id}) as fallback after creation failure.`);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
// If still no browser after all attempts
|
|
293
|
+
if (!targetInstance || !targetInstance.context) {
|
|
294
|
+
// Check context existence as well
|
|
295
|
+
console.error("Failed to find or create a healthy browser instance with a valid context.");
|
|
296
|
+
throw new Error("No healthy browsers/contexts available in the pool.");
|
|
297
|
+
}
|
|
298
|
+
try {
|
|
299
|
+
const activePages = targetInstance.context.pages().length;
|
|
300
|
+
console.log(`Acquiring page from browser (ID: ${targetInstance.metrics.id}, Active Pages: ${activePages})`);
|
|
301
|
+
// Create page within the instance's context
|
|
302
|
+
const page = await targetInstance.context.newPage();
|
|
303
|
+
targetInstance.metrics.pagesCreated++;
|
|
304
|
+
// Active page count will be updated by health check or can be done here
|
|
305
|
+
targetInstance.metrics.activePages = targetInstance.context.pages().length;
|
|
306
|
+
targetInstance.metrics.lastUsed = new Date(); // Update last used time
|
|
307
|
+
// Track page close to potentially update metrics (less critical if health check does it)
|
|
308
|
+
// Playwright pages emit 'close' event
|
|
309
|
+
page.on("close", () => {
|
|
310
|
+
try {
|
|
311
|
+
// Update metrics if the instance still exists in the pool
|
|
312
|
+
const instanceInPool = this.pool.find((inst) => inst === targetInstance);
|
|
313
|
+
if (instanceInPool && instanceInPool.context) {
|
|
314
|
+
instanceInPool.metrics.activePages = instanceInPool.context.pages().length;
|
|
315
|
+
// console.log(`Page closed event, browser active pages: ${instanceInPool.metrics.activePages} (ID: ${instanceInPool.metrics.id})`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
catch (e) {
|
|
319
|
+
// Ignore errors here, health check is the safety net
|
|
320
|
+
console.warn("Minor error updating metrics on page close event:", e);
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
return page;
|
|
324
|
+
}
|
|
325
|
+
catch (error) {
|
|
326
|
+
console.error(`Failed to create page in browser/context (ID: ${targetInstance.metrics.id}):`, error);
|
|
327
|
+
targetInstance.metrics.errors++;
|
|
328
|
+
// Mark browser as unhealthy if page creation fails
|
|
329
|
+
targetInstance.isHealthy = false;
|
|
330
|
+
targetInstance.metrics.isHealthy = false;
|
|
331
|
+
this.healthCheck().catch((err) => console.error("Error running immediate health check after page fail:", err)); // Trigger health check
|
|
332
|
+
throw new Error(`Failed to create page: ${error.message}`); // Re-throw
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
// cleanup needs to close contexts as well
|
|
336
|
+
async cleanup() {
|
|
337
|
+
if (this.isCleaningUp)
|
|
338
|
+
return; // Prevent concurrent cleanup
|
|
339
|
+
this.isCleaningUp = true;
|
|
340
|
+
console.log("Cleaning up browser pool...");
|
|
341
|
+
// Stop health checks immediately
|
|
342
|
+
if (this.healthCheckTimer) {
|
|
343
|
+
clearInterval(this.healthCheckTimer); // Cast to NodeJS.Timeout
|
|
344
|
+
this.healthCheckTimer = undefined;
|
|
345
|
+
console.log("Health checks stopped.");
|
|
346
|
+
}
|
|
347
|
+
// Create a copy of the pool to iterate over
|
|
348
|
+
const browsersToClose = [...this.pool];
|
|
349
|
+
console.log(`Closing ${browsersToClose.length} browser instance(s)...`);
|
|
350
|
+
// Close browsers and their contexts concurrently
|
|
351
|
+
await Promise.allSettled(browsersToClose.map(async (instance) => {
|
|
352
|
+
try {
|
|
353
|
+
// Ensure context is closed first if it exists
|
|
354
|
+
if (instance.context) {
|
|
355
|
+
await instance.context.close();
|
|
356
|
+
}
|
|
357
|
+
await instance.browser.close();
|
|
358
|
+
}
|
|
359
|
+
catch (error) {
|
|
360
|
+
console.error(`Error closing browser or context (ID: ${instance.metrics.id}) during cleanup:`, error);
|
|
361
|
+
}
|
|
362
|
+
}));
|
|
363
|
+
this.pool = []; // Ensure pool is empty
|
|
364
|
+
this.isCleaningUp = false;
|
|
365
|
+
console.log("Browser pool cleanup complete.");
|
|
366
|
+
}
|
|
367
|
+
// getMetrics remains largely the same, ensure it reflects Playwright structure
|
|
368
|
+
getMetrics() {
|
|
369
|
+
// Return a deep copy of metrics to prevent external modification
|
|
370
|
+
return this.pool.map((instance) => ({
|
|
371
|
+
...instance.metrics,
|
|
372
|
+
// Ensure isHealthy and activePages are correctly sourced if not updated elsewhere
|
|
373
|
+
isHealthy: instance.isHealthy,
|
|
374
|
+
activePages: instance.context?.pages()?.length ?? instance.metrics.activePages ?? 0, // Get latest count from context if possible
|
|
375
|
+
}));
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
//# sourceMappingURL=BrowserPool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BrowserPool.js","sourceRoot":"","sources":["../../src/browser/BrowserPool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { Page } from "playwright";
|
|
2
|
+
import type { BrowserMetrics } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Manages a pool of Playwright Browser instances for efficient reuse.
|
|
5
|
+
*/
|
|
6
|
+
export declare class PlaywrightBrowserPool {
|
|
7
|
+
private pool;
|
|
8
|
+
private readonly maxBrowsers;
|
|
9
|
+
private readonly maxPagesPerContext;
|
|
10
|
+
private readonly maxBrowserAge;
|
|
11
|
+
private readonly healthCheckInterval;
|
|
12
|
+
private healthCheckTimer;
|
|
13
|
+
private readonly maxIdleTime;
|
|
14
|
+
private isCleaningUp;
|
|
15
|
+
private readonly useHeadedMode;
|
|
16
|
+
private readonly blockedDomains;
|
|
17
|
+
private readonly blockedResourceTypes;
|
|
18
|
+
private readonly proxyConfig?;
|
|
19
|
+
private static readonly DEFAULT_BLOCKED_DOMAINS;
|
|
20
|
+
private static readonly DEFAULT_BLOCKED_RESOURCE_TYPES;
|
|
21
|
+
private readonly acquireQueue;
|
|
22
|
+
constructor(config?: {
|
|
23
|
+
maxBrowsers?: number;
|
|
24
|
+
maxPagesPerContext?: number;
|
|
25
|
+
maxBrowserAge?: number;
|
|
26
|
+
healthCheckInterval?: number;
|
|
27
|
+
useHeadedMode?: boolean;
|
|
28
|
+
blockedDomains?: string[];
|
|
29
|
+
blockedResourceTypes?: string[];
|
|
30
|
+
proxy?: {
|
|
31
|
+
server: string;
|
|
32
|
+
username?: string;
|
|
33
|
+
password?: string;
|
|
34
|
+
};
|
|
35
|
+
maxIdleTime?: number;
|
|
36
|
+
});
|
|
37
|
+
/**
|
|
38
|
+
* Initializes the pool and starts health checks.
|
|
39
|
+
*/
|
|
40
|
+
initialize(): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Schedules the next health check.
|
|
43
|
+
*/
|
|
44
|
+
private scheduleHealthCheck;
|
|
45
|
+
/**
|
|
46
|
+
* Ensures the pool has the configured maximum number of browser instances.
|
|
47
|
+
*/
|
|
48
|
+
private ensureMinimumInstances;
|
|
49
|
+
/**
|
|
50
|
+
* Creates a new Playwright Browser instance and adds it to the pool.
|
|
51
|
+
*/
|
|
52
|
+
private createBrowserInstance;
|
|
53
|
+
/**
|
|
54
|
+
* Acquires a Page from a healthy browser instance in the pool.
|
|
55
|
+
*/
|
|
56
|
+
acquirePage(): Promise<Page>;
|
|
57
|
+
/**
|
|
58
|
+
* Performs health checks on all instances.
|
|
59
|
+
*/
|
|
60
|
+
private healthCheck;
|
|
61
|
+
/**
|
|
62
|
+
* Closes and removes a browser instance from the pool.
|
|
63
|
+
*/
|
|
64
|
+
private closeAndRemoveInstance;
|
|
65
|
+
/**
|
|
66
|
+
* Releases a page back to the pool, closing it.
|
|
67
|
+
*/
|
|
68
|
+
releasePage(page: Page): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Stops health checks and closes all browser instances.
|
|
71
|
+
*/
|
|
72
|
+
cleanup(): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Retrieves metrics for each browser instance in the pool.
|
|
75
|
+
*/
|
|
76
|
+
getMetrics(): BrowserMetrics[];
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=PlaywrightBrowserPool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PlaywrightBrowserPool.d.ts","sourceRoot":"","sources":["../../src/browser/PlaywrightBrowserPool.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAGV,IAAI,EAIL,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AA4BlD;;GAEG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,IAAI,CAA6C;IACzD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,gBAAgB,CAA+B;IACvD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;IACrD,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IAExC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAW;IAC1C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAW;IAEhD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAI3B;IAGF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAwB7C;IACF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,8BAA8B,CAOpD;IAEF,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA0C;gBAGrE,MAAM,GAAE;QACN,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;QAChC,KAAK,CAAC,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACjE,WAAW,CAAC,EAAE,MAAM,CAAC;KACjB;IAqBR;;OAEG;IACU,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMxC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAc3B;;OAEG;YACW,sBAAsB;IAapC;;OAEG;YACW,qBAAqB;IA+FnC;;OAEG;IACI,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAqEnC;;OAEG;YACW,WAAW;IAiEzB;;OAEG;YACW,sBAAsB;IAoBpC;;OAEG;IACU,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCnD;;OAEG;IACU,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBrC;;OAEG;IACI,UAAU,IAAI,cAAc,EAAE;CAQtC"}
|