1use crate::{
2 AsEntity, AsQuery, Connection, Driver, Error, Executor, Query, QueryResult, Result, Row,
3 RowsAffected,
4};
5use anyhow::anyhow;
6use deadpool::managed::{Manager, Metrics, Object, Pool, RecycleResult, Timeouts};
7use futures::{FutureExt, Stream, future::BoxFuture};
8use std::{
9 borrow::Cow,
10 fmt::Debug,
11 future,
12 ops::{Deref, DerefMut},
13 sync::Arc,
14 time::Duration,
15};
16
17#[derive(Debug)]
24pub struct DBConnectionManager<D: Driver> {
25 driver: D,
26 url: Cow<'static, str>,
27}
28
29impl<D: Driver> DBConnectionManager<D> {
30 pub fn new(driver: D, url: Cow<'static, str>) -> Self {
31 Self { driver, url }
32 }
33}
34
35impl<D: Driver> Manager for DBConnectionManager<D> {
36 type Type = D::Connection;
37 type Error = Error;
38 async fn create(&self) -> Result<Self::Type> {
39 Ok(D::Connection::connect(&self.driver, self.url.clone()).await?)
40 }
41 fn recycle(
42 &self,
43 _: &mut Self::Type,
44 _: &Metrics,
45 ) -> impl Future<Output = RecycleResult<Self::Error>> + Send {
46 future::ready(RecycleResult::Ok(()))
47 }
48}
49
50#[derive(Debug)]
61pub struct PooledConnection<D: Driver> {
62 pub(crate) object: Object<DBConnectionManager<D>>,
63}
64
65pub trait ConnectionPool<D: Driver>: Sync + Send + Debug {
71 fn get<'s>(&'s self) -> BoxFuture<'s, Result<PooledConnection<D>>>;
78
79 fn timeout_get<'s>(&'s self, timeout: Duration) -> BoxFuture<'s, Result<PooledConnection<D>>>;
85
86 fn detach<'s>(&'s self) -> BoxFuture<'s, Result<D::Connection>>;
94
95 fn resize(&self, max_size: usize) -> Result<()>;
97
98 fn into_box(self) -> Box<dyn ConnectionPool<D> + Send + Sync>
100 where
101 Self: Sized,
102 D: 'static;
103
104 fn into_arc(self) -> Arc<dyn ConnectionPool<D> + Send + Sync>
106 where
107 Self: Sized,
108 D: 'static;
109
110 fn close(self) -> BoxFuture<'static, Result<()>>;
113}
114
115impl<D: Driver> ConnectionPool<D> for Pool<DBConnectionManager<D>>
116where
117 <D as Driver>::Connection: Debug,
118{
119 fn get<'s>(&'s self) -> BoxFuture<'s, Result<PooledConnection<D>>> {
120 async move {
121 let object = Pool::<DBConnectionManager<D>>::get(self)
122 .await
123 .map_err(|e| anyhow!("{e:#?}"))?;
124 Ok(PooledConnection { object })
125 }
126 .boxed()
127 }
128
129 fn timeout_get<'s>(&'s self, timeout: Duration) -> BoxFuture<'s, Result<PooledConnection<D>>> {
130 async move {
131 let object = Pool::<DBConnectionManager<D>>::timeout_get(
132 self,
133 &Timeouts::wait_millis(timeout.as_millis() as u64),
134 )
135 .await
136 .map_err(|e| anyhow!("{e:#?}"))?;
137 Ok(PooledConnection::<D> { object })
138 }
139 .boxed()
140 }
141
142 fn detach<'s>(&'s self) -> BoxFuture<'s, Result<D::Connection>>
143 where
144 Self: Sized,
145 {
146 async {
147 let v = Pool::<DBConnectionManager<D>>::get(self)
148 .await
149 .map_err(|e| anyhow!("{e:#?}"))?;
150 Ok(Object::<DBConnectionManager<D>>::take(v))
151 }
152 .boxed()
153 }
154
155 fn resize(&self, max_size: usize) -> Result<()> {
156 Ok(self.resize(max_size))
157 }
158
159 fn into_box(self) -> Box<dyn ConnectionPool<D> + Send + Sync>
160 where
161 Self: Sized,
162 D: 'static,
163 {
164 Box::new(self)
165 }
166
167 fn into_arc(self) -> Arc<dyn ConnectionPool<D> + Send + Sync>
168 where
169 Self: Sized,
170 D: 'static,
171 {
172 Arc::new(self)
173 }
174
175 fn close(self) -> BoxFuture<'static, Result<()>> {
176 Self::close(&self);
177 future::ready(Ok(())).boxed()
178 }
179}
180
181impl<D: Driver> Executor for PooledConnection<D> {
182 type Driver = D;
183
184 fn accepts_multiple_statements(&self) -> bool {
185 self.object.accepts_multiple_statements()
186 }
187
188 fn driver(&self) -> D {
189 self.object.driver()
190 }
191
192 fn prepare<'s>(
193 &'s mut self,
194 query: impl AsQuery<D> + 's,
195 ) -> impl Future<Output = Result<Query<D>>> + Send {
196 self.object.prepare(query)
197 }
198
199 fn do_prepare(&mut self, sql: String) -> impl Future<Output = Result<Query<D>>> + Send {
200 self.object.do_prepare(sql)
201 }
202
203 fn run<'s>(
204 &'s mut self,
205 query: impl AsQuery<D> + 's,
206 ) -> impl Stream<Item = Result<QueryResult>> + Send {
207 self.object.run(query)
208 }
209
210 fn fetch<'s>(
211 &'s mut self,
212 query: impl AsQuery<D> + 's,
213 ) -> impl Stream<Item = Result<Row>> + Send {
214 self.object.fetch(query)
215 }
216
217 fn execute<'s>(
218 &'s mut self,
219 query: impl AsQuery<D> + 's,
220 ) -> impl Future<Output = Result<RowsAffected>> + Send {
221 self.object.execute(query)
222 }
223
224 fn append<It>(&mut self, entities: It) -> impl Future<Output = Result<RowsAffected>> + Send
225 where
226 It: IntoIterator + Send,
227 It::IntoIter: Send,
228 It::Item: AsEntity,
229 {
230 self.object.append(entities)
231 }
232}
233
234impl<D: Driver> Connection for PooledConnection<D> {
235 fn connect(
236 _driver: &D,
237 _url: Cow<'static, str>,
238 ) -> impl Future<Output = Result<<D as Driver>::Connection>> + Send
239 where
240 Self: Sized,
241 {
242 future::ready(Err(anyhow!(
243 "Cannot connect using a PooledConnection, such object must be obtained from a connection pool",
244 )))
245 }
246
247 fn begin(&mut self) -> impl Future<Output = Result<<D as Driver>::Transaction<'_>>> + Send {
248 self.object.begin()
249 }
250}
251
252impl<D: Driver> Deref for PooledConnection<D> {
253 type Target = D::Connection;
254 fn deref(&self) -> &Self::Target {
255 &self.object
256 }
257}
258
259impl<D: Driver> DerefMut for PooledConnection<D> {
260 fn deref_mut(&mut self) -> &mut Self::Target {
261 &mut self.object
262 }
263}
264
265impl<D: Driver> AsRef<D::Connection> for PooledConnection<D> {
266 fn as_ref(&self) -> &D::Connection {
267 &self.object
268 }
269}
270
271impl<D: Driver> AsMut<D::Connection> for PooledConnection<D> {
272 fn as_mut(&mut self) -> &mut D::Connection {
273 &mut self.object
274 }
275}