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}