use crate::JobSchedulerError; use crate::context::Context; #[cfg(not(feature = "has_bytes"))] use crate::job::job_data::JobState; #[cfg(feature = "has_bytes")] use crate::job::job_data_prost::JobState; use crate::job::to_code::JobCode; use crate::job_scheduler::JobsSchedulerLocked; use std::future::Future; use std::pin::Pin; use std::sync::Arc; use tokio::sync::RwLock; use tokio::sync::broadcast::error::RecvError; use tokio::sync::broadcast::{Receiver, Sender}; use tracing::error; use uuid::Uuid; #[derive(Default)] pub struct JobRunner {} impl JobRunner { async fn listen_for_activations( job_code: Arc>>, mut rx: Receiver, tx_notify: Sender<(Uuid, JobState)>, job_scheduler: JobsSchedulerLocked, ) { loop { let val = rx.recv().await; if let Err(e) = val { error!("Error receiving {:?}", e); if matches!(e, RecvError::Closed) { break; } continue; } let uuid = val.unwrap(); { let tx = tx_notify.clone(); tokio::spawn(async move { if let Err(e) = tx.send((uuid, JobState::Started)) { error!("Error sending error listening for activation {:?}", e); } }); } let mut w = job_code.write().await; let code = w.get(uuid).await; match code { Ok(Some(job)) => { let mut job = job.write().await; let v = (job)(uuid, job_scheduler.clone()); let tx = tx_notify.clone(); tokio::spawn(async move { v.await; if let Err(e) = tx.send((uuid, JobState::Done)) { error!("Error sending spawned task {:?}", e); } }); } _ => { error!("Error getting {:?} from job code", uuid); continue; } } } } pub fn init( &mut self, context: &Context, job_scheduler: JobsSchedulerLocked, ) -> Pin> + Send>> { let job_code = context.job_code.clone(); let notify_tx = context.notify_tx.clone(); let job_activation_rx = context.job_activation_tx.subscribe(); Box::pin(async move { tokio::spawn(JobRunner::listen_for_activations( job_code, job_activation_rx, notify_tx, job_scheduler, )); Ok(()) }) } }