2025-04-09 23:15:07 +02:00
|
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
|
use tokio::sync::Notify;
|
2024-11-20 08:15:31 -07:00
|
|
|
|
2025-10-26 16:20:51 +10:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
2024-11-20 08:15:31 -07:00
|
|
|
pub enum ControllerState {
|
|
|
|
|
Cancelled,
|
2025-09-01 01:28:26 -04:00
|
|
|
Failed,
|
2024-11-20 08:15:31 -07:00
|
|
|
Paused,
|
|
|
|
|
Running,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
struct ControllerInner {
|
|
|
|
|
state: Mutex<ControllerState>,
|
|
|
|
|
progress: Mutex<f32>,
|
2025-04-09 23:15:07 +02:00
|
|
|
notify: Notify,
|
2024-11-20 08:15:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct Controller {
|
|
|
|
|
primary: bool,
|
|
|
|
|
inner: Arc<ControllerInner>,
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-19 01:05:02 -05:00
|
|
|
impl Default for Controller {
|
|
|
|
|
fn default() -> Self {
|
2024-11-20 08:15:31 -07:00
|
|
|
Self {
|
|
|
|
|
primary: true,
|
|
|
|
|
inner: Arc::new(ControllerInner {
|
|
|
|
|
state: Mutex::new(ControllerState::Running),
|
|
|
|
|
progress: Mutex::new(0.0),
|
2025-04-09 23:15:07 +02:00
|
|
|
notify: Notify::new(),
|
2024-11-20 08:15:31 -07:00
|
|
|
}),
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-01-19 01:05:02 -05:00
|
|
|
}
|
2024-11-20 08:15:31 -07:00
|
|
|
|
2025-01-19 01:05:02 -05:00
|
|
|
impl Controller {
|
2025-09-01 01:28:26 -04:00
|
|
|
pub async fn check(&self) -> Result<(), ControllerState> {
|
2024-11-20 08:15:31 -07:00
|
|
|
loop {
|
2025-04-09 23:15:07 +02:00
|
|
|
match self.state() {
|
2025-09-01 01:28:26 -04:00
|
|
|
ControllerState::Cancelled => return Err(ControllerState::Cancelled),
|
|
|
|
|
ControllerState::Failed => return Err(ControllerState::Failed),
|
2025-04-09 23:15:07 +02:00
|
|
|
ControllerState::Paused => (),
|
2024-11-20 08:15:31 -07:00
|
|
|
ControllerState::Running => return Ok(()),
|
|
|
|
|
}
|
2025-04-09 23:15:07 +02:00
|
|
|
|
|
|
|
|
self.inner.notify.notified().await;
|
2024-11-20 08:15:31 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn progress(&self) -> f32 {
|
|
|
|
|
*self.inner.progress.lock().unwrap()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_progress(&self, progress: f32) {
|
|
|
|
|
*self.inner.progress.lock().unwrap() = progress;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn state(&self) -> ControllerState {
|
|
|
|
|
*self.inner.state.lock().unwrap()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_state(&self, state: ControllerState) {
|
|
|
|
|
*self.inner.state.lock().unwrap() = state;
|
2025-04-09 23:15:07 +02:00
|
|
|
self.inner.notify.notify_waiters();
|
2024-11-20 08:15:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn is_cancelled(&self) -> bool {
|
|
|
|
|
matches!(self.state(), ControllerState::Cancelled)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn cancel(&self) {
|
|
|
|
|
self.set_state(ControllerState::Cancelled);
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-01 01:28:26 -04:00
|
|
|
pub fn is_failed(&self) -> bool {
|
|
|
|
|
matches!(self.state(), ControllerState::Failed)
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-20 08:15:31 -07:00
|
|
|
pub fn is_paused(&self) -> bool {
|
|
|
|
|
matches!(self.state(), ControllerState::Paused)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn pause(&self) {
|
|
|
|
|
self.set_state(ControllerState::Paused);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn unpause(&self) {
|
2025-09-01 01:28:26 -04:00
|
|
|
if !self.is_cancelled() | !self.is_failed() {
|
2025-04-09 23:15:07 +02:00
|
|
|
self.set_state(ControllerState::Running);
|
|
|
|
|
}
|
2024-11-20 08:15:31 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Clone for Controller {
|
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
primary: false,
|
|
|
|
|
inner: self.inner.clone(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Drop for Controller {
|
|
|
|
|
fn drop(&mut self) {
|
2025-09-01 01:28:26 -04:00
|
|
|
// Cancel operations if primary controller is dropped and controller is still running
|
|
|
|
|
if self.primary && self.state() != ControllerState::Failed {
|
2024-11-20 08:15:31 -07:00
|
|
|
self.cancel();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|