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