melib/imap: introduce a conf flag for server timeout
timeout integer (optional) Timeout to use for server connections in seconds. A timeout of 0 seconds means there's no timeout. (16)master
parent
96985c9c1f
commit
06a58a70bd
|
@ -240,6 +240,12 @@ Use IDLE extension.
|
||||||
Use COMPRESS=DEFLATE extension (if built with DEFLATE support).
|
Use COMPRESS=DEFLATE extension (if built with DEFLATE support).
|
||||||
.\" default value
|
.\" default value
|
||||||
.Pq Em true
|
.Pq Em true
|
||||||
|
.It Ic timeout Ar integer
|
||||||
|
.Pq Em optional
|
||||||
|
Timeout to use for server connections in seconds.
|
||||||
|
A timeout of 0 seconds means there's no timeout.
|
||||||
|
.\" default value
|
||||||
|
.Pq Em 16
|
||||||
.El
|
.El
|
||||||
.Ss JMAP only
|
.Ss JMAP only
|
||||||
JMAP specific options
|
JMAP specific options
|
||||||
|
|
|
@ -97,6 +97,7 @@ pub struct ImapServerConf {
|
||||||
pub use_tls: bool,
|
pub use_tls: bool,
|
||||||
pub danger_accept_invalid_certs: bool,
|
pub danger_accept_invalid_certs: bool,
|
||||||
pub protocol: ImapProtocol,
|
pub protocol: ImapProtocol,
|
||||||
|
pub timeout: Option<Duration>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IsSubscribedFn(Box<dyn Fn(&str) -> bool + Send + Sync>);
|
struct IsSubscribedFn(Box<dyn Fn(&str) -> bool + Send + Sync>);
|
||||||
|
@ -167,6 +168,7 @@ pub struct UIDStore {
|
||||||
mailboxes: Arc<FutureMutex<HashMap<MailboxHash, ImapMailbox>>>,
|
mailboxes: Arc<FutureMutex<HashMap<MailboxHash, ImapMailbox>>>,
|
||||||
is_online: Arc<Mutex<(Instant, Result<()>)>>,
|
is_online: Arc<Mutex<(Instant, Result<()>)>>,
|
||||||
event_consumer: BackendEventConsumer,
|
event_consumer: BackendEventConsumer,
|
||||||
|
timeout: Option<Duration>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UIDStore {
|
impl UIDStore {
|
||||||
|
@ -174,6 +176,7 @@ impl UIDStore {
|
||||||
account_hash: AccountHash,
|
account_hash: AccountHash,
|
||||||
account_name: Arc<String>,
|
account_name: Arc<String>,
|
||||||
event_consumer: BackendEventConsumer,
|
event_consumer: BackendEventConsumer,
|
||||||
|
timeout: Option<Duration>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
UIDStore {
|
UIDStore {
|
||||||
account_hash,
|
account_hash,
|
||||||
|
@ -197,6 +200,7 @@ impl UIDStore {
|
||||||
Err(MeliError::new("Account is uninitialised.")),
|
Err(MeliError::new("Account is uninitialised.")),
|
||||||
))),
|
))),
|
||||||
event_consumer,
|
event_consumer,
|
||||||
|
timeout,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -354,12 +358,12 @@ impl MailBackend for ImapType {
|
||||||
let main_conn = self.connection.clone();
|
let main_conn = self.connection.clone();
|
||||||
let uid_store = self.uid_store.clone();
|
let uid_store = self.uid_store.clone();
|
||||||
Ok(Box::pin(async move {
|
Ok(Box::pin(async move {
|
||||||
let inbox = timeout(Duration::from_secs(3), uid_store.mailboxes.lock())
|
let inbox = timeout(uid_store.timeout, uid_store.mailboxes.lock())
|
||||||
.await?
|
.await?
|
||||||
.get(&mailbox_hash)
|
.get(&mailbox_hash)
|
||||||
.map(std::clone::Clone::clone)
|
.map(std::clone::Clone::clone)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut conn = timeout(Duration::from_secs(3), main_conn.lock()).await?;
|
let mut conn = timeout(uid_store.timeout, main_conn.lock()).await?;
|
||||||
watch::examine_updates(inbox, &mut conn, &uid_store).await?;
|
watch::examine_updates(inbox, &mut conn, &uid_store).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}))
|
}))
|
||||||
|
@ -416,11 +420,12 @@ impl MailBackend for ImapType {
|
||||||
|
|
||||||
fn is_online(&self) -> ResultFuture<()> {
|
fn is_online(&self) -> ResultFuture<()> {
|
||||||
let connection = self.connection.clone();
|
let connection = self.connection.clone();
|
||||||
|
let timeout_dur = self.server_conf.timeout;
|
||||||
Ok(Box::pin(async move {
|
Ok(Box::pin(async move {
|
||||||
match timeout(std::time::Duration::from_secs(3), connection.lock()).await {
|
match timeout(timeout_dur, connection.lock()).await {
|
||||||
Ok(mut conn) => {
|
Ok(mut conn) => {
|
||||||
debug!("is_online");
|
debug!("is_online");
|
||||||
match debug!(timeout(std::time::Duration::from_secs(3), conn.connect()).await) {
|
match debug!(timeout(timeout_dur, conn.connect()).await) {
|
||||||
Ok(Ok(())) => Ok(()),
|
Ok(Ok(())) => Ok(()),
|
||||||
Err(err) | Ok(Err(err)) => {
|
Err(err) | Ok(Err(err)) => {
|
||||||
conn.stream = Err(err.clone());
|
conn.stream = Err(err.clone());
|
||||||
|
@ -453,6 +458,7 @@ impl MailBackend for ImapType {
|
||||||
Ok(Box::pin(async move {
|
Ok(Box::pin(async move {
|
||||||
debug!(has_idle);
|
debug!(has_idle);
|
||||||
let main_conn2 = main_conn.clone();
|
let main_conn2 = main_conn.clone();
|
||||||
|
let timeout_dur = uid_store.timeout;
|
||||||
let kit = ImapWatchKit {
|
let kit = ImapWatchKit {
|
||||||
conn,
|
conn,
|
||||||
main_conn,
|
main_conn,
|
||||||
|
@ -463,7 +469,7 @@ impl MailBackend for ImapType {
|
||||||
} else {
|
} else {
|
||||||
poll_with_examine(kit).await
|
poll_with_examine(kit).await
|
||||||
} {
|
} {
|
||||||
let mut main_conn = timeout(Duration::from_secs(3), main_conn2.lock()).await?;
|
let mut main_conn = timeout(timeout_dur, main_conn2.lock()).await?;
|
||||||
if err.kind.is_network() {
|
if err.kind.is_network() {
|
||||||
main_conn.uid_store.is_online.lock().unwrap().1 = Err(err.clone());
|
main_conn.uid_store.is_online.lock().unwrap().1 = Err(err.clone());
|
||||||
}
|
}
|
||||||
|
@ -1222,6 +1228,12 @@ impl ImapType {
|
||||||
s.name,
|
s.name,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
let timeout = get_conf_val!(s["timeout"], 16_u64)?;
|
||||||
|
let timeout = if timeout == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(Duration::from_secs(timeout))
|
||||||
|
};
|
||||||
let server_conf = ImapServerConf {
|
let server_conf = ImapServerConf {
|
||||||
server_hostname: server_hostname.to_string(),
|
server_hostname: server_hostname.to_string(),
|
||||||
server_username: server_username.to_string(),
|
server_username: server_username.to_string(),
|
||||||
|
@ -1238,6 +1250,7 @@ impl ImapType {
|
||||||
deflate: get_conf_val!(s["use_deflate"], true)?,
|
deflate: get_conf_val!(s["use_deflate"], true)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
timeout,
|
||||||
};
|
};
|
||||||
let account_hash = {
|
let account_hash = {
|
||||||
let mut hasher = DefaultHasher::new();
|
let mut hasher = DefaultHasher::new();
|
||||||
|
@ -1247,7 +1260,12 @@ impl ImapType {
|
||||||
let account_name = Arc::new(s.name().to_string());
|
let account_name = Arc::new(s.name().to_string());
|
||||||
let uid_store: Arc<UIDStore> = Arc::new(UIDStore {
|
let uid_store: Arc<UIDStore> = Arc::new(UIDStore {
|
||||||
keep_offline_cache,
|
keep_offline_cache,
|
||||||
..UIDStore::new(account_hash, account_name, event_consumer)
|
..UIDStore::new(
|
||||||
|
account_hash,
|
||||||
|
account_name,
|
||||||
|
event_consumer,
|
||||||
|
server_conf.timeout,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
let connection = ImapConnection::new_connection(&server_conf, uid_store.clone());
|
let connection = ImapConnection::new_connection(&server_conf, uid_store.clone());
|
||||||
|
|
||||||
|
@ -1262,15 +1280,18 @@ impl ImapType {
|
||||||
pub fn shell(&mut self) {
|
pub fn shell(&mut self) {
|
||||||
let mut conn = ImapConnection::new_connection(&self.server_conf, self.uid_store.clone());
|
let mut conn = ImapConnection::new_connection(&self.server_conf, self.uid_store.clone());
|
||||||
|
|
||||||
futures::executor::block_on(timeout(Duration::from_secs(3), conn.connect()))
|
futures::executor::block_on(timeout(self.server_conf.timeout, conn.connect()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut res = String::with_capacity(8 * 1024);
|
let mut res = String::with_capacity(8 * 1024);
|
||||||
futures::executor::block_on(timeout(Duration::from_secs(3), conn.send_command(b"NOOP")))
|
|
||||||
.unwrap()
|
|
||||||
.unwrap();
|
|
||||||
futures::executor::block_on(timeout(
|
futures::executor::block_on(timeout(
|
||||||
Duration::from_secs(3),
|
self.server_conf.timeout,
|
||||||
|
conn.send_command(b"NOOP"),
|
||||||
|
))
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
futures::executor::block_on(timeout(
|
||||||
|
self.server_conf.timeout,
|
||||||
conn.read_response(&mut res, RequiredResponses::empty()),
|
conn.read_response(&mut res, RequiredResponses::empty()),
|
||||||
))
|
))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -1284,13 +1305,13 @@ impl ImapType {
|
||||||
match io::stdin().read_line(&mut input) {
|
match io::stdin().read_line(&mut input) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
futures::executor::block_on(timeout(
|
futures::executor::block_on(timeout(
|
||||||
Duration::from_secs(3),
|
self.server_conf.timeout,
|
||||||
conn.send_command(input.as_bytes()),
|
conn.send_command(input.as_bytes()),
|
||||||
))
|
))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
futures::executor::block_on(timeout(
|
futures::executor::block_on(timeout(
|
||||||
Duration::from_secs(3),
|
self.server_conf.timeout,
|
||||||
conn.read_lines(&mut res, String::new()),
|
conn.read_lines(&mut res, String::new()),
|
||||||
))
|
))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -1460,6 +1481,7 @@ impl ImapType {
|
||||||
s.name.as_str(),
|
s.name.as_str(),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
let _timeout = get_conf_val!(s["timeout"], 16_u64)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,7 @@ pub struct ImapStream {
|
||||||
pub stream: AsyncWrapper<Connection>,
|
pub stream: AsyncWrapper<Connection>,
|
||||||
pub protocol: ImapProtocol,
|
pub protocol: ImapProtocol,
|
||||||
pub current_mailbox: MailboxSelection,
|
pub current_mailbox: MailboxSelection,
|
||||||
|
pub timeout: Option<Duration>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
|
@ -134,8 +135,12 @@ impl ImapStream {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut socket = AsyncWrapper::new(Connection::Tcp(
|
let mut socket = AsyncWrapper::new(Connection::Tcp(
|
||||||
TcpStream::connect_timeout(&addr, Duration::new(4, 0))
|
if let Some(timeout) = server_conf.timeout {
|
||||||
.chain_err_kind(crate::error::ErrorKind::Network)?,
|
TcpStream::connect_timeout(&addr, timeout)
|
||||||
|
.chain_err_kind(crate::error::ErrorKind::Network)?
|
||||||
|
} else {
|
||||||
|
TcpStream::connect(&addr).chain_err_kind(crate::error::ErrorKind::Network)?
|
||||||
|
},
|
||||||
))
|
))
|
||||||
.chain_err_kind(crate::error::ErrorKind::Network)?;
|
.chain_err_kind(crate::error::ErrorKind::Network)?;
|
||||||
if server_conf.use_starttls {
|
if server_conf.use_starttls {
|
||||||
|
@ -239,8 +244,12 @@ impl ImapStream {
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
AsyncWrapper::new(Connection::Tcp(
|
AsyncWrapper::new(Connection::Tcp(
|
||||||
TcpStream::connect_timeout(&addr, Duration::new(4, 0))
|
if let Some(timeout) = server_conf.timeout {
|
||||||
.chain_err_kind(crate::error::ErrorKind::Network)?,
|
TcpStream::connect_timeout(&addr, timeout)
|
||||||
|
.chain_err_kind(crate::error::ErrorKind::Network)?
|
||||||
|
} else {
|
||||||
|
TcpStream::connect(&addr).chain_err_kind(crate::error::ErrorKind::Network)?
|
||||||
|
},
|
||||||
))
|
))
|
||||||
.chain_err_kind(crate::error::ErrorKind::Network)?
|
.chain_err_kind(crate::error::ErrorKind::Network)?
|
||||||
};
|
};
|
||||||
|
@ -250,6 +259,7 @@ impl ImapStream {
|
||||||
stream,
|
stream,
|
||||||
protocol: server_conf.protocol,
|
protocol: server_conf.protocol,
|
||||||
current_mailbox: MailboxSelection::None,
|
current_mailbox: MailboxSelection::None,
|
||||||
|
timeout: server_conf.timeout,
|
||||||
};
|
};
|
||||||
if let ImapProtocol::ManageSieve = server_conf.protocol {
|
if let ImapProtocol::ManageSieve = server_conf.protocol {
|
||||||
use data_encoding::BASE64;
|
use data_encoding::BASE64;
|
||||||
|
@ -384,7 +394,7 @@ impl ImapStream {
|
||||||
ret.clear();
|
ret.clear();
|
||||||
let mut last_line_idx: usize = 0;
|
let mut last_line_idx: usize = 0;
|
||||||
loop {
|
loop {
|
||||||
match timeout(Duration::from_secs(16), self.stream.read(&mut buf)).await? {
|
match timeout(self.timeout, self.stream.read(&mut buf)).await? {
|
||||||
Ok(0) => break,
|
Ok(0) => break,
|
||||||
Ok(b) => {
|
Ok(b) => {
|
||||||
ret.push_str(unsafe { std::str::from_utf8_unchecked(&buf[0..b]) });
|
ret.push_str(unsafe { std::str::from_utf8_unchecked(&buf[0..b]) });
|
||||||
|
@ -432,7 +442,7 @@ impl ImapStream {
|
||||||
|
|
||||||
pub async fn send_command(&mut self, command: &[u8]) -> Result<()> {
|
pub async fn send_command(&mut self, command: &[u8]) -> Result<()> {
|
||||||
if let Err(err) = timeout(
|
if let Err(err) = timeout(
|
||||||
Duration::from_secs(16),
|
self.timeout,
|
||||||
try_await(async move {
|
try_await(async move {
|
||||||
let command = command.trim();
|
let command = command.trim();
|
||||||
match self.protocol {
|
match self.protocol {
|
||||||
|
@ -603,6 +613,7 @@ impl ImapConnection {
|
||||||
stream,
|
stream,
|
||||||
protocol,
|
protocol,
|
||||||
current_mailbox,
|
current_mailbox,
|
||||||
|
timeout,
|
||||||
} = std::mem::replace(&mut self.stream, Err(MeliError::new("")))?;
|
} = std::mem::replace(&mut self.stream, Err(MeliError::new("")))?;
|
||||||
let stream = stream.into_inner()?;
|
let stream = stream.into_inner()?;
|
||||||
self.stream = Ok(ImapStream {
|
self.stream = Ok(ImapStream {
|
||||||
|
@ -610,6 +621,7 @@ impl ImapConnection {
|
||||||
stream: AsyncWrapper::new(stream.deflate())?,
|
stream: AsyncWrapper::new(stream.deflate())?,
|
||||||
protocol,
|
protocol,
|
||||||
current_mailbox,
|
current_mailbox,
|
||||||
|
timeout,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,12 @@ pub fn new_managesieve_connection(
|
||||||
let server_password = get_conf_val!(s["server_password"])?;
|
let server_password = get_conf_val!(s["server_password"])?;
|
||||||
let server_port = get_conf_val!(s["server_port"], 4190)?;
|
let server_port = get_conf_val!(s["server_port"], 4190)?;
|
||||||
let danger_accept_invalid_certs: bool = get_conf_val!(s["danger_accept_invalid_certs"], false)?;
|
let danger_accept_invalid_certs: bool = get_conf_val!(s["danger_accept_invalid_certs"], false)?;
|
||||||
|
let timeout = get_conf_val!(s["timeout"], 16_u64)?;
|
||||||
|
let timeout = if timeout == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(std::time::Duration::from_secs(timeout))
|
||||||
|
};
|
||||||
let server_conf = ImapServerConf {
|
let server_conf = ImapServerConf {
|
||||||
server_hostname: server_hostname.to_string(),
|
server_hostname: server_hostname.to_string(),
|
||||||
server_username: server_username.to_string(),
|
server_username: server_username.to_string(),
|
||||||
|
@ -105,13 +111,19 @@ pub fn new_managesieve_connection(
|
||||||
use_tls: true,
|
use_tls: true,
|
||||||
danger_accept_invalid_certs,
|
danger_accept_invalid_certs,
|
||||||
protocol: ImapProtocol::ManageSieve,
|
protocol: ImapProtocol::ManageSieve,
|
||||||
|
timeout,
|
||||||
};
|
};
|
||||||
let uid_store = Arc::new(UIDStore {
|
let uid_store = Arc::new(UIDStore {
|
||||||
is_online: Arc::new(Mutex::new((
|
is_online: Arc::new(Mutex::new((
|
||||||
Instant::now(),
|
Instant::now(),
|
||||||
Err(MeliError::new("Account is uninitialised.")),
|
Err(MeliError::new("Account is uninitialised.")),
|
||||||
))),
|
))),
|
||||||
..UIDStore::new(account_hash, Arc::new(account_name), event_consumer)
|
..UIDStore::new(
|
||||||
|
account_hash,
|
||||||
|
Arc::new(account_name),
|
||||||
|
event_consumer,
|
||||||
|
server_conf.timeout,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
Ok(ImapConnection::new_connection(&server_conf, uid_store))
|
Ok(ImapConnection::new_connection(&server_conf, uid_store))
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,8 +66,7 @@ impl BackendOp for ImapOp {
|
||||||
if !exists_in_cache {
|
if !exists_in_cache {
|
||||||
let mut response = String::with_capacity(8 * 1024);
|
let mut response = String::with_capacity(8 * 1024);
|
||||||
{
|
{
|
||||||
let mut conn =
|
let mut conn = timeout(uid_store.timeout, connection.lock()).await?;
|
||||||
timeout(std::time::Duration::from_secs(3), connection.lock()).await?;
|
|
||||||
conn.examine_mailbox(mailbox_hash, &mut response, false)
|
conn.examine_mailbox(mailbox_hash, &mut response, false)
|
||||||
.await?;
|
.await?;
|
||||||
conn.send_command(format!("UID FETCH {} (FLAGS RFC822)", uid).as_bytes())
|
conn.send_command(format!("UID FETCH {} (FLAGS RFC822)", uid).as_bytes())
|
||||||
|
|
|
@ -39,7 +39,7 @@ pub async fn poll_with_examine(kit: ImapWatchKit) -> Result<()> {
|
||||||
conn.connect().await?;
|
conn.connect().await?;
|
||||||
loop {
|
loop {
|
||||||
let mailboxes: HashMap<MailboxHash, ImapMailbox> = {
|
let mailboxes: HashMap<MailboxHash, ImapMailbox> = {
|
||||||
let mailboxes_lck = timeout(Duration::from_secs(3), uid_store.mailboxes.lock()).await?;
|
let mailboxes_lck = timeout(uid_store.timeout, uid_store.mailboxes.lock()).await?;
|
||||||
mailboxes_lck.clone()
|
mailboxes_lck.clone()
|
||||||
};
|
};
|
||||||
for (_, mailbox) in mailboxes {
|
for (_, mailbox) in mailboxes {
|
||||||
|
@ -109,14 +109,16 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
let mut blockn = ImapBlockingConnection::from(conn);
|
let mut blockn = ImapBlockingConnection::from(conn);
|
||||||
let mut beat = std::time::Instant::now();
|
let mut beat = std::time::Instant::now();
|
||||||
let mut watch = std::time::Instant::now();
|
let mut watch = std::time::Instant::now();
|
||||||
|
/* duration interval before IMAP timeouts */
|
||||||
|
const _35_MINS: std::time::Duration = std::time::Duration::from_secs(35 * 60);
|
||||||
/* duration interval to send heartbeat */
|
/* duration interval to send heartbeat */
|
||||||
const _26_MINS: std::time::Duration = std::time::Duration::from_secs(26 * 60);
|
const _26_MINS: std::time::Duration = std::time::Duration::from_secs(26 * 60);
|
||||||
/* duration interval to check other mailboxes for changes */
|
/* duration interval to check other mailboxes for changes */
|
||||||
const _5_MINS: std::time::Duration = std::time::Duration::from_secs(5 * 60);
|
const _5_MINS: std::time::Duration = std::time::Duration::from_secs(5 * 60);
|
||||||
while let Some(line) = timeout(Duration::from_secs(35 * 60), blockn.as_stream()).await? {
|
while let Some(line) = timeout(Some(_35_MINS), blockn.as_stream()).await? {
|
||||||
let now = std::time::Instant::now();
|
let now = std::time::Instant::now();
|
||||||
if now.duration_since(beat) >= _26_MINS {
|
if now.duration_since(beat) >= _26_MINS {
|
||||||
let mut main_conn_lck = timeout(Duration::from_secs(3), main_conn.lock()).await?;
|
let mut main_conn_lck = timeout(uid_store.timeout, main_conn.lock()).await?;
|
||||||
blockn.conn.send_raw(b"DONE").await?;
|
blockn.conn.send_raw(b"DONE").await?;
|
||||||
blockn
|
blockn
|
||||||
.conn
|
.conn
|
||||||
|
@ -131,10 +133,10 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
}
|
}
|
||||||
if now.duration_since(watch) >= _5_MINS {
|
if now.duration_since(watch) >= _5_MINS {
|
||||||
/* Time to poll all inboxes */
|
/* Time to poll all inboxes */
|
||||||
let mut conn = timeout(Duration::from_secs(3), main_conn.lock()).await?;
|
let mut conn = timeout(uid_store.timeout, main_conn.lock()).await?;
|
||||||
let mailboxes: HashMap<MailboxHash, ImapMailbox> = {
|
let mailboxes: HashMap<MailboxHash, ImapMailbox> = {
|
||||||
let mailboxes_lck =
|
let mailboxes_lck =
|
||||||
timeout(Duration::from_secs(3), uid_store.mailboxes.lock()).await?;
|
timeout(uid_store.timeout, uid_store.mailboxes.lock()).await?;
|
||||||
mailboxes_lck.clone()
|
mailboxes_lck.clone()
|
||||||
};
|
};
|
||||||
for (h, mailbox) in mailboxes {
|
for (h, mailbox) in mailboxes {
|
||||||
|
@ -183,16 +185,6 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
}
|
}
|
||||||
debug!("IDLE connection dropped");
|
debug!("IDLE connection dropped");
|
||||||
let err: &str = blockn.err().unwrap_or("Unknown reason.");
|
let err: &str = blockn.err().unwrap_or("Unknown reason.");
|
||||||
timeout(Duration::from_secs(3), main_conn.lock())
|
|
||||||
.await?
|
|
||||||
.add_refresh_event(RefreshEvent {
|
|
||||||
account_hash: uid_store.account_hash,
|
|
||||||
mailbox_hash,
|
|
||||||
kind: RefreshEventKind::Failure(MeliError::new(format!(
|
|
||||||
"IDLE connection dropped: {}",
|
|
||||||
&err
|
|
||||||
))),
|
|
||||||
});
|
|
||||||
Err(MeliError::new(format!("IDLE connection dropped: {}", err)))
|
Err(MeliError::new(format!("IDLE connection dropped: {}", err)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -191,13 +191,18 @@ pub fn lookup_ipv4(host: &str, port: u16) -> crate::Result<std::net::SocketAddr>
|
||||||
|
|
||||||
use futures::future::{self, Either, Future};
|
use futures::future::{self, Either, Future};
|
||||||
|
|
||||||
pub async fn timeout<O>(dur: std::time::Duration, f: impl Future<Output = O>) -> crate::Result<O> {
|
pub async fn timeout<O>(
|
||||||
|
dur: Option<std::time::Duration>,
|
||||||
|
f: impl Future<Output = O>,
|
||||||
|
) -> crate::Result<O> {
|
||||||
futures::pin_mut!(f);
|
futures::pin_mut!(f);
|
||||||
match future::select(f, smol::Timer::after(dur)).await {
|
if let Some(dur) = dur {
|
||||||
Either::Left((out, _)) => Ok(out),
|
match future::select(f, smol::Timer::after(dur)).await {
|
||||||
Either::Right(_) => {
|
Either::Left((out, _)) => Ok(out),
|
||||||
Err(crate::error::MeliError::new("Timed out.")
|
Either::Right(_) => Err(crate::error::MeliError::new("Timed out.")
|
||||||
.set_kind(crate::error::ErrorKind::Timeout))
|
.set_kind(crate::error::ErrorKind::Timeout)),
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Ok(f.await)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue