Change debounce time to notify callsite (#726)

* makes debounces a property of calls to notify rather than a global property of the notification manager

* Update appmgr/src/status/mod.rs

Co-authored-by: Aiden McClelland <3732071+dr-bonez@users.noreply.github.com>
This commit is contained in:
Keagan McClelland
2021-10-23 21:49:51 -06:00
committed by Aiden McClelland
parent 17d0f9e533
commit 678fa0731e
5 changed files with 25 additions and 27 deletions

View File

@@ -161,7 +161,7 @@ impl RpcContext {
.await?;
let managers = ManagerMap::default();
let metrics_cache = RwLock::new(None);
let notification_manager = NotificationManager::new(secret_store.clone(), 3600);
let notification_manager = NotificationManager::new(secret_store.clone());
let seed = Arc::new(RpcContextSeed {
bind_rpc: base.bind_rpc.unwrap_or(([127, 0, 0, 1], 5959).into()),
bind_ws: base.bind_ws.unwrap_or(([127, 0, 0, 1], 5960).into()),

View File

@@ -320,6 +320,7 @@ impl Manager {
String::from("Service Crashed"),
format!("The service {} has crashed with the following exit code: {}\nDetails: {}", thread_shared.manifest.id.clone(), e.0, e.1),
NotificationSubtype::General,
Some(900) // 15 minutes
)
.await;
match res {

View File

@@ -151,6 +151,7 @@ pub async fn create(
title,
message,
NotificationSubtype::General,
None,
)
.await
}
@@ -265,14 +266,12 @@ impl NotificationSubtype {
pub struct NotificationManager {
sqlite: SqlitePool,
cache: Mutex<HashMap<(Option<PackageId>, NotificationLevel, String), i64>>,
debounce_interval: u32,
}
impl NotificationManager {
pub fn new(sqlite: SqlitePool, debounce_interval: u32) -> Self {
pub fn new(sqlite: SqlitePool) -> Self {
NotificationManager {
sqlite,
cache: Mutex::new(HashMap::new()),
debounce_interval,
}
}
#[instrument(skip(self, db))]
@@ -284,8 +283,12 @@ impl NotificationManager {
title: String,
message: String,
subtype: NotificationSubtype,
debounce_interval: Option<u32>,
) -> Result<(), Error> {
if !self.should_notify(&package_id, &level, &title).await {
if !self
.should_notify(&package_id, &level, &title, debounce_interval)
.await
{
return Ok(());
}
let mut count = crate::db::DatabaseModel::new()
@@ -310,26 +313,13 @@ impl NotificationManager {
count.save(db).await?;
Ok(())
}
async fn gc(&self) {
let mut guard = self.cache.lock().await;
let mut temp = HashMap::new();
for (k, v) in (*guard).drain() {
if v + self.debounce_interval as i64 > Utc::now().timestamp() {
temp.insert(k, v);
}
}
*guard = temp
}
async fn should_notify(
&self,
package_id: &Option<PackageId>,
level: &NotificationLevel,
title: &String,
debounce_interval: Option<u32>,
) -> bool {
if level == &NotificationLevel::Error {
return true;
}
self.gc().await;
let mut guard = self.cache.lock().await;
let k = (package_id.clone(), level.clone(), title.clone());
let v = (*guard).get(&k);
@@ -338,15 +328,20 @@ impl NotificationManager {
(*guard).insert(k, Utc::now().timestamp());
true
}
Some(t) => {
if t + self.debounce_interval as i64 > Utc::now().timestamp() {
false
} else {
// this path should be very rare due to gc above
(*guard).remove(&k);
Some(last_issued) => match debounce_interval {
None => {
(*guard).insert(k, Utc::now().timestamp());
true
}
}
Some(interval) => {
if last_issued + interval as i64 > Utc::now().timestamp() {
false
} else {
(*guard).insert(k, Utc::now().timestamp());
true
}
}
},
}
}
}

View File

@@ -352,7 +352,8 @@ impl MainStatus {
NotificationLevel::Error,
String::from("Critical Health Check Failed"),
format!("{} was shut down because a health check required for its operation failed\n{}", manifest.title, error),
NotificationSubtype::General
NotificationSubtype::General,
None
)
.await?;
should_stop = true;

View File

@@ -260,6 +260,7 @@ async fn maybe_do_update(ctx: RpcContext) -> Result<Option<Arc<Revision>>, Error
"EmbassyOS Update Failed".to_owned(),
format!("Update was not successful because of {}", e),
NotificationSubtype::General,
None,
)
.await
.expect("")