use std::{
sync::OnceLock,
thread::{self, JoinHandle},
time::Duration,
};
use crossbeam::channel::{self, Receiver, Sender};
use crate::{should_shutdown, shutdown};
static PROCESS_TX: OnceLock<Sender<ProcessRequest>> = OnceLock::new();
pub fn send_process_request(request: ProcessRequest) {
PROCESS_TX.get().unwrap().send(request).unwrap();
}
mod extract;
pub(crate) enum ProcessRequest {
Extract { callback: oneshot::Sender<bool> },
}
pub struct ProcessThread {
rx: Receiver<ProcessRequest>,
}
impl ProcessThread {
pub fn open() -> JoinHandle<()> {
let (tx, rx) = channel::unbounded();
PROCESS_TX.set(tx).expect("Process thread was opened twice");
thread::spawn(move || {
let processor = ProcessThread { rx };
if let Err(err) = processor.run() {
shutdown(format!("Process thread failed with error: {err}"));
}
})
}
pub fn run(self) -> anyhow::Result<()> {
while !should_shutdown() {
match self.rx.recv_timeout(Duration::from_secs(10)) {
Ok(request) => self.process_request(request)?,
Err(channel::RecvTimeoutError::Timeout) => continue,
Err(err) => return Err(err.into()),
}
}
Ok(())
}
pub fn process_request(&self, request: ProcessRequest) -> anyhow::Result<()> {
match request {
ProcessRequest::Extract { callback } => {
let _ = callback.send(true);
extract::extract()?;
}
}
Ok(())
}
}