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