use std::sync::Arc;
use parking_lot::Mutex;
use qsu::rt::{InitCtx, RunEnv, ServiceHandler, TermCtx};
#[cfg(feature = "tokio")]
use qsu::rt::TokioServiceHandler;
#[cfg(feature = "rocket")]
use qsu::{
rocket::{Build, Ignite, Rocket},
rt::RocketServiceHandler
};
use crate::err::Error;
#[derive(Default)]
pub struct FailMode {
init: bool,
run: bool,
shutdown: bool
}
#[allow(unused)]
impl FailMode {
pub const fn init(&mut self) -> &mut Self {
self.init = true;
self
}
pub const fn run(&mut self) -> &mut Self {
self.run = true;
self
}
pub const fn shutdown(&mut self) -> &mut Self {
self.shutdown = true;
self
}
}
#[derive(Default)]
pub struct Visited {
pub init: bool,
pub run: bool,
pub shutdown: bool
}
#[derive(Default)]
pub struct MySyncService {
pub fail: FailMode,
pub visited: Arc<Mutex<Visited>>
}
#[allow(unused)]
impl MySyncService {
pub const fn fail_init(mut self) -> Self {
self.fail.init();
self
}
pub const fn fail_run(mut self) -> Self {
self.fail.run();
self
}
pub const fn fail_shutdown(mut self) -> Self {
self.fail.shutdown();
self
}
}
impl ServiceHandler for MySyncService {
type AppErr = Error;
fn init(&mut self, _ictx: &mut InitCtx) -> Result<(), Self::AppErr> {
self.visited.lock().init = true;
if self.fail.init {
Err(Error::hello("From Sync::init()"))?;
}
Ok(())
}
fn run(&mut self, _re: &RunEnv) -> Result<(), Self::AppErr> {
self.visited.lock().run = true;
if self.fail.run {
Err(Error::hello("From Sync::run()"))?;
}
Ok(())
}
fn shutdown(&mut self, _tctx: &mut TermCtx) -> Result<(), Self::AppErr> {
self.visited.lock().shutdown = true;
if self.fail.shutdown {
Err(Error::hello("From Sync::shutdown()"))?;
}
Ok(())
}
}
#[cfg(feature = "tokio")]
#[derive(Default)]
pub struct MyTokioService {
pub fail: FailMode,
pub visited: Arc<Mutex<Visited>>
}
#[cfg(feature = "tokio")]
#[allow(unused)]
impl MyTokioService {
pub const fn fail_init(mut self) -> Self {
self.fail.init();
self
}
pub const fn fail_run(mut self) -> Self {
self.fail.run();
self
}
pub const fn fail_shutdown(mut self) -> Self {
self.fail.shutdown();
self
}
}
#[cfg(feature = "tokio")]
#[qsu::async_trait]
impl TokioServiceHandler for MyTokioService {
type AppErr = Error;
async fn init(&mut self, _ictx: &mut InitCtx) -> Result<(), Self::AppErr> {
self.visited.lock().init = true;
if self.fail.init {
Err(Error::hello("From Tokio::init()"))?;
}
Ok(())
}
async fn run(&mut self, _re: &RunEnv) -> Result<(), Self::AppErr> {
self.visited.lock().run = true;
if self.fail.run {
Err(Error::hello("From Tokio::run()"))?;
}
Ok(())
}
async fn shutdown(
&mut self,
_tctx: &mut TermCtx
) -> Result<(), Self::AppErr> {
self.visited.lock().shutdown = true;
if self.fail.shutdown {
Err(Error::hello("From Tokio::shutdown()"))?;
}
Ok(())
}
}
#[cfg(feature = "rocket")]
#[derive(Default)]
pub struct MyRocketService {
pub fail: FailMode,
pub visited: Arc<Mutex<Visited>>
}
#[cfg(feature = "rocket")]
#[allow(unused)]
impl MyRocketService {
pub const fn fail_init(mut self) -> Self {
self.fail.init();
self
}
pub const fn fail_run(mut self) -> Self {
self.fail.run();
self
}
pub const fn fail_shutdown(mut self) -> Self {
self.fail.shutdown();
self
}
}
#[cfg(feature = "rocket")]
#[qsu::async_trait]
impl RocketServiceHandler for MyRocketService {
type AppErr = Error;
async fn init(
&mut self,
_ictx: &mut InitCtx
) -> Result<Vec<Rocket<Build>>, Self::AppErr> {
self.visited.lock().init = true;
if self.fail.init {
Err(Error::hello("From Rocket::init()"))?;
}
Ok(Vec::new())
}
async fn run(
&mut self,
_rockets: Vec<Rocket<Ignite>>,
_re: &RunEnv
) -> Result<(), Self::AppErr> {
self.visited.lock().run = true;
if self.fail.run {
Err(Error::hello("From Rocket::run()"))?;
}
Ok(())
}
async fn shutdown(
&mut self,
_tctx: &mut TermCtx
) -> Result<(), Self::AppErr> {
self.visited.lock().shutdown = true;
if self.fail.shutdown {
Err(Error::hello("From Rocket::shutdown()"))?;
}
Ok(())
}
}