use std::path::PathBuf;
use std::sync::{LazyLock, mpsc};
enum CleanRequest {
File(PathBuf),
Directory(PathBuf),
Flush(mpsc::SyncSender<()>),
}
static CLEANER: LazyLock<mpsc::Sender<CleanRequest>> = LazyLock::new(|| {
let (tx, rx) = mpsc::channel();
std::thread::Builder::new()
.name("polars-ooc-cleaner".into())
.spawn(move || run(rx))
.expect("failed to spawn polars-ooc cleaner thread");
tx
});
fn run(rx: mpsc::Receiver<CleanRequest>) {
cleanup_stale_dirs();
while let Ok(req) = rx.recv() {
match req {
CleanRequest::File(p) => {
if polars_config::config().verbose() {
eprintln!("[ooc] clean {}", p.display());
}
let _ = std::fs::remove_file(&p);
},
CleanRequest::Directory(p) => {
let _ = std::fs::remove_dir_all(&p);
},
CleanRequest::Flush(done) => {
let _ = done.send(());
},
}
}
}
pub(crate) fn delete_file(path: PathBuf) {
let _ = CLEANER.send(CleanRequest::File(path));
}
pub(crate) fn delete_directory(path: PathBuf) {
let _ = CLEANER.send(CleanRequest::Directory(path));
}
pub(crate) fn init() {
LazyLock::force(&CLEANER);
}
pub(crate) fn shutdown() {
let (tx, rx) = mpsc::sync_channel(1);
let _ = CLEANER.send(CleanRequest::Flush(tx));
let _ = rx.recv();
}
fn cleanup_stale_dirs() {
let spill_dir = polars_config::config().ooc_spill_dir();
let Ok(entries) = std::fs::read_dir(&spill_dir) else {
return;
};
let our_pid = std::process::id();
entries
.flatten()
.filter_map(|e| {
let pid = e.file_name().to_str()?.parse::<u32>().ok()?;
(pid != our_pid && !polars_utils::sys::is_process_alive(pid)).then(|| e.path())
})
.for_each(|p| {
let _ = std::fs::remove_dir_all(&p);
});
}