1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
//! Connection Pooling with r2d2. //! use crate::{ConnectParams, Connection, HdbError, HdbResult, IntoConnectParams}; /// Implementation of r2d2's /// [`ManageConnection`](https://docs.rs/r2d2/*/r2d2/trait.ManageConnection.html) /// interface. /// /// # Example /// /// ```rust,no_run /// # use hdbconnect::{ConnectionManager, ConnectParams, HdbResult}; /// # use std::thread; /// # const NUM_THREADS:usize = 15; /// # const POOL_SIZE:u32 = 5; /// /// let connect_params = ConnectParams::builder() /// .hostname("abcd123") /// .port(2222) /// .dbuser("MEIER") /// .password("schlau") /// .build() /// .unwrap(); /// let manager = ConnectionManager::new(&connect_params).unwrap(); /// let pool = r2d2::Pool::builder().max_size(POOL_SIZE).build(manager).unwrap(); /// /// for _ in 0..NUM_THREADS { /// let pool = pool.clone(); /// thread::spawn(move || { /// let mut conn = pool.get().unwrap(); /// // ... work with your connection /// }); /// } /// /// ``` /// #[derive(Debug)] pub struct ConnectionManager { connect_params: ConnectParams, } impl ConnectionManager { /// Creates a new `ConnectionManager`. /// /// # Errors /// /// `HdbError::Usage` if not enough or inconsistent information was provided pub fn new<P: IntoConnectParams>(p: P) -> HdbResult<Self> { Ok(Self { connect_params: p.into_connect_params()?, }) } } impl r2d2::ManageConnection for ConnectionManager { type Connection = Connection; type Error = HdbError; // Attempts to create a new connection. fn connect(&self) -> Result<Self::Connection, Self::Error> { trace!("ConnectionManager::connect()"); Connection::new(&self.connect_params) } // Determines if the connection is still connected to the database. // A standard implementation would check if a simple query like SELECT 1 succeeds. fn is_valid(&self, conn: &mut Self::Connection) -> Result<(), Self::Error> { trace!("ConnectionManager::is_valid()"); conn.query("SELECT 'IsConnectionStillAlive' from dummy") .map(|_| ()) } // *Quickly* determines if the connection is no longer usable. // This will be called synchronously every time a connection is returned to the pool, // so it should not block. If it returns true, the connection will be discarded. // For example, an implementation might check if the underlying TCP socket has disconnected. // Implementations that do not support this kind of fast health check may simply return false. fn has_broken(&self, _conn: &mut Self::Connection) -> bool { trace!("ConnectionManager::has_broken()"); false // TODO } }