Skip to main content

port_sdk/
tracking.rs

1use std::collections::{HashMap, HashSet};
2use std::sync::{Arc, Mutex};
3
4/// Tracks resources created during tests or manual runs so stragglers can be cleaned up later.
5#[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}