mirror of https://github.com/rwf2/Rocket.git
Update 'diesel-async' in 'db_pools' to 0.5.
Also modifies the `databases` example so that it makes use of the new ability to run migrations in diesel-async v0.5. To accomplish this, `diesel_async::async_connection_wrapper::AsyncConnectionWrapper` is exported from `rocket_db_pools::diesel` and used in the `diesel_mysql` portion of the `databases` example. The URL for the MySQL version of the database example is now `/mysql` instead of `/diesel-async`.
This commit is contained in:
parent
1a3ef5b23f
commit
87f80714fa
|
@ -26,8 +26,8 @@ sqlx_postgres = ["sqlx", "sqlx/postgres", "log"]
|
||||||
sqlx_sqlite = ["sqlx", "sqlx/sqlite", "log"]
|
sqlx_sqlite = ["sqlx", "sqlx/sqlite", "log"]
|
||||||
sqlx_macros = ["sqlx/macros"]
|
sqlx_macros = ["sqlx/macros"]
|
||||||
# diesel features
|
# diesel features
|
||||||
diesel_postgres = ["diesel-async/postgres", "diesel-async/deadpool", "diesel", "deadpool_09"]
|
diesel_postgres = ["diesel-async/postgres", "diesel-async/deadpool", "deadpool", "diesel"]
|
||||||
diesel_mysql = ["diesel-async/mysql", "diesel-async/deadpool", "diesel", "deadpool_09"]
|
diesel_mysql = ["diesel-async/mysql", "diesel-async/deadpool", "deadpool", "diesel"]
|
||||||
# implicit features: mongodb
|
# implicit features: mongodb
|
||||||
|
|
||||||
[dependencies.rocket]
|
[dependencies.rocket]
|
||||||
|
@ -39,9 +39,8 @@ default-features = false
|
||||||
path = "../codegen"
|
path = "../codegen"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
[dependencies.deadpool_09]
|
[dependencies.deadpool]
|
||||||
package = "deadpool"
|
version = "0.12.1"
|
||||||
version = "0.9.5"
|
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["rt_tokio_1", "managed"]
|
features = ["rt_tokio_1", "managed"]
|
||||||
optional = true
|
optional = true
|
||||||
|
@ -52,12 +51,6 @@ default-features = false
|
||||||
features = ["rt_tokio_1"]
|
features = ["rt_tokio_1"]
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.deadpool]
|
|
||||||
version = "0.12.1"
|
|
||||||
default-features = false
|
|
||||||
features = ["rt_tokio_1", "managed"]
|
|
||||||
optional = true
|
|
||||||
|
|
||||||
[dependencies.deadpool-redis]
|
[dependencies.deadpool-redis]
|
||||||
version = "0.15"
|
version = "0.15"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
@ -71,8 +64,9 @@ features = ["compat-3-0-0", "rustls-tls"]
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.diesel-async]
|
[dependencies.diesel-async]
|
||||||
version = "0.4.1"
|
version = "0.5.0"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
features = ["async-connection-wrapper"]
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.diesel]
|
[dependencies.diesel]
|
||||||
|
|
|
@ -84,6 +84,9 @@ pub use diesel_async::pg;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use diesel_async::pooled_connection::deadpool::Pool;
|
pub use diesel_async::pooled_connection::deadpool::Pool;
|
||||||
|
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use diesel_async::async_connection_wrapper::AsyncConnectionWrapper;
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
#[cfg(feature = "diesel_mysql")]
|
#[cfg(feature = "diesel_mysql")]
|
||||||
pub use diesel_async::AsyncMysqlConnection;
|
pub use diesel_async::AsyncMysqlConnection;
|
||||||
|
|
|
@ -157,6 +157,9 @@ mod deadpool_postgres {
|
||||||
use deadpool::{Runtime, managed::{Manager, Pool, PoolError, Object}};
|
use deadpool::{Runtime, managed::{Manager, Pool, PoolError, Object}};
|
||||||
use super::{Duration, Error, Config, Figment};
|
use super::{Duration, Error, Config, Figment};
|
||||||
|
|
||||||
|
#[cfg(feature = "diesel")]
|
||||||
|
use diesel_async::pooled_connection::AsyncDieselConnectionManager;
|
||||||
|
|
||||||
pub trait DeadManager: Manager + Sized + Send + Sync + 'static {
|
pub trait DeadManager: Manager + Sized + Send + Sync + 'static {
|
||||||
fn new(config: &Config) -> Result<Self, Self::Error>;
|
fn new(config: &Config) -> Result<Self, Self::Error>;
|
||||||
}
|
}
|
||||||
|
@ -175,6 +178,20 @@ mod deadpool_postgres {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "diesel_postgres")]
|
||||||
|
impl DeadManager for AsyncDieselConnectionManager<diesel_async::AsyncPgConnection> {
|
||||||
|
fn new(config: &Config) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Self::new(config.url.as_str()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "diesel_mysql")]
|
||||||
|
impl DeadManager for AsyncDieselConnectionManager<diesel_async::AsyncMysqlConnection> {
|
||||||
|
fn new(config: &Config) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Self::new(config.url.as_str()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[rocket::async_trait]
|
#[rocket::async_trait]
|
||||||
impl<M: DeadManager, C: From<Object<M>>> crate::Pool for Pool<M, C>
|
impl<M: DeadManager, C: From<Object<M>>> crate::Pool for Pool<M, C>
|
||||||
where M::Type: Send, C: Send + Sync + 'static, M::Error: std::error::Error
|
where M::Type: Send, C: Send + Sync + 'static, M::Error: std::error::Error
|
||||||
|
@ -207,64 +224,6 @@ mod deadpool_postgres {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove when new release of diesel-async with deadpool 0.10 is out.
|
|
||||||
#[cfg(all(feature = "deadpool_09", any(feature = "diesel_postgres", feature = "diesel_mysql")))]
|
|
||||||
mod deadpool_old {
|
|
||||||
use deadpool_09::{managed::{Manager, Pool, PoolError, Object, BuildError}, Runtime};
|
|
||||||
use diesel_async::pooled_connection::AsyncDieselConnectionManager;
|
|
||||||
|
|
||||||
use super::{Duration, Error, Config, Figment};
|
|
||||||
|
|
||||||
pub trait DeadManager: Manager + Sized + Send + Sync + 'static {
|
|
||||||
fn new(config: &Config) -> Result<Self, Self::Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "diesel_postgres")]
|
|
||||||
impl DeadManager for AsyncDieselConnectionManager<diesel_async::AsyncPgConnection> {
|
|
||||||
fn new(config: &Config) -> Result<Self, Self::Error> {
|
|
||||||
Ok(Self::new(config.url.as_str()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "diesel_mysql")]
|
|
||||||
impl DeadManager for AsyncDieselConnectionManager<diesel_async::AsyncMysqlConnection> {
|
|
||||||
fn new(config: &Config) -> Result<Self, Self::Error> {
|
|
||||||
Ok(Self::new(config.url.as_str()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rocket::async_trait]
|
|
||||||
impl<M: DeadManager, C: From<Object<M>>> crate::Pool for Pool<M, C>
|
|
||||||
where M::Type: Send, C: Send + Sync + 'static, M::Error: std::error::Error
|
|
||||||
{
|
|
||||||
type Error = Error<BuildError<M::Error>, PoolError<M::Error>>;
|
|
||||||
|
|
||||||
type Connection = C;
|
|
||||||
|
|
||||||
async fn init(figment: &Figment) -> Result<Self, Self::Error> {
|
|
||||||
let config: Config = figment.extract()?;
|
|
||||||
let manager = M::new(&config).map_err(|e| Error::Init(BuildError::Backend(e)))?;
|
|
||||||
|
|
||||||
Pool::builder(manager)
|
|
||||||
.max_size(config.max_connections)
|
|
||||||
.wait_timeout(Some(Duration::from_secs(config.connect_timeout)))
|
|
||||||
.create_timeout(Some(Duration::from_secs(config.connect_timeout)))
|
|
||||||
.recycle_timeout(config.idle_timeout.map(Duration::from_secs))
|
|
||||||
.runtime(Runtime::Tokio1)
|
|
||||||
.build()
|
|
||||||
.map_err(Error::Init)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get(&self) -> Result<Self::Connection, Self::Error> {
|
|
||||||
self.get().await.map_err(Error::Get)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn close(&self) {
|
|
||||||
<Pool<M, C>>::close(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "sqlx")]
|
#[cfg(feature = "sqlx")]
|
||||||
mod sqlx {
|
mod sqlx {
|
||||||
use sqlx::ConnectOptions;
|
use sqlx::ConnectOptions;
|
||||||
|
|
|
@ -130,7 +130,7 @@ impl Poolable for diesel::SqliteConnection {
|
||||||
fn on_acquire(&self, conn: &mut SqliteConnection) -> Result<(), Error> {
|
fn on_acquire(&self, conn: &mut SqliteConnection) -> Result<(), Error> {
|
||||||
conn.batch_execute("\
|
conn.batch_execute("\
|
||||||
PRAGMA journal_mode = WAL;\
|
PRAGMA journal_mode = WAL;\
|
||||||
PRAGMA busy_timeout = 1000;\
|
PRAGMA busy_timeout = 5000;\
|
||||||
PRAGMA foreign_keys = ON;\
|
PRAGMA foreign_keys = ON;\
|
||||||
").map_err(Error::QueryError)?;
|
").map_err(Error::QueryError)?;
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ This example implements a JSON-based HTTP API for a "blog" using several databas
|
||||||
* `sqlx` (`/sqlx`, `sqlx.rs`)
|
* `sqlx` (`/sqlx`, `sqlx.rs`)
|
||||||
* `rusqlite` (`/rusqlite`, `rusqlite.rs`)
|
* `rusqlite` (`/rusqlite`, `rusqlite.rs`)
|
||||||
* `diesel` (sqlite) (`/diesel`, `diesel_sqlite.rs`)
|
* `diesel` (sqlite) (`/diesel`, `diesel_sqlite.rs`)
|
||||||
* `diesel-async` (mysql) (`/diesel-async`, `diesel_mysql.rs`)
|
* `diesel-async` (mysql) (`/mysql`, `diesel_mysql.rs`)
|
||||||
|
|
||||||
The exposed API is succinctly described as follows, with
|
The exposed API is succinctly described as follows, with
|
||||||
[`httpie`](https://httpie.io/) CLI examples:
|
[`httpie`](https://httpie.io/) CLI examples:
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
use rocket::{Rocket, Build};
|
||||||
use rocket::fairing::AdHoc;
|
use rocket::fairing::AdHoc;
|
||||||
use rocket::response::{Debug, status::Created};
|
use rocket::response::{Debug, status::Created};
|
||||||
use rocket::serde::{Serialize, Deserialize, json::Json};
|
use rocket::serde::{Serialize, Deserialize, json::Json};
|
||||||
|
|
||||||
use rocket_db_pools::{Database, Connection};
|
use rocket_db_pools::{Database, Connection};
|
||||||
use rocket_db_pools::diesel::{MysqlPool, prelude::*};
|
use rocket_db_pools::diesel::{prelude::*, MysqlPool};
|
||||||
|
|
||||||
type Result<T, E = Debug<diesel::result::Error>> = std::result::Result<T, E>;
|
type Result<T, E = Debug<diesel::result::Error>> = std::result::Result<T, E>;
|
||||||
|
|
||||||
|
@ -34,7 +35,7 @@ diesel::table! {
|
||||||
|
|
||||||
#[post("/", data = "<post>")]
|
#[post("/", data = "<post>")]
|
||||||
async fn create(mut db: Connection<Db>, mut post: Json<Post>) -> Result<Created<Json<Post>>> {
|
async fn create(mut db: Connection<Db>, mut post: Json<Post>) -> Result<Created<Json<Post>>> {
|
||||||
diesel::sql_function!(fn last_insert_id() -> BigInt);
|
diesel::define_sql_function!(fn last_insert_id() -> BigInt);
|
||||||
|
|
||||||
let post = db.transaction(|mut conn| Box::pin(async move {
|
let post = db.transaction(|mut conn| Box::pin(async move {
|
||||||
diesel::insert_into(posts::table)
|
diesel::insert_into(posts::table)
|
||||||
|
@ -89,9 +90,33 @@ async fn destroy(mut db: Connection<Db>) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn run_migrations(rocket: Rocket<Build>) -> Rocket<Build> {
|
||||||
|
use rocket_db_pools::diesel::AsyncConnectionWrapper;
|
||||||
|
use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
|
||||||
|
|
||||||
|
const MIGRATIONS: EmbeddedMigrations = embed_migrations!("db/diesel/mysql-migrations");
|
||||||
|
|
||||||
|
let conn = Db::fetch(&rocket)
|
||||||
|
.expect("database is attached")
|
||||||
|
.get().await
|
||||||
|
.unwrap_or_else(|e| {
|
||||||
|
span_error!("failed to connect to MySQL database" => error!("{e}"));
|
||||||
|
panic!("aborting launch");
|
||||||
|
});
|
||||||
|
|
||||||
|
// `run_pending_migrations` blocks, so it must be run in `spawn_blocking`
|
||||||
|
rocket::tokio::task::spawn_blocking(move || {
|
||||||
|
let mut conn: AsyncConnectionWrapper<_> = conn.into();
|
||||||
|
conn.run_pending_migrations(MIGRATIONS).expect("diesel migrations");
|
||||||
|
}).await.expect("diesel migrations");
|
||||||
|
|
||||||
|
rocket
|
||||||
|
}
|
||||||
|
|
||||||
pub fn stage() -> AdHoc {
|
pub fn stage() -> AdHoc {
|
||||||
AdHoc::on_ignite("Diesel MySQL Stage", |rocket| async {
|
AdHoc::on_ignite("Diesel MySQL Stage", |rocket| async {
|
||||||
rocket.attach(Db::init())
|
rocket.attach(Db::init())
|
||||||
.mount("/diesel-async", routes![list, read, create, delete, destroy])
|
.attach(AdHoc::on_ignite("Diesel Migrations", run_migrations))
|
||||||
|
.mount("/mysql", routes![list, read, create, delete, destroy])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue