picodata_rust/
client.rs

1use std::sync::Arc;
2
3use crate::{
4    config::Config,
5    error::Error,
6    manager::Manager,
7    strategy::{RoundRobin, Strategy},
8};
9
10/// Client which is used to query picodata.
11#[derive(Clone)]
12pub struct Client {
13    /// Connection manager.
14    manager: Arc<Manager>,
15}
16
17impl Client {
18    /// Creates a new instance of picodata client.
19    ///
20    /// # Parameters
21    ///
22    /// - `config`: A config for a client.
23    ///
24    /// # Errors
25    ///
26    /// - Any [`Error`] than manager initializer may return.
27    ///
28    /// # Returns
29    ///
30    /// An instance of `Client` on success or an `Error` if manager init did fail.
31    pub async fn new(config: Config) -> Result<Self, Error> {
32        let manager = Arc::new(Manager::new(config, RoundRobin::new()).await?);
33        Ok(Self { manager })
34    }
35
36    /// Creates a new instance of picodata client with a custom strategy.
37    ///
38    /// # Parameters
39    ///
40    /// - `config`: A config for a client.
41    /// - `strategy`: A strategy that descibes the method to pick next connection.
42    ///
43    /// # Errors
44    ///
45    /// - Any [`Error`] than manager initializer may return.
46    ///
47    /// # Returns
48    ///
49    /// An instance of `Client` on success or an `Error` if manager init did fail.
50    pub async fn new_with_strategy<S>(config: Config, strategy: S) -> Result<Self, Error>
51    where
52        S: Strategy,
53    {
54        let manager = Arc::new(Manager::new(config, strategy).await?);
55        Ok(Self { manager })
56    }
57
58    /// Query picodata cluster.
59    ///
60    /// # Parameters
61    ///
62    /// - `sql`: A query to execute.
63    /// - `params`: A query bind params.
64    ///
65    /// # Errors
66    ///
67    /// - [`Error::Postgres`] in case of failed query exeuction.
68    /// - [`Error::PostgresPool`] in case of failed connection acquire.
69    ///
70    /// # Returns
71    ///
72    /// A vector of rows in case of success or an `Error` otherwise.
73    pub async fn query(
74        &self,
75        sql: &str,
76        params: &[&(dyn pg::types::ToSql + Sync)],
77    ) -> Result<Vec<pg::Row>, Error> {
78        let client = self.manager.next().await?.get().await?;
79        Ok(client.query(sql, params).await?)
80    }
81
82    /// Execute on picodata cluster.
83    ///
84    /// # Parameters
85    ///
86    /// - `sql`: A query to execute.
87    /// - `params`: A query bind params.
88    ///
89    /// # Errors
90    ///
91    /// - [`Error::Postgres`] in case of failed query exeuction.
92    /// - [`Error::PostgresPool`] in case of failed connection acquire.
93    ///
94    /// # Returns
95    ///
96    /// A unit in case of success or an `Error` otherwise.
97    pub async fn execute(
98        &self,
99        sql: &str,
100        params: &[&(dyn pg::types::ToSql + Sync)],
101    ) -> Result<u64, Error> {
102        let client = self.manager.next().await?.get().await?;
103        Ok(client.execute(sql, params).await?)
104    }
105
106    /// Ping each instance of picodata cluster.
107    ///
108    /// # Errors
109    ///
110    /// - [`Error::Postgres`] in case of failed query exeuction.
111    /// - [`Error::PostgresPool`] in case of failed connection acquire.
112    ///
113    /// # Returns
114    ///
115    /// A unit in case of success or an `Error` otherwise.
116    pub async fn ping(&self) -> Result<(), Error> {
117        self.manager
118            .map(|pool| async move {
119                let client = pool.get().await?;
120                client.simple_query("SELECT 1").await?;
121                Ok(())
122            })
123            .await?;
124        Ok(())
125    }
126
127    /// Closes pool manager.
128    ///
129    /// # Errors
130    ///
131    /// - Any [`Error`] that manager may return.
132    ///
133    /// # Returns
134    ///
135    /// A unit in case of success or an `Error` otherwise.
136    pub async fn close(&self) -> Result<(), Error> {
137        self.manager.close().await
138    }
139}