aster_forge_tasks/
temp.rs1use crate::{Result, TaskCoreError, TaskLease};
8
9pub async fn cleanup_temp_dir(path: &str) {
14 aster_forge_utils::fs::cleanup_temp_dir(path).await;
15}
16
17pub async fn cleanup_runtime_temp_root(temp_root: &str) {
19 aster_forge_utils::fs::cleanup_runtime_temp_root(temp_root).await;
20}
21
22pub async fn prepare_task_temp_dir_in_root(temp_root: &str, lease: TaskLease) -> Result<String> {
24 tracing::debug!(
25 task_id = lease.task_id,
26 processing_token = lease.processing_token,
27 "preparing background task temp dir"
28 );
29 cleanup_task_temp_dir_for_lease_in_root(temp_root, lease).await?;
30 let task_temp_dir = aster_forge_utils::paths::task_token_temp_dir(
31 temp_root,
32 lease.task_id,
33 lease.processing_token,
34 );
35 tokio::fs::create_dir_all(&task_temp_dir)
36 .await
37 .map_err(|error| TaskCoreError::io(format!("create task temp dir: {error}")))?;
38 tracing::debug!(
39 task_id = lease.task_id,
40 processing_token = lease.processing_token,
41 "prepared background task temp dir"
42 );
43 Ok(task_temp_dir)
44}
45
46pub async fn cleanup_task_temp_dir_for_lease_in_root(
48 temp_root: &str,
49 lease: TaskLease,
50) -> Result<()> {
51 tracing::debug!(
52 task_id = lease.task_id,
53 processing_token = lease.processing_token,
54 "cleaning background task temp dir for lease"
55 );
56 cleanup_temp_dir(&aster_forge_utils::paths::task_token_temp_dir(
57 temp_root,
58 lease.task_id,
59 lease.processing_token,
60 ))
61 .await;
62 Ok(())
63}
64
65pub async fn cleanup_task_temp_dir_for_task_in_root(temp_root: &str, task_id: i64) -> Result<()> {
67 tracing::debug!(task_id, "cleaning background task temp dir in root");
68 cleanup_temp_dir(&aster_forge_utils::paths::task_temp_dir(temp_root, task_id)).await;
69 Ok(())
70}
71
72#[cfg(test)]
73mod tests {
74 use std::path::PathBuf;
75 use std::sync::atomic::{AtomicU64, Ordering};
76
77 use crate::TaskLease;
78
79 use super::{
80 cleanup_runtime_temp_root, cleanup_task_temp_dir_for_lease_in_root,
81 cleanup_task_temp_dir_for_task_in_root, cleanup_temp_dir, prepare_task_temp_dir_in_root,
82 };
83
84 static TEMP_ID: AtomicU64 = AtomicU64::new(0);
85
86 fn unique_temp_path(label: &str) -> PathBuf {
87 std::env::temp_dir().join(format!(
88 "aster-forge-tasks-{label}-{}-{}",
89 std::process::id(),
90 TEMP_ID.fetch_add(1, Ordering::Relaxed)
91 ))
92 }
93
94 #[tokio::test]
95 async fn cleanup_temp_dir_removes_directory_tree() {
96 let path = unique_temp_path("cleanup");
97 let nested = path.join("nested");
98 tokio::fs::create_dir_all(&nested).await.unwrap();
99 tokio::fs::write(nested.join("payload.txt"), b"temporary")
100 .await
101 .unwrap();
102
103 cleanup_temp_dir(path.to_str().unwrap()).await;
104
105 assert!(!path.exists());
106 }
107
108 #[tokio::test]
109 async fn cleanup_temp_dir_tolerates_missing_directory() {
110 let path = unique_temp_path("missing-cleanup");
111
112 cleanup_temp_dir(path.to_str().unwrap()).await;
113
114 assert!(!path.exists());
115 }
116
117 #[tokio::test]
118 async fn prepare_task_temp_dir_creates_token_scoped_directory() {
119 let root = unique_temp_path("prepare");
120 let lease = TaskLease::new(42, 7);
121
122 let prepared = prepare_task_temp_dir_in_root(root.to_str().unwrap(), lease)
123 .await
124 .expect("task temp dir should be prepared");
125
126 assert!(PathBuf::from(&prepared).is_dir());
127 cleanup_temp_dir(root.to_str().unwrap()).await;
128 }
129
130 #[tokio::test]
131 async fn cleanup_task_temp_dir_for_lease_removes_only_token_dir() {
132 let root = unique_temp_path("lease-cleanup");
133 let lease = TaskLease::new(42, 7);
134 let keep = aster_forge_utils::paths::task_token_temp_dir(root.to_str().unwrap(), 42, 8);
135 let remove = prepare_task_temp_dir_in_root(root.to_str().unwrap(), lease)
136 .await
137 .expect("task temp dir should be prepared");
138 tokio::fs::create_dir_all(&keep).await.unwrap();
139
140 cleanup_task_temp_dir_for_lease_in_root(root.to_str().unwrap(), lease)
141 .await
142 .expect("lease cleanup should succeed");
143
144 assert!(!PathBuf::from(remove).exists());
145 assert!(PathBuf::from(&keep).is_dir());
146 cleanup_temp_dir(root.to_str().unwrap()).await;
147 }
148
149 #[tokio::test]
150 async fn cleanup_task_temp_dir_for_task_removes_all_token_dirs() {
151 let root = unique_temp_path("task-cleanup");
152 let lease = TaskLease::new(42, 7);
153 prepare_task_temp_dir_in_root(root.to_str().unwrap(), lease)
154 .await
155 .expect("task temp dir should be prepared");
156
157 cleanup_task_temp_dir_for_task_in_root(root.to_str().unwrap(), 42)
158 .await
159 .expect("task cleanup should succeed");
160
161 assert!(
162 !PathBuf::from(aster_forge_utils::paths::task_temp_dir(
163 root.to_str().unwrap(),
164 42
165 ))
166 .exists()
167 );
168 cleanup_temp_dir(root.to_str().unwrap()).await;
169 }
170
171 #[tokio::test]
172 async fn cleanup_runtime_temp_root_removes_runtime_namespace_only() {
173 let root = unique_temp_path("runtime-cleanup");
174 let runtime = aster_forge_utils::paths::runtime_temp_dir(root.to_str().unwrap());
175 let keep = root.join("tasks");
176 tokio::fs::create_dir_all(&runtime).await.unwrap();
177 tokio::fs::create_dir_all(&keep).await.unwrap();
178
179 cleanup_runtime_temp_root(root.to_str().unwrap()).await;
180
181 assert!(!PathBuf::from(runtime).exists());
182 assert!(keep.is_dir());
183 cleanup_temp_dir(root.to_str().unwrap()).await;
184 }
185}