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>: 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>>
100 where
101 D: 'static;
102
103 fn into_arc(self) -> Arc<dyn ConnectionPool<D>>
105 where
106 D: 'static;
107
108 fn close(self) -> BoxFuture<'static, Result<()>>;
111}
112
113impl<D: Driver> ConnectionPool<D> for Pool<DBConnectionManager<D>>
114where
115 <D as Driver>::Connection: Debug,
116{
117 fn get<'s>(&'s self) -> BoxFuture<'s, Result<PooledConnection<D>>> {
118 async move {
119 let object = Pool::<DBConnectionManager<D>>::get(self)
120 .await
121 .map_err(|e| anyhow!("{e:#?}"))?;
122 Ok(PooledConnection { object })
123 }
124 .boxed()
125 }
126
127 fn timeout_get<'s>(&'s self, timeout: Duration) -> BoxFuture<'s, Result<PooledConnection<D>>> {
128 async move {
129 let object = Pool::<DBConnectionManager<D>>::timeout_get(
130 self,
131 &Timeouts::wait_millis(timeout.as_millis() as u64),
132 )
133 .await
134 .map_err(|e| anyhow!("{e:#?}"))?;
135 Ok(PooledConnection::<D> { object })
136 }
137 .boxed()
138 }
139
140 fn detach<'s>(&'s self) -> BoxFuture<'s, Result<D::Connection>>
141 where
142 Self: Sized,
143 {
144 async {
145 let v = Pool::<DBConnectionManager<D>>::get(self)
146 .await
147 .map_err(|e| anyhow!("{e:#?}"))?;
148 Ok(Object::<DBConnectionManager<D>>::take(v))
149 }
150 .boxed()
151 }
152
153 fn resize(&self, max_size: usize) -> Result<()> {
154 Ok(self.resize(max_size))
155 }
156
157 fn into_box(self) -> Box<dyn ConnectionPool<D>>
158 where
159 D: 'static,
160 {
161 Box::new(self)
162 }
163
164 fn into_arc(self) -> Arc<dyn ConnectionPool<D>>
165 where
166 D: 'static,
167 {
168 Arc::new(self)
169 }
170
171 fn close(self) -> BoxFuture<'static, Result<()>> {
172 Self::close(&self);
173 future::ready(Ok(())).boxed()
174 }
175}
176
177impl<D: Driver> Executor for PooledConnection<D> {
178 type Driver = D;
179
180 fn accepts_multiple_statements(&self) -> bool {
181 self.object.accepts_multiple_statements()
182 }
183
184 fn driver(&self) -> D {
185 self.object.driver()
186 }
187
188 fn prepare<'s>(
189 &'s mut self,
190 query: impl AsQuery<D> + 's,
191 ) -> impl Future<Output = Result<Query<D>>> + Send {
192 self.object.prepare(query)
193 }
194
195 fn do_prepare(&mut self, sql: String) -> impl Future<Output = Result<Query<D>>> + Send {
196 self.object.do_prepare(sql)
197 }
198
199 fn run<'s>(
200 &'s mut self,
201 query: impl AsQuery<D> + 's,
202 ) -> impl Stream<Item = Result<QueryResult>> + Send {
203 self.object.run(query)
204 }
205
206 fn fetch<'s>(
207 &'s mut self,
208 query: impl AsQuery<D> + 's,
209 ) -> impl Stream<Item = Result<Row>> + Send {
210 self.object.fetch(query)
211 }
212
213 fn execute<'s>(
214 &'s mut self,
215 query: impl AsQuery<D> + 's,
216 ) -> impl Future<Output = Result<RowsAffected>> + Send {
217 self.object.execute(query)
218 }
219
220 fn append<It>(&mut self, entities: It) -> impl Future<Output = Result<RowsAffected>> + Send
221 where
222 It: IntoIterator + Send,
223 It::IntoIter: Send,
224 It::Item: AsEntity,
225 {
226 self.object.append(entities)
227 }
228}
229
230impl<D: Driver> Connection for PooledConnection<D> {
231 fn connect(
232 _driver: &D,
233 _url: Cow<'static, str>,
234 ) -> impl Future<Output = Result<<D as Driver>::Connection>> + Send
235 where
236 Self: Sized,
237 {
238 future::ready(Err(anyhow!(
239 "Cannot connect using a PooledConnection, such object must be obtained from a connection pool",
240 )))
241 }
242
243 fn begin(&mut self) -> impl Future<Output = Result<<D as Driver>::Transaction<'_>>> + Send {
244 self.object.begin()
245 }
246}
247
248impl<D: Driver> Deref for PooledConnection<D> {
249 type Target = D::Connection;
250 fn deref(&self) -> &Self::Target {
251 &self.object
252 }
253}
254
255impl<D: Driver> DerefMut for PooledConnection<D> {
256 fn deref_mut(&mut self) -> &mut Self::Target {
257 &mut self.object
258 }
259}
260
261impl<D: Driver> AsRef<D::Connection> for PooledConnection<D> {
262 fn as_ref(&self) -> &D::Connection {
263 &self.object
264 }
265}
266
267impl<D: Driver> AsMut<D::Connection> for PooledConnection<D> {
268 fn as_mut(&mut self) -> &mut D::Connection {
269 &mut self.object
270 }
271}