Drop embedded async 'Client' in async runtime.

This commit is contained in:
Jeb Rosen 2021-02-26 09:47:09 -08:00 committed by Sergio Benitez
parent 68b244ebdc
commit d778c2cb10
3 changed files with 31 additions and 5 deletions

View File

@ -26,7 +26,7 @@ use crate::http::Method;
/// .dispatch(); /// .dispatch();
/// ``` /// ```
pub struct Client { pub struct Client {
pub(crate) inner: asynchronous::Client, pub(crate) inner: Option<asynchronous::Client>,
runtime: RefCell<tokio::runtime::Runtime>, runtime: RefCell<tokio::runtime::Runtime>,
} }
@ -38,7 +38,7 @@ impl Client {
.expect("create tokio runtime"); .expect("create tokio runtime");
// Initialize the Rocket instance // Initialize the Rocket instance
let inner = runtime.block_on(asynchronous::Client::_new(rocket, tracked))?; let inner = Some(runtime.block_on(asynchronous::Client::_new(rocket, tracked))?);
Ok(Self { inner, runtime: RefCell::new(runtime) }) Ok(Self { inner, runtime: RefCell::new(runtime) })
} }
@ -54,6 +54,11 @@ impl Client {
f(&client, request, response) f(&client, request, response)
} }
#[inline(always)]
pub(crate) fn inner(&self) -> &asynchronous::Client {
self.inner.as_ref().expect("internal invariant broken: self.inner is Some")
}
#[inline(always)] #[inline(always)]
pub(crate) fn block_on<F, R>(&self, fut: F) -> R pub(crate) fn block_on<F, R>(&self, fut: F) -> R
where F: std::future::Future<Output=R>, where F: std::future::Future<Output=R>,
@ -63,14 +68,14 @@ impl Client {
#[inline(always)] #[inline(always)]
fn _rocket(&self) -> &Rocket { fn _rocket(&self) -> &Rocket {
self.inner._rocket() self.inner()._rocket()
} }
#[inline(always)] #[inline(always)]
pub(crate) fn _with_raw_cookies<F, T>(&self, f: F) -> T pub(crate) fn _with_raw_cookies<F, T>(&self, f: F) -> T
where F: FnOnce(&crate::http::private::cookie::CookieJar) -> T where F: FnOnce(&crate::http::private::cookie::CookieJar) -> T
{ {
self.inner._with_raw_cookies(f) self.inner()._with_raw_cookies(f)
} }
#[inline(always)] #[inline(always)]
@ -88,6 +93,13 @@ impl Client {
pub_client_impl!("use rocket::local::blocking::Client;"); pub_client_impl!("use rocket::local::blocking::Client;");
} }
impl Drop for Client {
fn drop(&mut self) {
let client = self.inner.take();
self.block_on(async { drop(client) });
}
}
#[cfg(doctest)] #[cfg(doctest)]
mod doctest { mod doctest {
/// ```compile_fail /// ```compile_fail

View File

@ -39,7 +39,7 @@ impl<'c> LocalRequest<'c> {
method: Method, method: Method,
uri: Cow<'c, str> uri: Cow<'c, str>
) -> LocalRequest<'c> { ) -> LocalRequest<'c> {
let inner = asynchronous::LocalRequest::new(&client.inner, method, uri); let inner = asynchronous::LocalRequest::new(client.inner(), method, uri);
Self { inner, client } Self { inner, client }
} }

View File

@ -0,0 +1,14 @@
use rocket::local::blocking::Client;
struct SpawnBlockingOnDrop;
impl Drop for SpawnBlockingOnDrop {
fn drop(&mut self) {
rocket::tokio::task::spawn_blocking(|| ());
}
}
#[test]
fn test_access_runtime_in_state_drop() {
Client::tracked(rocket::ignite().manage(SpawnBlockingOnDrop)).unwrap();
}