* BatchDestroyDeployment

* periphery image pull api

* Add Pull apis

* Add PullStack / PullDeployment

* improve init deploy from container

* stacks + deployments update_available source

* Fix deploy / destroy stack service

* updates available indicator

* add poll for updates and auto update options

* use interval to handle waiting between resource refresh

* stack auto update deploy whole stack

* format

* clean up the docs

* update available alerts

* update alerting format

* fix most clippy
This commit is contained in:
Maxwell Becker
2024-11-04 20:28:31 -08:00
committed by GitHub
parent 97ced3b2cb
commit aea5441466
90 changed files with 2413 additions and 677 deletions

12
lib/cache/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,12 @@
[package]
name = "cache"
version.workspace = true
edition.workspace = true
authors.workspace = true
license.workspace = true
repository.workspace = true
homepage.workspace = true
[dependencies]
anyhow.workspace = true
tokio.workspace = true

67
lib/cache/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,67 @@
use std::{collections::HashMap, hash::Hash, sync::Arc};
use tokio::sync::Mutex;
/// Prevents simultaneous / rapid fire access to an action,
/// returning the cached result instead in these situations.
#[derive(Default)]
pub struct TimeoutCache<K, Res>(
Mutex<HashMap<K, Arc<Mutex<CacheEntry<Res>>>>>,
);
impl<K: Eq + Hash, Res: Default> TimeoutCache<K, Res> {
pub async fn get_lock(
&self,
key: K,
) -> Arc<Mutex<CacheEntry<Res>>> {
let mut lock = self.0.lock().await;
lock.entry(key).or_default().clone()
}
}
pub struct CacheEntry<Res> {
/// The last cached ts
pub last_ts: i64,
/// The last cached result
pub res: anyhow::Result<Res>,
}
impl<Res: Default> Default for CacheEntry<Res> {
fn default() -> Self {
CacheEntry {
last_ts: 0,
res: Ok(Res::default()),
}
}
}
impl<Res: Clone> CacheEntry<Res> {
pub fn set(&mut self, res: &anyhow::Result<Res>, timestamp: i64) {
self.res = res
.as_ref()
.map(|res| res.clone())
.map_err(clone_anyhow_error);
self.last_ts = timestamp;
}
pub fn clone_res(&self) -> anyhow::Result<Res> {
self
.res
.as_ref()
.map(|res| res.clone())
.map_err(clone_anyhow_error)
}
}
fn clone_anyhow_error(e: &anyhow::Error) -> anyhow::Error {
let mut reasons =
e.chain().map(|e| e.to_string()).collect::<Vec<_>>();
// Always guaranteed to be at least one reason
// Need to start the chain with the last reason
let mut e = anyhow::Error::msg(reasons.pop().unwrap());
// Need to reverse reason application from lowest context to highest context.
for reason in reasons.into_iter().rev() {
e = e.context(reason)
}
e
}