Use 'tokio_executor::blocking' when acquiring connections from synchronous database pools to avoid tying up the executor.

This commit is contained in:
Jeb Rosen 2019-10-20 14:25:10 -07:00 committed by Sergio Benitez
parent adf7e4233a
commit 0ab787e216
3 changed files with 17 additions and 8 deletions

View File

@ -73,6 +73,7 @@ pub fn database_attr(attr: TokenStream, input: TokenStream) -> Result<TokenStrea
let databases = quote_spanned!(span => ::rocket_contrib::databases);
let Poolable = quote_spanned!(span => #databases::Poolable);
let r2d2 = quote_spanned!(span => #databases::r2d2);
let tokio_executor = quote_spanned!(span => #databases::tokio_executor);
let request = quote!(::rocket::request);
let generated_types = quote_spanned! { span =>
@ -140,17 +141,21 @@ pub fn database_attr(attr: TokenStream, input: TokenStream) -> Result<TokenStrea
}
}
impl<'a, 'r> #request::FromRequest<'a, 'r> for #guard_type {
impl<'a, 'r> #request::FromRequestAsync<'a, 'r> for #guard_type {
type Error = ();
fn from_request(request: &'a #request::Request<'r>) -> #request::Outcome<Self, ()> {
fn from_request<'fut>(request: &'a #request::Request<'r>) -> #request::FromRequestFuture<'fut, Self, Self::Error> where 'a: 'fut {
use ::rocket::{Outcome, http::Status};
let pool = ::rocket::try_outcome!(request.guard::<::rocket::State<#pool_type>>());
Box::pin(async move {
let pool = ::rocket::try_outcome!(request.guard::<::rocket::State<'_, #pool_type>>()).0.clone();
match pool.0.get() {
Ok(conn) => Outcome::Success(#guard_type(conn)),
Err(_) => Outcome::Failure((Status::ServiceUnavailable, ())),
}
#tokio_executor::blocking::run(move || {
match pool.get() {
Ok(conn) => Outcome::Success(#guard_type(conn)),
Err(_) => Outcome::Failure((Status::ServiceUnavailable, ())),
}
}).await
})
}
}
}.into())

View File

@ -14,7 +14,7 @@ edition = "2018"
[features]
# Internal use only.
templates = ["serde", "serde_json", "glob", "notify"]
databases = ["r2d2", "rocket_contrib_codegen/database_attribute"]
databases = ["r2d2", "tokio-executor", "rocket_contrib_codegen/database_attribute"]
# User-facing features.
default = ["json", "serve"]
@ -66,6 +66,7 @@ uuid = { version = ">=0.7.0, <0.9.0", optional = true }
diesel = { version = "1.0", default-features = false, optional = true }
postgres = { version = "0.17", optional = true }
r2d2 = { version = "0.8", optional = true }
tokio-executor = { version = "0.2.0-alpha.6", optional = true }
r2d2_postgres = { version = "0.16", optional = true }
mysql = { version = "17.0", optional = true }
r2d2_mysql = { version = "17.0", optional = true }

View File

@ -397,6 +397,9 @@
pub extern crate r2d2;
#[doc(hidden)]
pub extern crate tokio_executor;
#[cfg(any(feature = "diesel_sqlite_pool",
feature = "diesel_postgres_pool",
feature = "diesel_mysql_pool"))]