tokiotasksshutdown

Easily manage and gracefully shutdown tokio tasks while monitoring their return results

Crates.io License

Example

```rust use {std::time::Duration, tokio::time::sleep, tokiotasksshutdown::*};

// By default this will catch Ctrl+C. // You may have your tasks return your own error type. let tasks: TasksMainHandle = TasksBuilder::default() .timeouts(Some(Duration::fromsecs(2)), Some(Duration::frommillis(500))) .build();

// Spawn tasks tasks .spawn("gracefullyshuttingdowntask", |taskshandle| async move { loop { match taskshandle .onshutdownor({ // Simulating another future running concurrently, // e.g. listening on a channel... sleep(Duration::frommillis(100)) }) .await { ShouldShutdownOr::ShouldShutdown => { // We have been kindly asked to shutdown, let's exit break; } ShouldShutdownOr::ShouldNotShutdown(res) => { // Got result of channel listening } } } Ok(()) // Note that if a task were to error, graceful shutdown would be initiated. // This behavior can be disabled. }) .unwrap(); // Note that calls can be chained since spawn returns &TasksHandle

// Let's simulate a Ctrl+C after some time let taskshandle: TasksHandle<_> = tasks.handle(); tokio::task::spawn(async move { sleep(Duration::frommillis(150)).await; taskshandle.startshutdown(); });

// Let's make sure there were no errors tasks.join_all().await.unwrap();

// Make sure we have shut down when expected assert!( testduration > Duration::frommillis(145) && testduration < Duration::frommillis(155) ); ```

In this example, the task will have run one loop already (sleep has hit at t=100ms) when asked for graceful shutdown at t=150ms, which will immediately make it gracefully shut down.

Similar crates

This crate is inspired from tokio-graceful-shutdown. I ran into issues using it where it would sometimes freeze when tasks were supposed to timeout and that was very hard to investigate because there is a lot of code, so I figured the easiest way to fix it would be to just rewrite a simpler version of it from scratch.

Compared to tokio-graceful-shutdown, it has 3x less code, no subsystem concept (any shutdown is global on a TasksMainHandle), more flexible control, and a (hopefully) more reliable shutdown mechanism (notably it can survive tasks accidentally blocking - although I don't think that was my original issue).