Search code examples
asynchronousrustasync-awaitrust-tokio

Is there some way how to shutdown tokio::runtime::Runtime?


Problem is in a microservice with Tokio, where connect to db and other stuff async, but when some connection failed, microservice dont end work. Its a great when you need this case, but I need to end work of this microservice when connection lost... so could you help me how to safety shutdown process...?

src/main.rs

use tokio; // 1.0.0+

fn main() {
    let rt = tokio::runtime::Builder::new_multi_thread()
        .worker_threads(workers_number)
        .enable_all()
        .build()
        .unwrap();
    rt.block_on(async {
    // health cheacker connection
    let health_checker = match HealthChecker::new(some_configuration).await?;
    // some connection to db
    // ...
    // transport client connection
    // ...

    // so when connection failed or lost I need to 
    // end process like `std::process::abort()`
    // but I cant use it, because its unsafe

    let mut task_handler = vec![];

    // create some task

    join_all(task_handler).await;
  });
}

anyone have some ideas?


Solution

  • You can call any of the Runtime shutdown methods shutdown_timeout or shutdown_background.

    If it is needed some king of waiting, you could spawn a task with a tokio::sync::oneshot that will trigger the shutdown when signaled.

    use core::time::Duration;
    use crate::tokio::time::sleep;
    use tokio;
    
    fn main() {
        let rt = tokio::runtime::Builder::new_multi_thread()
            .enable_all()
            .build()
            .unwrap();
            
        let handle = rt.handle().clone();
        
        let (s, r) = tokio::sync::oneshot::channel();
        
        rt.spawn(async move {
            sleep(Duration::from_secs(1)).await;
            s.send(0);
        });
        
        handle.block_on(async move {
            r.await;
            rt.shutdown_background();
        });
    }
    

    Playground