1use std::collections::{HashMap, HashSet};
2use std::sync::{Arc, Mutex};
3
4#[derive(Debug, Default)]
6pub struct ResourceTracker {
7 inner: Mutex<HashMap<String, HashSet<String>>>,
8}
9
10impl ResourceTracker {
11 pub fn new() -> Self {
12 Self::default()
13 }
14
15 pub fn record_creation(&self, resource_type: impl Into<String>, id: impl Into<String>) {
16 let resource_key = resource_type.into();
17 let mut guard = self.inner.lock().expect("resource tracker mutex poisoned");
18 let entry = guard.entry(resource_key).or_default();
19 entry.insert(id.into());
20 }
21
22 pub fn record_deletion(&self, resource_type: impl Into<String>, id: impl Into<String>) {
23 let resource_key = resource_type.into();
24 let resource_id = id.into();
25 let mut guard = self.inner.lock().expect("resource tracker mutex poisoned");
26 if let Some(entry) = guard.get_mut(&resource_key) {
27 entry.remove(&resource_id);
28 if entry.is_empty() {
29 guard.remove(&resource_key);
30 }
31 }
32 }
33
34 pub fn outstanding(&self) -> HashMap<String, Vec<String>> {
35 let guard = self.inner.lock().expect("resource tracker mutex poisoned");
36 guard.iter().map(|(key, values)| (key.clone(), values.iter().cloned().collect())).collect()
37 }
38}
39
40pub type ResourceTrackerHandle = Arc<ResourceTracker>;
41
42pub fn new_shared_tracker() -> ResourceTrackerHandle {
43 Arc::new(ResourceTracker::new())
44}