Skip to content

Commit 48899b5

Browse files
committed
feat(operator): Add graceful shutdown to EoS checker
1 parent 99ceb14 commit 48899b5

1 file changed

Lines changed: 38 additions & 18 deletions

File tree

  • crates/stackable-operator/src/eos

crates/stackable-operator/src/eos/mod.rs

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use chrono::{DateTime, Utc};
2+
use futures::FutureExt;
23
use snafu::{ResultExt, Snafu};
34
use stackable_shared::time::Duration;
5+
use tokio::select;
46
use tracing::{Level, instrument};
57

68
/// Available options to configure a [`EndOfSupportChecker`].
@@ -114,33 +116,51 @@ impl EndOfSupportChecker {
114116
///
115117
/// It is recommended to run the end-of-support checker via [`futures::try_join!`] or
116118
/// [`tokio::join`] alongside other futures (eg. for controllers).
117-
pub async fn run(self) {
119+
pub async fn run<F>(self, shutdown_signal: F)
120+
where
121+
F: Future<Output = ()>,
122+
{
118123
// Immediately return if the end-of-support checker is disabled.
119124
if self.disabled {
120125
return;
121126
}
122127

123-
// Construct an interval which can be polled.
124128
let mut interval = tokio::time::interval(self.interval.into());
125129

130+
let shutdown_signal = shutdown_signal.fuse();
131+
tokio::pin!(shutdown_signal);
132+
126133
loop {
127-
// TODO: Add way to stop from the outside
128-
// The first tick ticks immediately.
129-
interval.tick().await;
130-
let now = Utc::now();
131-
132-
tracing::info_span!(
133-
"checking end-of-support state",
134-
eos.interval = self.interval.to_string(),
135-
eos.now = now.to_rfc3339(),
136-
);
137-
138-
// Continue the loop and wait for the next tick to run the check again.
139-
if now <= self.eos_datetime {
140-
continue;
134+
select! {
135+
// We used a biased polling strategy to always check if a
136+
// shutdown signal was received before polling the EoS check
137+
// interval.
138+
biased;
139+
140+
_ = &mut shutdown_signal => {
141+
tracing::trace!("received shutdown signal");
142+
break;
143+
}
144+
145+
// The first tick ticks immediately.
146+
_ = interval.tick() => {
147+
let now = Utc::now();
148+
149+
tracing::info_span!(
150+
"checking end-of-support state",
151+
eos.interval = self.interval.to_string(),
152+
eos.now = now.to_rfc3339(),
153+
);
154+
155+
// Continue the loop and wait for the next tick to run the
156+
// check again.
157+
if now <= self.eos_datetime {
158+
continue;
159+
}
160+
161+
self.emit_warning(now);
162+
}
141163
}
142-
143-
self.emit_warning(now);
144164
}
145165
}
146166

0 commit comments

Comments
 (0)