-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into dependabot/cargo/miette-7.0.0
- Loading branch information
Showing
17 changed files
with
385 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ jobs: | |
name: Audit | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- uses: actions/checkout@v4 | ||
- uses: rustsec/[email protected] | ||
with: | ||
token: ${{ secrets.GITHUB_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
[package] | ||
name = "tokio-graceful-shutdown" | ||
authors = ["Finomnis <[email protected]>"] | ||
version = "0.14.2" | ||
version = "0.14.3" | ||
edition = "2021" | ||
rust-version = "1.70" | ||
license = "MIT OR Apache-2.0" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
//! This example demonstrates how multiple subsystems could be shut down sequentially. | ||
//! | ||
//! When a shutdown gets triggered (via Ctrl+C), Nested1 will shutdown first, | ||
//! followed by Nested2 and Nested3. Only once the previous subsystem is finished shutting down, | ||
//! the next subsystem will follow. | ||
use miette::Result; | ||
use tokio::time::{sleep, Duration}; | ||
use tokio_graceful_shutdown::{ | ||
FutureExt, SubsystemBuilder, SubsystemFinishedFuture, SubsystemHandle, Toplevel, | ||
}; | ||
|
||
async fn counter(id: &str) { | ||
let mut i = 0; | ||
loop { | ||
tracing::info!("{id}: {i}"); | ||
i += 1; | ||
sleep(Duration::from_millis(50)).await; | ||
} | ||
} | ||
|
||
async fn nested1(subsys: SubsystemHandle) -> Result<()> { | ||
tracing::info!("Nested1 started."); | ||
if counter("Nested1").cancel_on_shutdown(&subsys).await.is_ok() { | ||
tracing::info!("Nested1 counter finished."); | ||
} else { | ||
tracing::info!("Nested1 shutting down ..."); | ||
sleep(Duration::from_millis(200)).await; | ||
} | ||
subsys.on_shutdown_requested().await; | ||
tracing::info!("Nested1 stopped."); | ||
Ok(()) | ||
} | ||
|
||
async fn nested2(subsys: SubsystemHandle, nested1_finished: SubsystemFinishedFuture) -> Result<()> { | ||
// Create a future that triggers once nested1 is finished **and** a shutdown is requested | ||
let shutdown = { | ||
let shutdown_requested = subsys.on_shutdown_requested(); | ||
async move { | ||
tokio::join!(shutdown_requested, nested1_finished); | ||
} | ||
}; | ||
|
||
tracing::info!("Nested2 started."); | ||
tokio::select! { | ||
_ = shutdown => { | ||
tracing::info!("Nested2 shutting down ..."); | ||
sleep(Duration::from_millis(200)).await; | ||
} | ||
_ = counter("Nested2") => { | ||
tracing::info!("Nested2 counter finished."); | ||
} | ||
} | ||
|
||
tracing::info!("Nested2 stopped."); | ||
Ok(()) | ||
} | ||
|
||
async fn nested3(subsys: SubsystemHandle, nested2_finished: SubsystemFinishedFuture) -> Result<()> { | ||
// Create a future that triggers once nested2 is finished **and** a shutdown is requested | ||
let shutdown = { | ||
// This is an alternative to `on_shutdown_requested()` (as shown in nested2). | ||
// Use this if `on_shutdown_requested()` gives you lifetime issues. | ||
let cancellation_token = subsys.create_cancellation_token(); | ||
async move { | ||
tokio::join!(cancellation_token.cancelled(), nested2_finished); | ||
} | ||
}; | ||
|
||
tracing::info!("Nested3 started."); | ||
tokio::select! { | ||
_ = shutdown => { | ||
tracing::info!("Nested3 shutting down ..."); | ||
sleep(Duration::from_millis(200)).await; | ||
} | ||
_ = counter("Nested3") => { | ||
tracing::info!("Nested3 counter finished."); | ||
} | ||
} | ||
|
||
tracing::info!("Nested3 stopped."); | ||
Ok(()) | ||
} | ||
|
||
async fn root(subsys: SubsystemHandle) -> Result<()> { | ||
tracing::info!("Root started."); | ||
|
||
tracing::info!("Starting nested subsystems ..."); | ||
let nested1 = subsys.start(SubsystemBuilder::new("Nested1", nested1)); | ||
let nested1_finished = nested1.finished(); | ||
let nested2 = subsys.start(SubsystemBuilder::new("Nested2", |s| { | ||
nested2(s, nested1_finished) | ||
})); | ||
let nested2_finished = nested2.finished(); | ||
subsys.start(SubsystemBuilder::new("Nested3", |s| { | ||
nested3(s, nested2_finished) | ||
})); | ||
tracing::info!("Nested subsystems started."); | ||
|
||
// Wait for all children to finish shutting down. | ||
subsys.wait_for_children().await; | ||
|
||
tracing::info!("All children finished, stopping Root ..."); | ||
sleep(Duration::from_millis(200)).await; | ||
tracing::info!("Root stopped."); | ||
|
||
Ok(()) | ||
} | ||
|
||
#[tokio::main(flavor = "current_thread")] | ||
async fn main() -> Result<()> { | ||
// Init logging | ||
tracing_subscriber::fmt() | ||
.with_max_level(tracing::Level::TRACE) | ||
.init(); | ||
|
||
// Setup and execute subsystem tree | ||
Toplevel::new(|s| async move { | ||
s.start(SubsystemBuilder::new("Root", root)); | ||
}) | ||
.catch_signals() | ||
.handle_shutdown_requests(Duration::from_millis(1000)) | ||
.await | ||
.map_err(Into::into) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
//! This example demonstrates how a parent subsystem could orchestrate | ||
//! the shutdown order of its children manually. | ||
//! | ||
//! This is done by spawning the children in 'detached' mode to prevent | ||
//! that the shutdown signal gets passed to the children. | ||
//! Then, the parent calls `initialize_shutdown` on each child manually. | ||
use miette::Result; | ||
use tokio::time::{sleep, Duration}; | ||
use tokio_graceful_shutdown::{FutureExt, SubsystemBuilder, SubsystemHandle, Toplevel}; | ||
|
||
async fn counter(id: &str) { | ||
let mut i = 0; | ||
loop { | ||
tracing::info!("{id}: {i}"); | ||
i += 1; | ||
sleep(Duration::from_millis(50)).await; | ||
} | ||
} | ||
|
||
async fn child(name: &str, subsys: SubsystemHandle) -> Result<()> { | ||
tracing::info!("{name} started."); | ||
if counter(name).cancel_on_shutdown(&subsys).await.is_ok() { | ||
tracing::info!("{name} counter finished."); | ||
} else { | ||
tracing::info!("{name} shutting down ..."); | ||
sleep(Duration::from_millis(200)).await; | ||
} | ||
subsys.on_shutdown_requested().await; | ||
tracing::info!("{name} stopped."); | ||
Ok(()) | ||
} | ||
|
||
async fn parent(subsys: SubsystemHandle) -> Result<()> { | ||
tracing::info!("Parent started."); | ||
|
||
tracing::info!("Starting detached nested subsystems ..."); | ||
let nested1 = | ||
subsys.start(SubsystemBuilder::new("Nested1", |s| child("Nested1", s)).detached()); | ||
let nested2 = | ||
subsys.start(SubsystemBuilder::new("Nested2", |s| child("Nested2", s)).detached()); | ||
let nested3 = | ||
subsys.start(SubsystemBuilder::new("Nested3", |s| child("Nested3", s)).detached()); | ||
tracing::info!("Nested subsystems started."); | ||
|
||
// Wait for the shutdown to happen | ||
subsys.on_shutdown_requested().await; | ||
|
||
// Shut down children sequentially. As they are detached, they will not shutdown on their own, | ||
// but need to be shut down manually via `initiate_shutdown`. | ||
tracing::info!("Initiating Nested1 shutdown ..."); | ||
nested1.initiate_shutdown(); | ||
nested1.join().await?; | ||
tracing::info!("Initiating Nested2 shutdown ..."); | ||
nested2.initiate_shutdown(); | ||
nested2.join().await?; | ||
tracing::info!("Initiating Nested3 shutdown ..."); | ||
nested3.initiate_shutdown(); | ||
nested3.join().await?; | ||
|
||
tracing::info!("All children finished, stopping Root ..."); | ||
sleep(Duration::from_millis(200)).await; | ||
tracing::info!("Root stopped."); | ||
|
||
Ok(()) | ||
} | ||
|
||
#[tokio::main(flavor = "current_thread")] | ||
async fn main() -> Result<()> { | ||
// Init logging | ||
tracing_subscriber::fmt() | ||
.with_max_level(tracing::Level::TRACE) | ||
.init(); | ||
|
||
// Setup and execute subsystem tree | ||
Toplevel::new(|s| async move { | ||
s.start(SubsystemBuilder::new("parent", parent)); | ||
}) | ||
.catch_signals() | ||
.handle_shutdown_requests(Duration::from_millis(1000)) | ||
.await | ||
.map_err(Into::into) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.