diff --git a/melib/src/async_workers.rs b/melib/src/async_workers.rs index 7eb49d2b..25497d4f 100644 --- a/melib/src/async_workers.rs +++ b/melib/src/async_workers.rs @@ -37,7 +37,6 @@ use crossbeam::{ select, }; use std::fmt; -use std::sync::Arc; #[derive(Clone, Debug)] pub struct WorkContext { @@ -47,11 +46,10 @@ pub struct WorkContext { pub finished: Sender, } -#[derive(Clone)] pub struct Work { priority: u64, pub is_static: bool, - pub closure: Arc () + Send + Sync>>, + pub closure: Box () + Send + Sync>, name: String, status: String, } @@ -77,7 +75,7 @@ impl PartialEq for Work { impl Eq for Work {} impl Work { - pub fn compute(&self, work_context: WorkContext) { + pub fn compute(self, work_context: WorkContext) { (self.closure)(work_context); } } @@ -118,9 +116,9 @@ pub struct AsyncBuilder { is_static: bool, } -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct Async { - work: Work, + work: Option, active: bool, tx: Sender>, rx: Receiver>, @@ -165,15 +163,15 @@ where } /// Returns an `Async` object that contains a `Thread` join handle that returns a `T` - pub fn build(self, work: Box () + Send + Sync>) -> Async { + pub fn build(self, work: Box () + Send + Sync>) -> Async { Async { - work: Work { + work: Some(Work { priority: self.priority, is_static: self.is_static, - closure: Arc::new(work), + closure: work, name: String::new(), status: String::new(), - }, + }), tx: self.tx, rx: self.rx, active: false, @@ -188,7 +186,7 @@ where pub fn work(&mut self) -> Option { if !self.active { self.active = true; - Some(self.work.clone()) + self.work.take() } else { None } diff --git a/melib/src/backends/imap.rs b/melib/src/backends/imap.rs index 0329887e..dd4aad88 100644 --- a/melib/src/backends/imap.rs +++ b/melib/src/backends/imap.rs @@ -185,8 +185,6 @@ impl MailBackend for ImapType { tx.send(AsyncStatus::Finished).unwrap(); return; } - let connection = connection.clone(); - let tx = tx.clone(); let mut response = String::with_capacity(8 * 1024); let conn = connection.lock(); exit_on_error!(&tx, conn); @@ -246,7 +244,7 @@ impl MailBackend for ImapType { response.lines().collect::>().len() ); match protocol_parser::uid_fetch_responses(&response) { - Ok((_, v)) => { + Ok((_, v, _)) => { debug!("responses len is {}", v.len()); for UidFetchResponse { uid, diff --git a/melib/src/backends/imap/connection.rs b/melib/src/backends/imap/connection.rs index 3ee66613..601f39af 100644 --- a/melib/src/backends/imap/connection.rs +++ b/melib/src/backends/imap/connection.rs @@ -333,6 +333,13 @@ impl ImapConnection { } pub fn read_response(&mut self, ret: &mut String) -> Result<()> { + if let (instant, ref mut status @ Ok(())) = *self.online.lock().unwrap() { + if Instant::now().duration_since(instant) >= std::time::Duration::new(60 * 30, 0) { + *status = Err(MeliError::new("Connection timed out")); + self.stream = Err(MeliError::new("Connection timed out")); + } + } + if let Ok(ref mut stream) = self.stream { if let Ok(_) = stream.read_response(ret) { return Ok(()); @@ -418,7 +425,7 @@ impl ImapConnection { } pub fn send_command(&mut self, command: &[u8]) -> Result { - if let (instant, ref mut status @ Ok(())) = *self.online.lock().unwrap() { + if let (instant, ref mut status) = *self.online.lock().unwrap() { if Instant::now().duration_since(instant) >= std::time::Duration::new(60 * 30, 0) { *status = Err(MeliError::new("Connection timed out")); self.stream = Err(MeliError::new("Connection timed out")); diff --git a/melib/src/backends/imap/protocol_parser.rs b/melib/src/backends/imap/protocol_parser.rs index 472e0fe7..17bedff6 100644 --- a/melib/src/backends/imap/protocol_parser.rs +++ b/melib/src/backends/imap/protocol_parser.rs @@ -5,7 +5,9 @@ use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use std::str::FromStr; -pub type ImapParseResult<'a, T> = Result<(&'a str, T)>; +#[derive(Debug)] +pub struct Alert(String); +pub type ImapParseResult<'a, T> = Result<(&'a str, T, Option)>; pub struct ImapLineIterator<'a> { slice: &'a str, } @@ -328,13 +330,22 @@ pub fn uid_fetch_response(input: &str) -> ImapParseResult> env.set_has_attachments(has_attachments); } - Ok((&input[i..], ret)) + Ok((&input[i..], ret, None)) } pub fn uid_fetch_responses(mut input: &str) -> ImapParseResult>> { let mut ret = Vec::new(); + let mut alert: Option = None; - while let Ok((rest, el)) = uid_fetch_response(input) { + while let Ok((rest, el, el_alert)) = uid_fetch_response(input) { + if let Some(el_alert) = el_alert { + match &mut alert { + Some(Alert(ref mut alert)) => { + alert.extend(el_alert.0.chars()); + } + a @ None => *a = Some(el_alert), + } + } input = rest; ret.push(el); } @@ -345,7 +356,7 @@ pub fn uid_fetch_responses(mut input: &str) -> ImapParseResult Result<()> { ); debug!(&response); match protocol_parser::uid_fetch_responses(&response) { - Ok((_, v)) => { + Ok((_, v, _)) => { let len = v.len(); let mut ctr = 0; for UidFetchResponse { @@ -421,7 +421,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> { conn.read_response(&mut response) ); match protocol_parser::uid_fetch_responses(&response) { - Ok((_, v)) => { + Ok((_, v, _)) => { let len = v.len(); let mut ctr = 0; for UidFetchResponse { @@ -600,7 +600,7 @@ fn examine_updates( ); debug!(&response); match protocol_parser::uid_fetch_responses(&response) { - Ok((_, v)) => { + Ok((_, v, _)) => { for UidFetchResponse { uid, flags, body, .. } in v @@ -679,7 +679,7 @@ fn examine_updates( conn.read_response(&mut response) ); match protocol_parser::uid_fetch_responses(&response) { - Ok((_, v)) => { + Ok((_, v, _)) => { for UidFetchResponse { uid, flags, body, .. } in v diff --git a/melib/src/backends/maildir/backend.rs b/melib/src/backends/maildir/backend.rs index e524b688..6426abfc 100644 --- a/melib/src/backends/maildir/backend.rs +++ b/melib/src/backends/maildir/backend.rs @@ -218,26 +218,13 @@ impl MailBackend for MaildirType { let sender = Arc::new(sender); Box::new(move |work_context: crate::async_workers::WorkContext| { - let cache_dir = cache_dir.clone(); - let folder_index = folder_index.clone(); - let root_path = root_path.clone(); - let path = path.clone(); - let name = name.clone(); - let map = map.clone(); - let sender = sender.clone(); work_context .set_name .send((std::thread::current().id(), name.clone())) .unwrap(); let thunk = move |sender: &RefreshEventConsumer| { debug!("refreshing"); - let cache_dir = cache_dir.clone(); - let map = map.clone(); - let folder_index = folder_index.clone(); - let folder_hash = folder_hash.clone(); - let root_path = root_path.clone(); let mut path = path.clone(); - let cache_dir = cache_dir.clone(); path.push("new"); for d in path.read_dir()? { if let Ok(p) = d { @@ -789,35 +776,23 @@ impl MaildirType { let handle = { let tx = w.tx(); - // TODO: Avoid clone let folder: &MaildirFolder = &self.folders[&self.owned_folder_idx(folder)]; let folder_hash = folder.hash(); let unseen = folder.unseen.clone(); let total = folder.total.clone(); let tx_final = w.tx(); - let path: PathBuf = folder.fs_path().into(); + let mut path: PathBuf = folder.fs_path().into(); let name = format!("parsing {:?}", folder.name()); let root_path = self.path.to_path_buf(); let map = self.hash_indexes.clone(); let folder_index = self.folder_index.clone(); let closure = move |work_context: crate::async_workers::WorkContext| { - let unseen = unseen.clone(); - let total = total.clone(); - let name = name.clone(); work_context .set_name .send((std::thread::current().id(), name.clone())) .unwrap(); - let root_path = root_path.clone(); - let map = map.clone(); - let folder_index = folder_index.clone(); - let tx = tx.clone(); - let cache_dir = cache_dir.clone(); - let path = path.clone(); - let thunk = move || { - let mut path = path.clone(); - let cache_dir = cache_dir.clone(); + let mut thunk = move || { path.push("new"); for d in path.read_dir()? { if let Ok(p) = d { @@ -841,7 +816,6 @@ impl MaildirType { if !files.is_empty() { crossbeam::scope(|scope| { let mut threads = Vec::with_capacity(cores); - let cache_dir = cache_dir.clone(); let chunk_size = if count / cores > 0 { count / cores } else { diff --git a/ui/src/conf/accounts.rs b/ui/src/conf/accounts.rs index b156d5fd..6239cdd5 100644 --- a/ui/src/conf/accounts.rs +++ b/ui/src/conf/accounts.rs @@ -480,7 +480,7 @@ impl Account { work_context: &WorkContext, notify_fn: Arc, ) -> Worker { - let mailbox_handle = backend.write().unwrap().get(&folder); + let mut mailbox_handle = backend.write().unwrap().get(&folder); let mut builder = AsyncBuilder::new(); let our_tx = builder.tx(); let folder_hash = folder.hash(); @@ -508,7 +508,6 @@ impl Account { builder.set_priority(priority).set_is_static(true); let mut w = builder.build(Box::new(move |work_context| { let name = format!("Parsing {}", folder.path()); - let mut mailbox_handle = mailbox_handle.clone(); let work = mailbox_handle.work().unwrap(); work_context.new_work.send(work).unwrap(); let thread_id = std::thread::current().id();