html2pdf_api/traits/
healthcheck.rs

1//! Health check trait for browser instances.
2//!
3//! This module provides the [`Healthcheck`] trait, which defines how
4//! browser instances verify they are still functional and responsive.
5//!
6//! # Overview
7//!
8//! The browser pool periodically pings active browsers to detect failures.
9//! When a browser fails too many consecutive health checks, it is removed
10//! from the pool and replaced.
11//!
12//! # Default Implementation
13//!
14//! [`TrackedBrowser`](crate::TrackedBrowser) implements this trait by:
15//! 1. Creating a new tab
16//! 2. Closing the tab
17//! 3. Updating the last ping timestamp
18//!
19//! This is a lightweight operation that verifies the browser process
20//! is alive and the CDP (Chrome DevTools Protocol) connection works.
21
22use crate::error::Result;
23
24/// Trait for browser-like objects that support health checking.
25///
26/// Implementors must provide a [`ping()`](Self::ping) method that verifies
27/// the browser is still functional and responsive.
28///
29/// # Thread Safety
30///
31/// This trait requires `Send + Sync` because browsers may be health-checked
32/// from a background thread while being used from another thread.
33///
34/// # Example Implementation
35///
36/// ```rust,ignore
37/// use html2pdf_api::{Healthcheck, Result, BrowserPoolError};
38///
39/// struct MyBrowser {
40///     inner: SomeBrowserType,
41/// }
42///
43/// impl Healthcheck for MyBrowser {
44///     fn ping(&self) -> Result<()> {
45///         // Try to create a tab to verify browser is responsive
46///         let tab = self.inner.new_tab()
47///             .map_err(|e| BrowserPoolError::HealthCheckFailed(e.to_string()))?;
48///         
49///         // Clean up
50///         let _ = tab.close();
51///         
52///         Ok(())
53///     }
54/// }
55/// ```
56///
57/// # How It's Used
58///
59/// The browser pool's keep-alive thread calls `ping()` on all active browsers
60/// at regular intervals (configured via
61/// [`ping_interval`](crate::BrowserPoolConfig::ping_interval)).
62///
63/// ```text
64/// Keep-Alive Thread
65///       │
66///       ├─── ping() ──→ Browser 1 ──→ ✓ OK
67///       │
68///       ├─── ping() ──→ Browser 2 ──→ ✗ Failed (count: 1)
69///       │
70///       └─── ping() ──→ Browser 3 ──→ ✓ OK
71/// ```
72///
73/// After [`max_ping_failures`](crate::BrowserPoolConfig::max_ping_failures)
74/// consecutive failures, the browser is removed and replaced.
75pub trait Healthcheck: Send + Sync {
76    /// Perform a health check on the browser.
77    ///
78    /// Should perform a lightweight operation like creating/closing a tab
79    /// to verify the browser process is still responsive.
80    ///
81    /// # Implementation Guidelines
82    ///
83    /// - **Keep it fast**: Health checks run frequently; avoid heavy operations
84    /// - **Don't hold locks**: Release any locks before performing I/O
85    /// - **Be idempotent**: Multiple calls should be safe
86    /// - **Clean up**: Close any tabs or resources created during the check
87    ///
88    /// # Errors
89    ///
90    /// Returns [`BrowserPoolError::HealthCheckFailed`](crate::BrowserPoolError::HealthCheckFailed)
91    /// if the health check fails (browser unresponsive or crashed).
92    ///
93    /// # Example
94    ///
95    /// ```rust,ignore
96    /// use html2pdf_api::{Healthcheck, Result};
97    ///
98    /// fn check_browser_health<T: Healthcheck>(browser: &T) -> Result<()> {
99    ///     browser.ping()?;
100    ///     println!("Browser is healthy!");
101    ///     Ok(())
102    /// }
103    /// ```
104    fn ping(&self) -> Result<()>;
105}