use std::sync::Arc;
use tokio::{sync::mpsc, task::JoinSet};
use crate::RuntimeError;
use crate::core::TaskOutcome;
use crate::events::{Event, EventKind, RejectionKind};
use super::{Controller, ControllerCommand};
impl Controller {
pub(super) fn finalize_pending_on_shutdown(&self, rx: &mut mpsc::Receiver<ControllerCommand>) {
rx.close();
while let Ok(command) = rx.try_recv() {
match command {
ControllerCommand::Submit(sub) => {
let mut event = Event::new(EventKind::ControllerRejected)
.with_id(sub.id)
.with_rejection_kind(RejectionKind::ControllerShuttingDown)
.with_reason(crate::reasons::CONTROLLER_SHUTTING_DOWN);
if let Some(slot_name) = sub.spec.slot_override() {
event = event.with_task(slot_name.to_owned());
}
self.bus.publish(event);
if let Some(done) = sub.done {
let _ = done.send(TaskOutcome::Rejected {
kind: RejectionKind::ControllerShuttingDown,
reason: Arc::from(crate::reasons::CONTROLLER_SHUTTING_DOWN),
});
}
}
ControllerCommand::ManageIdentity { reply, .. } => {
let _ = reply.send(Err(RuntimeError::ShuttingDown));
}
}
}
}
pub(super) async fn finalize_slot_state_on_shutdown(&self) {
let slot_names: Vec<Arc<str>> = self
.slots
.iter()
.map(|entry| Arc::clone(entry.key()))
.collect();
for slot_name in slot_names {
let Some(slot) = self.slots.get(&*slot_name).map(|entry| entry.clone()) else {
continue;
};
let mut slot = slot.lock().await;
while let Some((id, _spec)) = slot.queue.pop_front() {
self.bus.publish(
Event::new(EventKind::ControllerRejected)
.with_task(Arc::clone(&slot_name))
.with_id(id)
.with_rejection_kind(RejectionKind::ControllerShuttingDown)
.with_reason(crate::reasons::CONTROLLER_SHUTTING_DOWN),
);
self.finalize_rejected(
id,
RejectionKind::ControllerShuttingDown,
crate::reasons::CONTROLLER_SHUTTING_DOWN,
);
}
}
self.finalize_remaining_watchers();
self.slots.clear();
}
pub(super) async fn drain_workers<T: 'static>(workers: &mut JoinSet<T>) {
while workers.join_next().await.is_some() {}
}
}