aboutsummaryrefslogtreecommitdiff
path: root/src/util/background/job_worker.rs
blob: 2568ea11af8f7f43d00e4c83ae1f112fb16ea5bd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//! Job worker: a generic worker that just processes incoming
//! jobs one by one

use std::sync::Arc;

use async_trait::async_trait;
use tokio::sync::{mpsc, Mutex};

use crate::background::worker::*;
use crate::background::*;

pub(crate) struct JobWorker {
	pub(crate) index: usize,
	pub(crate) job_chan: Arc<Mutex<mpsc::UnboundedReceiver<(Job, bool)>>>,
	pub(crate) next_job: Option<Job>,
}

#[async_trait]
impl Worker for JobWorker {
	fn name(&self) -> String {
		format!("Job worker #{}", self.index)
	}

	async fn work(&mut self, _must_exit: &mut watch::Receiver<bool>) -> Result<WorkerState, Error> {
		match self.next_job.take() {
			None => return Ok(WorkerState::Idle),
			Some(job) => {
				job.await?;
				Ok(WorkerState::Busy)
			}
		}
	}

	async fn wait_for_work(&mut self, must_exit: &watch::Receiver<bool>) -> WorkerState {
		loop {
			match self.job_chan.lock().await.recv().await {
				Some((job, cancellable)) => {
					if cancellable && *must_exit.borrow() {
						continue;
					}
					self.next_job = Some(job);
					return WorkerState::Busy;
				}
				None => return WorkerState::Done,
			}
		}
	}
}