mirror of
https://github.com/chatmail/core.git
synced 2026-04-27 18:36:30 +03:00
fix: do not interrupt IMAP loop from get_connectivity_html()
Android calls get_connectivity_html() every time connectivity changes, which in turn interrupts IMAP loop and triggers change from "not connected" to "connecting" state. To avoid such infinite loop of IMAP interrupts when there is not connectivity, update quota only when IMAP loop is interrupted otherwise. This anyway happens when a message is received or maybe_network is called. Also remove outdated comments about `Action::UpdateRecentQuota` job which does not exist anymore.
This commit is contained in:
@@ -211,9 +211,6 @@ pub struct InnerContext {
|
||||
/// Set to `None` if quota was never tried to load.
|
||||
pub(crate) quota: RwLock<Option<QuotaInfo>>,
|
||||
|
||||
/// Set to true if quota update is requested.
|
||||
pub(crate) quota_update_request: AtomicBool,
|
||||
|
||||
/// IMAP UID resync request.
|
||||
pub(crate) resync_request: AtomicBool,
|
||||
|
||||
@@ -384,7 +381,6 @@ impl Context {
|
||||
scheduler: SchedulerState::new(),
|
||||
ratelimit: RwLock::new(Ratelimit::new(Duration::new(60, 0), 6.0)), // Allow at least 1 message every 10 seconds + a burst of 6.
|
||||
quota: RwLock::new(None),
|
||||
quota_update_request: AtomicBool::new(false),
|
||||
resync_request: AtomicBool::new(false),
|
||||
new_msgs_notify,
|
||||
server_id: RwLock::new(None),
|
||||
|
||||
24
src/quota.rs
24
src/quota.rs
@@ -1,7 +1,6 @@
|
||||
//! # Support for IMAP QUOTA extension.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use anyhow::{anyhow, Context as _, Result};
|
||||
use async_imap::types::{Quota, QuotaResource};
|
||||
@@ -13,7 +12,6 @@ use crate::imap::scan_folders::get_watched_folders;
|
||||
use crate::imap::session::Session as ImapSession;
|
||||
use crate::imap::Imap;
|
||||
use crate::message::{Message, Viewtype};
|
||||
use crate::scheduler::InterruptInfo;
|
||||
use crate::tools::time;
|
||||
use crate::{stock_str, EventType};
|
||||
|
||||
@@ -34,17 +32,12 @@ pub const QUOTA_ERROR_THRESHOLD_PERCENTAGE: u64 = 95;
|
||||
/// providers report bad values and we would then spam the user.
|
||||
pub const QUOTA_ALLCLEAR_PERCENTAGE: u64 = 75;
|
||||
|
||||
/// if recent quota is older,
|
||||
/// it is re-fetched on dc_get_connectivity_html()
|
||||
pub const QUOTA_MAX_AGE_SECONDS: i64 = 60;
|
||||
|
||||
/// Server quota information with an update timestamp.
|
||||
#[derive(Debug)]
|
||||
pub struct QuotaInfo {
|
||||
/// Recently loaded quota information.
|
||||
/// set to `Err()` if the provider does not support quota or on other errors,
|
||||
/// set to `Ok()` for valid quota information.
|
||||
/// Updated by `Action::UpdateRecentQuota`
|
||||
pub(crate) recent: Result<BTreeMap<String, Vec<QuotaResource>>>,
|
||||
|
||||
/// Timestamp when structure was modified.
|
||||
@@ -110,18 +103,6 @@ pub fn needs_quota_warning(curr_percentage: u64, warned_at_percentage: u64) -> b
|
||||
}
|
||||
|
||||
impl Context {
|
||||
// Adds a job to update `quota.recent`
|
||||
pub(crate) async fn schedule_quota_update(&self) -> Result<()> {
|
||||
let requested = self.quota_update_request.swap(true, Ordering::Relaxed);
|
||||
if !requested {
|
||||
// Quota update was not requested before.
|
||||
self.scheduler
|
||||
.interrupt_inbox(InterruptInfo::new(false))
|
||||
.await;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Updates `quota.recent`, sets `quota.modified` to the current time
|
||||
/// and emits an event to let the UIs update connectivity view.
|
||||
///
|
||||
@@ -130,8 +111,6 @@ impl Context {
|
||||
/// As the message is added only once, the user is not spammed
|
||||
/// in case for some providers the quota is always at ~100%
|
||||
/// and new space is allocated as needed.
|
||||
///
|
||||
/// Called in response to `Action::UpdateRecentQuota`.
|
||||
pub(crate) async fn update_recent_quota(&self, imap: &mut Imap) -> Result<()> {
|
||||
if let Err(err) = imap.prepare(self).await {
|
||||
warn!(self, "could not connect: {:#}", err);
|
||||
@@ -166,9 +145,6 @@ impl Context {
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the request to update quota.
|
||||
self.quota_update_request.store(false, Ordering::Relaxed);
|
||||
|
||||
*self.quota.write().await = Some(QuotaInfo {
|
||||
recent: quota,
|
||||
modified: time(),
|
||||
|
||||
@@ -360,10 +360,20 @@ async fn inbox_loop(
|
||||
info = Default::default();
|
||||
}
|
||||
None => {
|
||||
let quota_requested = ctx.quota_update_request.swap(false, Ordering::Relaxed);
|
||||
if quota_requested {
|
||||
if let Err(err) = ctx.update_recent_quota(&mut connection).await {
|
||||
warn!(ctx, "Failed to update quota: {:#}.", err);
|
||||
{
|
||||
// Update quota no more than once a minute.
|
||||
let quota_needs_update = {
|
||||
let quota = ctx.quota.read().await;
|
||||
quota
|
||||
.as_ref()
|
||||
.filter(|quota| quota.modified + 60 > time())
|
||||
.is_none()
|
||||
};
|
||||
|
||||
if quota_needs_update {
|
||||
if let Err(err) = ctx.update_recent_quota(&mut connection).await {
|
||||
warn!(ctx, "Failed to update quota: {:#}.", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,7 @@ use tokio::sync::Mutex;
|
||||
|
||||
use crate::events::EventType;
|
||||
use crate::imap::{scan_folders::get_watched_folder_configs, FolderMeaning};
|
||||
use crate::quota::{
|
||||
QUOTA_ERROR_THRESHOLD_PERCENTAGE, QUOTA_MAX_AGE_SECONDS, QUOTA_WARN_THRESHOLD_PERCENTAGE,
|
||||
};
|
||||
use crate::tools::time;
|
||||
use crate::quota::{QUOTA_ERROR_THRESHOLD_PERCENTAGE, QUOTA_WARN_THRESHOLD_PERCENTAGE};
|
||||
use crate::{context::Context, log::LogExt};
|
||||
use crate::{stock_str, tools};
|
||||
|
||||
@@ -472,14 +469,9 @@ impl Context {
|
||||
ret += format!("<li>{e}</li>").as_str();
|
||||
}
|
||||
}
|
||||
|
||||
if quota.modified + QUOTA_MAX_AGE_SECONDS < time() {
|
||||
self.schedule_quota_update().await?;
|
||||
}
|
||||
} else {
|
||||
let not_connected = stock_str::not_connected(self).await;
|
||||
ret += &format!("<li>{not_connected}</li>");
|
||||
self.schedule_quota_update().await?;
|
||||
}
|
||||
ret += "</ul>";
|
||||
|
||||
|
||||
@@ -742,8 +742,6 @@ pub async fn housekeeping(context: &Context) -> Result<()> {
|
||||
warn!(context, "Failed to deduplicate peerstates: {:#}.", err)
|
||||
}
|
||||
|
||||
context.schedule_quota_update().await?;
|
||||
|
||||
// Try to clear the freelist to free some space on the disk. This
|
||||
// only works if auto_vacuum is enabled.
|
||||
match context
|
||||
|
||||
Reference in New Issue
Block a user