use std::sync::atomic::Ordering;
use tokio::sync::mpsc;
use super::super::SupervisorCore;
use crate::{core::registry::RegistryCommand, error::RuntimeError};
impl SupervisorCore {
pub(in crate::core::runtime) fn mark_shutting_down(&self) {
let _gate = self
.admission_gate
.lock()
.unwrap_or_else(|error| error.into_inner());
self.shutting_down.store(true, Ordering::Release);
}
#[cfg(all(test, feature = "controller"))]
pub(crate) fn close_registry_admission_for_test(&self) {
self.mark_shutting_down();
}
pub(super) fn command_admission(&self) -> Option<std::sync::MutexGuard<'_, ()>> {
let gate = self
.admission_gate
.lock()
.unwrap_or_else(|error| error.into_inner());
if self.is_shutting_down() {
None
} else {
Some(gate)
}
}
pub(super) fn try_reserve_command_admission(
&self,
) -> Result<
(
mpsc::Permit<'_, RegistryCommand>,
std::sync::MutexGuard<'_, ()>,
),
RuntimeError,
> {
if self.is_shutting_down() {
return Err(RuntimeError::ShuttingDown);
}
let permit = self.cmd_tx.try_reserve().map_err(|error| match error {
mpsc::error::TrySendError::Full(()) => RuntimeError::CommandQueueFull,
mpsc::error::TrySendError::Closed(()) => RuntimeError::ShuttingDown,
})?;
let Some(admission) = self.command_admission() else {
drop(permit);
return Err(RuntimeError::ShuttingDown);
};
Ok((permit, admission))
}
pub(in crate::core::runtime) async fn close_admission_and_fence_registry(
&self,
) -> Result<(), RuntimeError> {
self.mark_shutting_down();
self.registry.fence().await
}
}