Split 'AdHoc::on_launch' into two by fallibility.

The new 'AdHoc::try_on_launch()' replaces the previous 'on_launch'. The
new 'on_launch' returns a 'Rocket' directly.
This commit is contained in:
Sergio Benitez 2021-04-07 23:00:11 -07:00
parent 1c70df052c
commit 5931d6704b
5 changed files with 45 additions and 22 deletions

View File

@ -69,7 +69,7 @@ macro_rules! dberr {
impl<K: 'static, C: Poolable> ConnectionPool<K, C> { impl<K: 'static, C: Poolable> ConnectionPool<K, C> {
pub fn fairing(fairing_name: &'static str, db: &'static str) -> impl Fairing { pub fn fairing(fairing_name: &'static str, db: &'static str) -> impl Fairing {
AdHoc::on_launch(fairing_name, move |rocket| async move { AdHoc::try_on_launch(fairing_name, move |rocket| async move {
let config = match Config::from(db, &rocket) { let config = match Config::from(db, &rocket) {
Ok(config) => config, Ok(config) => config,
Err(e) => dberr!("config", db, "{}", e, rocket), Err(e) => dberr!("config", db, "{}", e, rocket),

View File

@ -1,6 +1,6 @@
use std::sync::Mutex; use std::sync::Mutex;
use futures::future::{Future, BoxFuture}; use futures::future::{Future, BoxFuture, FutureExt};
use crate::{Rocket, Request, Response, Data}; use crate::{Rocket, Request, Response, Data};
use crate::fairing::{Fairing, Kind, Info}; use crate::fairing::{Fairing, Kind, Info};
@ -72,8 +72,10 @@ enum AdHocKind {
impl AdHoc { impl AdHoc {
/// Constructs an `AdHoc` launch fairing named `name`. The function `f` will /// Constructs an `AdHoc` launch fairing named `name`. The function `f` will
/// be called by Rocket just prior to launch. Returning an `Err` aborts /// be called by Rocket just prior to launch.
/// launch. ///
/// This version of an `AdHoc` launch fairing cannot abort launch. For a
/// fallible version that can, see [`AdHoc::try_on_launch()`].
/// ///
/// # Example /// # Example
/// ///
@ -82,14 +84,35 @@ impl AdHoc {
/// ///
/// // The no-op launch fairing. /// // The no-op launch fairing.
/// let fairing = AdHoc::on_launch("Boom!", |rocket| async move { /// let fairing = AdHoc::on_launch("Boom!", |rocket| async move {
/// Ok(rocket) /// rocket
/// }); /// });
/// ``` /// ```
pub fn on_launch<F, Fut>(name: &'static str, f: F) -> AdHoc pub fn on_launch<F, Fut>(name: &'static str, f: F) -> AdHoc
where F: FnOnce(Rocket) -> Fut + Send + 'static, where F: FnOnce(Rocket) -> Fut + Send + 'static,
Fut: Future<Output=Result<Rocket, Rocket>> + Send + 'static, Fut: Future<Output = Rocket> + Send + 'static,
{ {
AdHoc { name, kind: AdHocKind::Launch(Once::new(Box::new(|r| Box::pin(f(r))))) } AdHoc::try_on_launch(name, |rocket| f(rocket).map(Ok))
}
/// Constructs an `AdHoc` launch fairing named `name`. The function `f` will
/// be called by Rocket just prior to launch. Returning an `Err` aborts
/// launch.
///
/// For an infallible version, see [`AdHoc::on_launch()`].
///
/// # Example
///
/// ```rust
/// use rocket::fairing::AdHoc;
///
/// // The no-op try launch fairing.
/// let fairing = AdHoc::try_on_launch("No-Op", |rocket| async { Ok(rocket) });
/// ```
pub fn try_on_launch<F, Fut>(name: &'static str, f: F) -> AdHoc
where F: FnOnce(Rocket) -> Fut + Send + 'static,
Fut: Future<Output = Result<Rocket, Rocket>> + Send + 'static,
{
AdHoc { name, kind: AdHocKind::Launch(Once::new(Box::new(|r| f(r).boxed()))) }
} }
/// Constructs an `AdHoc` launch fairing named `name`. The function `f` will /// Constructs an `AdHoc` launch fairing named `name`. The function `f` will
@ -182,7 +205,7 @@ impl AdHoc {
pub fn config<'de, T>() -> AdHoc pub fn config<'de, T>() -> AdHoc
where T: serde::Deserialize<'de> + Send + Sync + 'static where T: serde::Deserialize<'de> + Send + Sync + 'static
{ {
AdHoc::on_launch(std::any::type_name::<T>(), |rocket| async { AdHoc::try_on_launch(std::any::type_name::<T>(), |rocket| async {
let app_config = match rocket.figment().extract::<T>() { let app_config = match rocket.figment().extract::<T>() {
Ok(config) => config, Ok(config) => config,
Err(e) => { Err(e) => {

View File

@ -3,9 +3,9 @@ use rocket::fairing::AdHoc;
#[rocket::async_test] #[rocket::async_test]
async fn test_inspectable_launch_state() -> Result<(), Error> { async fn test_inspectable_launch_state() -> Result<(), Error> {
let rocket = rocket::ignite() let rocket = rocket::custom(rocket::Config::debug_default())
.attach(AdHoc::on_launch("Add State", |rocket| async { .attach(AdHoc::on_launch("Add State", |rocket| async {
Ok(rocket.manage("Hi!")) rocket.manage("Hi!")
})) }))
._ignite() ._ignite()
.await?; .await?;
@ -17,14 +17,14 @@ async fn test_inspectable_launch_state() -> Result<(), Error> {
#[rocket::async_test] #[rocket::async_test]
async fn test_inspectable_launch_state_in_liftoff() -> Result<(), Error> { async fn test_inspectable_launch_state_in_liftoff() -> Result<(), Error> {
let rocket = rocket::ignite() let rocket = rocket::custom(rocket::Config::debug_default())
.attach(AdHoc::on_launch("Add State", |rocket| async { .attach(AdHoc::on_launch("Add State", |rocket| async {
Ok(rocket.manage("Hi!")) rocket.manage("Hi!")
})) }))
.attach(AdHoc::on_launch("Inspect State", |rocket| async { .attach(AdHoc::on_launch("Inspect State", |rocket| async {
let state = rocket.state::<&'static str>(); let state = rocket.state::<&'static str>();
assert_eq!(state, Some(&"Hi!")); assert_eq!(state, Some(&"Hi!"));
Ok(rocket) rocket
})) }))
.attach(AdHoc::on_liftoff("Inspect State", |rocket| Box::pin(async move { .attach(AdHoc::on_liftoff("Inspect State", |rocket| Box::pin(async move {
let state = rocket.state::<&'static str>(); let state = rocket.state::<&'static str>();
@ -40,19 +40,19 @@ async fn test_inspectable_launch_state_in_liftoff() -> Result<(), Error> {
#[rocket::async_test] #[rocket::async_test]
async fn test_launch_state_is_well_ordered() -> Result<(), Error> { async fn test_launch_state_is_well_ordered() -> Result<(), Error> {
let rocket = rocket::ignite() let rocket = rocket::custom(rocket::Config::debug_default())
.attach(AdHoc::on_launch("Inspect State Pre", |rocket| async { .attach(AdHoc::on_launch("Inspect State Pre", |rocket| async {
let state = rocket.state::<&'static str>(); let state = rocket.state::<&'static str>();
assert_eq!(state, None); assert_eq!(state, None);
Ok(rocket) rocket
})) }))
.attach(AdHoc::on_launch("Add State", |rocket| async { .attach(AdHoc::on_launch("Add State", |rocket| async {
Ok(rocket.manage("Hi!")) rocket.manage("Hi!")
})) }))
.attach(AdHoc::on_launch("Inspect State", |rocket| async { .attach(AdHoc::on_launch("Inspect State", |rocket| async {
let state = rocket.state::<&'static str>(); let state = rocket.state::<&'static str>();
assert_eq!(state, Some(&"Hi!")); assert_eq!(state, Some(&"Hi!"));
Ok(rocket) rocket
})) }))
._ignite() ._ignite()
.await?; .await?;
@ -65,14 +65,14 @@ async fn test_launch_state_is_well_ordered() -> Result<(), Error> {
#[should_panic] #[should_panic]
#[rocket::async_test] #[rocket::async_test]
async fn negative_test_launch_state() { async fn negative_test_launch_state() {
let _ = rocket::ignite() let _ = rocket::custom(rocket::Config::debug_default())
.attach(AdHoc::on_launch("Add State", |rocket| async { .attach(AdHoc::on_launch("Add State", |rocket| async {
Ok(rocket.manage("Hi!")) rocket.manage("Hi!")
})) }))
.attach(AdHoc::on_launch("Inspect State", |rocket| async { .attach(AdHoc::on_launch("Inspect State", |rocket| async {
let state = rocket.state::<&'static str>(); let state = rocket.state::<&'static str>();
assert_ne!(state, Some(&"Hi!")); assert_ne!(state, Some(&"Hi!"));
Ok(rocket) rocket
})) }))
._ignite() ._ignite()
.await; .await;

View File

@ -36,7 +36,7 @@ fn rocket() -> rocket::Rocket {
}) })
})); }));
Ok(rocket) rocket
})) }))
} }

View File

@ -10,6 +10,6 @@ async fn test_await_timer_inside_attach() {
rocket::ignite() rocket::ignite()
.attach(rocket::fairing::AdHoc::on_launch("1", |rocket| async { .attach(rocket::fairing::AdHoc::on_launch("1", |rocket| async {
do_async_setup().await; do_async_setup().await;
Ok(rocket) rocket
})); }));
} }