feat(Core): gracefully shutdown router/scheduler if Redis is unavailable (#891)

Co-authored-by: prajjwal kumar <prajjwal.kumar@prajjwalkumar-DWKH9NPY4R.local>
Co-authored-by: Nishant Joshi <nishant.joshi@juspay.in>
Co-authored-by: Arun Raj M <jarnura47@gmail.com>
This commit is contained in:
Prajjwal Kumar
2023-04-24 13:08:00 +05:30
committed by GitHub
parent 85c7629061
commit 13185999d5
21 changed files with 166 additions and 74 deletions

View File

@ -25,11 +25,12 @@ pub mod utils;
use actix_web::{
body::MessageBody,
dev::{Server, ServiceFactory, ServiceRequest},
dev::{Server, ServerHandle, ServiceFactory, ServiceRequest},
middleware::ErrorHandlers,
};
use http::StatusCode;
use routes::AppState;
use tokio::sync::{mpsc, oneshot};
pub use self::env::logger;
use crate::{
@ -140,7 +141,8 @@ pub fn mk_app(
pub async fn start_server(conf: settings::Settings) -> ApplicationResult<(Server, AppState)> {
logger::debug!(startup_config=?conf);
let server = conf.server.clone();
let state = routes::AppState::new(conf).await;
let (tx, rx) = oneshot::channel();
let state = routes::AppState::new(conf, tx).await;
// Cloning to close connections before shutdown
let app_state = state.clone();
let request_body_limit = server.request_body_limit;
@ -149,10 +151,40 @@ pub async fn start_server(conf: settings::Settings) -> ApplicationResult<(Server
.workers(server.workers)
.shutdown_timeout(server.shutdown_timeout)
.run();
tokio::spawn(receiver_for_error(rx, server.handle()));
Ok((server, app_state))
}
pub async fn receiver_for_error(rx: oneshot::Receiver<()>, mut server: impl Stop) {
match rx.await {
Ok(_) => {
logger::error!("The redis server failed ");
server.stop_server().await;
}
Err(err) => {
logger::error!("Channel receiver error{err}");
}
}
}
#[async_trait::async_trait]
pub trait Stop {
async fn stop_server(&mut self);
}
#[async_trait::async_trait]
impl Stop for ServerHandle {
async fn stop_server(&mut self) {
let _ = self.stop(true).await;
}
}
#[async_trait::async_trait]
impl Stop for mpsc::Sender<()> {
async fn stop_server(&mut self) {
let _ = self.send(()).await.map_err(|err| logger::error!("{err}"));
}
}
pub fn get_application_builder(
request_body_limit: usize,
) -> actix_web::App<