let quota-warning reappear after import, rewarn at 95% (#2702)

* let quota-warning reappear after import

an import removes all device-messages,
including the quota warning.

resetting `Config::QuotaExceeding` makes sure,
the warning reappears soon after import -
otherwise the warning would reappear only after
storage is cleaned up and exceeds again.

* a second quota warning when 95% storage exceeded

* factor out warning-check and add a test for that
This commit is contained in:
bjoern
2021-09-22 12:41:35 +02:00
committed by GitHub
parent 66a5e0743d
commit a5826d6a06
2 changed files with 45 additions and 13 deletions

View File

@@ -2940,6 +2940,8 @@ pub async fn was_device_msg_ever_added(context: &Context, label: &str) -> Result
// no wrong information are shown in the device chat // no wrong information are shown in the device chat
// - deletion in `devmsglabels` makes sure, // - deletion in `devmsglabels` makes sure,
// deleted messages are resetted and useful messages can be added again // deleted messages are resetted and useful messages can be added again
// - we reset the config-option `QuotaExceeding`
// that is used as a helper to drive the corresponding device message.
pub(crate) async fn delete_and_reset_all_device_msgs(context: &Context) -> Result<()> { pub(crate) async fn delete_and_reset_all_device_msgs(context: &Context) -> Result<()> {
context context
.sql .sql
@@ -2952,6 +2954,7 @@ pub(crate) async fn delete_and_reset_all_device_msgs(context: &Context) -> Resul
.sql .sql
.execute("DELETE FROM devmsglabels;", paramsv![]) .execute("DELETE FROM devmsglabels;", paramsv![])
.await?; .await?;
context.set_config(Config::QuotaExceeding, None).await?;
Ok(()) Ok(())
} }

View File

@@ -20,14 +20,17 @@ use crate::{job, stock_str, EventType};
/// quota icon is "yellow". /// quota icon is "yellow".
pub const QUOTA_WARN_THRESHOLD_PERCENTAGE: u64 = 80; pub const QUOTA_WARN_THRESHOLD_PERCENTAGE: u64 = 80;
// warning is already issued at QUOTA_WARN_THRESHOLD_PERCENTAGE, // warning again after this usage percentage is reached,
// this threshold only makes the quota icon "red". // quota icon is "red".
pub const QUOTA_ERROR_THRESHOLD_PERCENTAGE: u64 = 99; pub const QUOTA_ERROR_THRESHOLD_PERCENTAGE: u64 = 95;
/// if quota is below this value (again), /// if quota is below this value (again),
/// QuotaExceeding is cleared. /// QuotaExceeding is cleared.
/// This value should be a bit below QUOTA_WARN_THRESHOLD_PERCENTAGE to /// This value should be a bit below QUOTA_WARN_THRESHOLD_PERCENTAGE to
/// avoid jittering and lots of warnings when quota is exactly at the warning threshold. /// avoid jittering and lots of warnings when quota is exactly at the warning threshold.
///
/// We do not repeat warnings on a daily base or so as some provider
/// providers report bad values and we would then spam the user.
pub const QUOTA_ALLCLEAR_PERCENTAGE: u64 = 75; pub const QUOTA_ALLCLEAR_PERCENTAGE: u64 = 75;
// if recent quota is older, // if recent quota is older,
@@ -96,6 +99,14 @@ fn get_highest_usage<'t>(
highest.ok_or_else(|| anyhow!("no quota_resource found, this is unexpected")) highest.ok_or_else(|| anyhow!("no quota_resource found, this is unexpected"))
} }
/// Checks if a quota warning is needed.
pub fn needs_quota_warning(curr_percentage: u64, warned_at_percentage: u64) -> bool {
(curr_percentage >= QUOTA_WARN_THRESHOLD_PERCENTAGE
&& warned_at_percentage < QUOTA_WARN_THRESHOLD_PERCENTAGE)
|| (curr_percentage >= QUOTA_ERROR_THRESHOLD_PERCENTAGE
&& warned_at_percentage < QUOTA_ERROR_THRESHOLD_PERCENTAGE)
}
impl Context { impl Context {
// Adds a job to update `quota.recent` // Adds a job to update `quota.recent`
pub(crate) async fn schedule_quota_update(&self) -> Result<()> { pub(crate) async fn schedule_quota_update(&self) -> Result<()> {
@@ -134,16 +145,15 @@ impl Context {
if let Ok(quota) = &quota { if let Ok(quota) = &quota {
match get_highest_usage(quota) { match get_highest_usage(quota) {
Ok((highest, _, _)) => { Ok((highest, _, _)) => {
if highest >= QUOTA_WARN_THRESHOLD_PERCENTAGE { if needs_quota_warning(
if self.get_config_int(Config::QuotaExceeding).await? == 0 { highest,
self.set_config(Config::QuotaExceeding, Some(&highest.to_string())) self.get_config_int(Config::QuotaExceeding).await? as u64,
.await?; ) {
self.set_config(Config::QuotaExceeding, Some(&highest.to_string()))
let mut msg = Message::new(Viewtype::Text); .await?;
msg.text = Some(stock_str::quota_exceeding(self, highest).await); let mut msg = Message::new(Viewtype::Text);
add_device_msg_with_importance(self, None, Some(&mut msg), true) msg.text = Some(stock_str::quota_exceeding(self, highest).await);
.await?; add_device_msg_with_importance(self, None, Some(&mut msg), true).await?;
}
} else if highest <= QUOTA_ALLCLEAR_PERCENTAGE { } else if highest <= QUOTA_ALLCLEAR_PERCENTAGE {
self.set_config(Config::QuotaExceeding, None).await?; self.set_config(Config::QuotaExceeding, None).await?;
} }
@@ -164,11 +174,30 @@ impl Context {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
use crate::quota::{ use crate::quota::{
QUOTA_ALLCLEAR_PERCENTAGE, QUOTA_ERROR_THRESHOLD_PERCENTAGE, QUOTA_ALLCLEAR_PERCENTAGE, QUOTA_ERROR_THRESHOLD_PERCENTAGE,
QUOTA_WARN_THRESHOLD_PERCENTAGE, QUOTA_WARN_THRESHOLD_PERCENTAGE,
}; };
#[async_std::test]
async fn test_needs_quota_warning() -> Result<()> {
assert!(!needs_quota_warning(0, 0));
assert!(!needs_quota_warning(10, 0));
assert!(!needs_quota_warning(70, 0));
assert!(!needs_quota_warning(75, 0));
assert!(!needs_quota_warning(79, 0));
assert!(needs_quota_warning(80, 0));
assert!(needs_quota_warning(81, 0));
assert!(!needs_quota_warning(85, 80));
assert!(!needs_quota_warning(85, 81));
assert!(needs_quota_warning(95, 82));
assert!(!needs_quota_warning(97, 95));
assert!(!needs_quota_warning(97, 96));
assert!(!needs_quota_warning(1000, 96));
Ok(())
}
#[allow(clippy::assertions_on_constants)] #[allow(clippy::assertions_on_constants)]
#[async_std::test] #[async_std::test]
async fn test_quota_thresholds() -> anyhow::Result<()> { async fn test_quota_thresholds() -> anyhow::Result<()> {