pispas_modules/
pdf_manager.rs1use std::fs;
2use std::path::{PathBuf};
3use tokio::task::spawn_blocking;
4use easy_trace::prelude::{debug, error, info};
5
6const MAX_PDFS: usize = 31;
8
9
10#[derive(Debug)]
12pub struct PDFManager {
13 pdf_files: Vec<PathBuf>,
15}
16
17impl PDFManager {
18 pub fn new() -> Self {
20 let pdf_files = Self::initialize_pdf_list().unwrap_or_else(|e| {
21 error!("Failed to initialize PDF files: {}", e);
22 Vec::new()
23 });
24 info!("Initialized with {} PDF files.", pdf_files.len());
25 let mut manager = PDFManager { pdf_files };
26 manager.maintain_pdf_files(); manager
28 }
29
30 fn initialize_pdf_list() -> sharing::PisPasResult<Vec<PathBuf>> {
35 let mut pdf_files: Vec<_> = fs::read_dir(sharing::paths::jobs_dir())
36 .expect("Failed to read jobs directory")
37 .filter_map(|entry| {
38 let entry = entry.ok()?; let metadata = entry.metadata().ok()?; let modified = metadata.modified().ok()?; Some((entry.path(), modified)) })
43 .filter(|(path, _)| {
44 path.extension().map(|ext| ext == "pdf").unwrap_or(false) })
46 .collect();
47
48 pdf_files.sort_by_key(|&(_, modified)| modified);
50 Ok(pdf_files.into_iter().map(|(path, _)| path).collect())
51 }
52
53 pub fn add_pdf_file(&mut self, pdf_file: PathBuf) {
57 if !self.pdf_files.contains(&pdf_file) {
58 self.pdf_files.push(pdf_file);
59 }
60 self.maintain_pdf_files();
61 }
62
63 fn maintain_pdf_files(&mut self) {
65 while self.pdf_files.len() > MAX_PDFS {
66 let oldest_pdf = self.pdf_files[0].clone();
67 match fs::remove_file(&oldest_pdf) {
68 Ok(_) => {
69 debug!("Deleted old PDF file: {:?}", oldest_pdf);
70 self.pdf_files.remove(0);
71 }
72 Err(ref e) if e.kind() == std::io::ErrorKind::PermissionDenied => {
73 error!(
74 "File {:?} is in use, moving to the end of the list: {}",
75 oldest_pdf, e
76 );
77 let pdf = self.pdf_files.remove(0);
78 self.pdf_files.push(pdf);
79 }
80 Err(e) => {
81 error!("Failed to delete file {:?}: {}", oldest_pdf, e);
82 self.pdf_files.remove(0);
83 }
84 }
85 }
86 debug!("Remaining PDF files: {}", self.pdf_files.len());
87 }
88
89 pub async fn _maintain_jobs_directory(&self) {
93 spawn_blocking(move || {
94 let mut pdf_files = Self::initialize_pdf_list().unwrap_or_else(|e| {
95 error!("Failed to initialize PDF files: {}", e);
96 Vec::new()
97 });
98
99 while pdf_files.len() > MAX_PDFS {
100 if let Some(oldest_pdf) = pdf_files.get(0) {
102 if let Err(e) = fs::remove_file(oldest_pdf) {
104 error!("Error deleting file {:?}: {}", oldest_pdf, e);
105 } else {
106 pdf_files.remove(0); }
109 }
110 }
111
112 info!("Remaining PDF files: {}", pdf_files.len());
113 })
114 .await
115 .unwrap();
116 }
117}