Add job handle to jobs to wait for results
Signed-off-by: trivernis <trivernis@protonmail.com>feature/jobs
parent
a87c341867
commit
e9dbbd1bd5
@ -0,0 +1,102 @@
|
|||||||
|
use mediarepo_core::error::{RepoError, RepoResult};
|
||||||
|
use std::mem;
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tokio::sync::broadcast::{Receiver, Sender};
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
|
pub struct JobHandle<T: Send + Sync, R: Send + Sync> {
|
||||||
|
status: Arc<RwLock<T>>,
|
||||||
|
state: Arc<RwLock<JobState>>,
|
||||||
|
result_receiver: CloneableReceiver<Arc<RwLock<RepoResult<R>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Send + Sync, R: Send + Sync> Clone for JobHandle<T, R> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
status: self.status.clone(),
|
||||||
|
state: self.state.clone(),
|
||||||
|
result_receiver: self.result_receiver.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Send + Sync, R: Send + Sync> JobHandle<T, R> {
|
||||||
|
pub fn new(
|
||||||
|
status: Arc<RwLock<T>>,
|
||||||
|
state: Arc<RwLock<JobState>>,
|
||||||
|
result_receiver: CloneableReceiver<Arc<RwLock<RepoResult<R>>>>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
status,
|
||||||
|
state,
|
||||||
|
result_receiver,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn state(&self) -> JobState {
|
||||||
|
*self.state.read().await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn status(&self) -> &Arc<RwLock<T>> {
|
||||||
|
&self.status
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn result(&mut self) -> Arc<RwLock<RepoResult<R>>> {
|
||||||
|
match self.result_receiver.recv().await {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => Arc::new(RwLock::new(Err(RepoError::from(&*e.to_string())))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn try_result(&mut self) -> RepoResult<R> {
|
||||||
|
let shared_result = self.result().await;
|
||||||
|
let mut result = shared_result.write().await;
|
||||||
|
mem::replace(&mut *result, Err(RepoError::from("result taken")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
|
pub enum JobState {
|
||||||
|
Queued,
|
||||||
|
Scheduled,
|
||||||
|
Running,
|
||||||
|
Finished,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CloneableReceiver<T: Clone> {
|
||||||
|
receiver: Receiver<T>,
|
||||||
|
sender: Sender<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone> CloneableReceiver<T> {
|
||||||
|
pub fn new(sender: Sender<T>) -> Self {
|
||||||
|
Self {
|
||||||
|
receiver: sender.subscribe(),
|
||||||
|
sender,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone> Clone for CloneableReceiver<T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
sender: self.sender.clone(),
|
||||||
|
receiver: self.sender.subscribe(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone> Deref for CloneableReceiver<T> {
|
||||||
|
type Target = Receiver<T>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.receiver
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone> DerefMut for CloneableReceiver<T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.receiver
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue