Skip to main content

fraiseql_db/
wire_pool.rs

1//! Connection pool for fraiseql-wire clients.
2//!
3//! fraiseql-wire's `FraiseClient` consumes itself on query execution,
4//! so we implement a simple connection factory pattern instead of traditional pooling.
5
6use std::sync::Arc;
7
8use fraiseql_error::{FraiseQLError, Result};
9
10/// Connection factory for fraiseql-wire clients.
11///
12/// Since `FraiseClient::query()` consumes the client, we store the connection string
13/// and create new clients on demand rather than pooling connections.
14#[derive(Debug, Clone)]
15pub struct WireClientFactory {
16    connection_string: Arc<String>,
17}
18
19impl WireClientFactory {
20    /// Create a new client factory.
21    ///
22    /// # Arguments
23    ///
24    /// * `connection_string` - PostgreSQL connection string (e.g., "postgres://localhost/mydb")
25    ///
26    /// # Example
27    ///
28    /// ```ignore
29    /// use fraiseql_core::db::wire_pool::WireClientFactory;
30    ///
31    /// let factory = WireClientFactory::new("postgres://localhost/fraiseql");
32    /// ```
33    #[must_use]
34    pub fn new(connection_string: impl Into<String>) -> Self {
35        Self {
36            connection_string: Arc::new(connection_string.into()),
37        }
38    }
39
40    /// Create a new fraiseql-wire client.
41    ///
42    /// This method creates a fresh connection each time it's called.
43    /// The connection is closed when the client is dropped after query execution.
44    ///
45    /// # Returns
46    ///
47    /// A new `FraiseClient` ready for query execution.
48    ///
49    /// # Errors
50    ///
51    /// Returns `FraiseQLError::ConnectionPool` if connection fails.
52    ///
53    /// # Example
54    ///
55    /// ```ignore
56    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
57    /// use fraiseql_core::db::wire_pool::WireClientFactory;
58    ///
59    /// let factory = WireClientFactory::new("postgres://localhost/fraiseql");
60    /// let client = factory.create_client().await?;
61    /// # Ok(())
62    /// # }
63    /// ```
64    pub async fn create_client(&self) -> Result<fraiseql_wire::FraiseClient> {
65        fraiseql_wire::FraiseClient::connect(&self.connection_string)
66            .await
67            .map_err(|e| FraiseQLError::ConnectionPool {
68                message: format!("Failed to create fraiseql-wire client: {e}"),
69            })
70    }
71
72    /// Get the connection string.
73    #[must_use]
74    pub fn connection_string(&self) -> &str {
75        &self.connection_string
76    }
77}
78
79#[cfg(test)]
80mod tests;