feat: shut down the kubernetes api watcher if it recieved SIGTERM
All checks were successful
/ build (push) Successful in 2m47s

This commit is contained in:
Tamipes 2026-06-22 14:34:29 +02:00
parent ae5b124c16
commit eac1c5d8fa
2 changed files with 26 additions and 12 deletions

View file

@ -40,13 +40,16 @@ impl KubeCache {
/// and if it is not possible returns a None. /// and if it is not possible returns a None.
/// ///
/// It also returns a JoinHandle which is tied to the api watcher /// It also returns a JoinHandle which is tied to the api watcher
/// and if it returns that means that the kubecache is not responsive now. /// and if that handle is joinable that means that `kubecache` is
/// not responsive after that point. (the server should be restarted)
/// ///
/// # Example: /// # Example:
/// ```no_run /// ```no_run
/// let (kube_cache, api_task) = kube_cache::KubeCache::create().await.unwrap(); /// let (kube_cache, api_task) = kube_cache::KubeCache::create().await.unwrap();
/// ``` /// ```
pub async fn create() -> Option<(KubeCache, JoinHandle<()>)> { pub async fn create(
token: tokio_util::sync::CancellationToken,
) -> Option<(KubeCache, JoinHandle<()>)> {
let in_cluster = match std::env::var("KUBERNETES_SERVICE_HOST") { let in_cluster = match std::env::var("KUBERNETES_SERVICE_HOST") {
Ok(_) => true, Ok(_) => true,
Err(_) => false, Err(_) => false,
@ -64,10 +67,16 @@ impl KubeCache {
let infinite_watch = dep_watcher_rf let infinite_watch = dep_watcher_rf
.applied_objects() .applied_objects()
.for_each(|_o| std::future::ready(())); .for_each(|_o| std::future::ready(()));
let _res = infinite_watch.await; tokio::select! {
tracing::error!( _ = infinite_watch => {
"deployments watcher ended; this should not happen; (program should exit now)" tracing::error!(
); "deployments watcher ended; this should not happen; (program should exit now)"
);
}
_ = token.cancelled() => {
tracing::info!("shut down kubernetes api watcher");
}
}
}); });
let srv_api: Api<Service> = Api::default_namespaced(client); let srv_api: Api<Service> = Api::default_namespaced(client);
@ -208,8 +217,10 @@ impl MinecraftAPI<Server> for McApi {
} }
impl McApi { impl McApi {
pub async fn create() -> Option<(Self, JoinHandle<()>)> { pub async fn create(
let (kube_cache, kube_task) = KubeCache::create().await?; token: tokio_util::sync::CancellationToken,
) -> Option<(Self, JoinHandle<()>)> {
let (kube_cache, kube_task) = KubeCache::create(token).await?;
Some(( Some((
Self { Self {
cache: kube_cache, cache: kube_cache,

View file

@ -27,7 +27,11 @@ async fn main() {
let revision: &'static str = env!("COMMIT_HASH"); let revision: &'static str = env!("COMMIT_HASH");
tracing::info!(revision); tracing::info!(revision);
let (api, api_task) = kube_cache::McApi::create().await.unwrap(); let cancel_token = tokio_util::sync::CancellationToken::new();
let (api, api_task) = kube_cache::McApi::create(cancel_token.clone())
.await
.unwrap();
tracing::info!("initialized kube api"); tracing::info!("initialized kube api");
let config: Config = Default::default(); let config: Config = Default::default();
@ -43,7 +47,6 @@ async fn main() {
return; return;
} }
}; };
let cancel_token = tokio_util::sync::CancellationToken::new();
let mut conn_task = proxy::start_proxy(listener, api, config, cancel_token.clone()); let mut conn_task = proxy::start_proxy(listener, api, config, cancel_token.clone());
@ -54,8 +57,8 @@ async fn main() {
_ = &mut conn_task => { _ = &mut conn_task => {
tracing::error!("the connection handling tokio:spawn'ed task ran to completion, which should not happen!"); tracing::error!("the connection handling tokio:spawn'ed task ran to completion, which should not happen!");
} }
result = sigterm.recv() => { _ = sigterm.recv() => {
tracing::info!(sigterm_signal = ?result,"SIGTERM received"); tracing::info!("SIGTERM received");
cancel_token.cancel(); cancel_token.cancel();
let res = conn_task.await; let res = conn_task.await;
tracing::info!(api_task_result = ?res, "shutdown complete"); tracing::info!(api_task_result = ?res, "shutdown complete");