1extern crate diesel;
2extern crate mobc;
3
4#[macro_use]
5extern crate async_trait;
6
7use diesel::{Connection, ConnectionError};
8use mobc::Manager as ManageConnection;
9use std::convert::Into;
10use std::fmt;
11use std::marker::PhantomData;
12
13pub struct ConnectionManager<T> {
14 database_url: String,
15 _marker: PhantomData<T>,
16}
17
18unsafe impl<T: Send + 'static> Sync for ConnectionManager<T> {}
19
20impl<T> ConnectionManager<T> {
21 pub fn new<S: Into<String>>(database_url: S) -> Self {
22 ConnectionManager {
23 database_url: database_url.into(),
24 _marker: PhantomData,
25 }
26 }
27}
28
29#[derive(Debug)]
30pub enum Error {
31 ConnectionError(ConnectionError),
32 QueryError(diesel::result::Error),
33}
34
35impl fmt::Display for Error {
36 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
37 match *self {
38 Error::ConnectionError(ref e) => e.fmt(f),
39 Error::QueryError(ref e) => e.fmt(f),
40 }
41 }
42}
43
44impl ::std::error::Error for Error {
45 fn description(&self) -> &str {
46 match *self {
47 Error::ConnectionError(ref e) => e.description(),
48 Error::QueryError(ref e) => e.description(),
49 }
50 }
51}
52
53#[async_trait]
54impl<T> ManageConnection for ConnectionManager<T>
55where
56 T: Connection + Send + 'static,
57{
58 type Connection = T;
59 type Error = Error;
60
61 async fn connect(&self) -> Result<T, Error> {
62 T::establish(&self.database_url).map_err(Error::ConnectionError)
63 }
64
65 async fn check(&self, conn: T) -> Result<T, Error> {
66 conn.execute("SELECT 1")
67 .map(|_| conn)
68 .map_err(Error::QueryError)
69 }
70}