1use std::{collections::VecDeque, sync::Arc};
6
7use parking_lot::Mutex;
8
9use crate::{page::Page, stealth::StealthProfile};
10
11pub struct PagePool {
13 idle_pages: Arc<Mutex<VecDeque<Page>>>,
14 max_size: usize,
15}
16
17impl PagePool {
18 #[allow(
19 clippy::arc_with_non_send_sync,
20 reason = "single-threaded page pool; Arc shares idle queue within one thread"
21 )]
22 pub fn new(max_size: usize) -> Self {
23 Self {
24 idle_pages: Arc::new(Mutex::new(VecDeque::with_capacity(max_size))),
25 max_size,
26 }
27 }
28
29 pub async fn acquire(
34 &self,
35 profile: Option<StealthProfile>,
36 ) -> Result<Page, crate::page::PageError> {
37 if let Some(mut page) = self.idle_pages.lock().pop_front() {
39 page.reload_html("<html><head></head><body></body></html>", "about:blank");
40 return Ok(page);
41 }
42 Page::from_html("<html><head></head><body></body></html>", profile.is_some()).await
44 }
45
46 pub fn release(&self, page: Page) {
48 let mut pages = self.idle_pages.lock();
49 if pages.len() < self.max_size {
50 pages.push_back(page);
51 }
52 }
53
54 pub async fn navigate(
56 &self,
57 url: &str,
58 profile: StealthProfile,
59 ) -> Result<Page, crate::page::PageError> {
60 let mut page = self.acquire(Some(profile)).await?;
61 page.navigate_warm(url).await?;
62 Ok(page)
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[tokio::test]
71 async fn pool_acquire_creates_page() {
72 let pool = PagePool::new(4);
73 let page = pool.acquire(None).await;
74 assert!(page.is_ok());
75 }
76
77 #[tokio::test]
78 async fn pool_release_and_reacquire() {
79 let pool = PagePool::new(4);
80 let page = pool.acquire(None).await.unwrap();
81 pool.release(page);
82 let page2 = pool.acquire(None).await;
83 assert!(page2.is_ok());
84 }
85
86 #[tokio::test]
87 async fn pool_respects_max_size() {
88 let pool = PagePool::new(1);
89 let p1 = pool.acquire(None).await.unwrap();
90 let p2 = pool.acquire(None).await.unwrap();
91 pool.release(p1);
92 pool.release(p2); let count = pool.idle_pages.lock().len();
94 assert_eq!(count, 1);
95 }
96}