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