This repository has been archived on 2025-08-14. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
subscribe-list/src/db.rs
2024-04-08 18:25:32 -07:00

56 lines
1.6 KiB
Rust

use tokio::sync::{mpsc, oneshot};
struct DbThreadInner {
op_sender: mpsc::Sender<Box<dyn FnOnce(&mut diesel::SqliteConnection) + Send>>,
join_handle: std::thread::JoinHandle<()>,
}
pub struct DbThread(Option<DbThreadInner>);
impl DbThread {
pub fn new(mut connection: diesel::SqliteConnection, buffer: usize) -> Self {
let (op_sender, mut op_receiver) =
mpsc::channel::<Box<dyn FnOnce(&mut diesel::SqliteConnection) + Send>>(buffer);
let join_handle = std::thread::spawn(move || loop {
let Some(f) = op_receiver.blocking_recv() else {
break;
};
f(&mut connection);
});
Self(Some(DbThreadInner {
op_sender,
join_handle,
}))
}
pub async fn run_on<
F: FnOnce(&mut diesel::SqliteConnection) -> T + Send + 'static,
T: Send + 'static,
>(
&self,
f: F,
) -> T {
let (result_sender, result_receiver) = oneshot::channel();
self.0
.as_ref()
.unwrap()
.op_sender
.send(Box::new(move |connection| {
// if send failed, the future must have been canceled, so ignore send failures
let _ = result_sender.send(f(connection));
}))
.await
.expect("send to succeed");
result_receiver.await.expect("result to be written")
}
}
impl Drop for DbThread {
fn drop(&mut self) {
let DbThreadInner {
op_sender,
join_handle,
} = self.0.take().unwrap();
drop(op_sender);
join_handle.join().unwrap();
}
}