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