batch_mode_batch_workspace_interface/
mock.rs1crate::ix!();
3
4#[derive(NamedItem,Debug, Clone)]
7pub struct MockItem {
8 pub name: String,
9}
10
11#[derive(Clone,Getters,Setters,Builder,Debug)]
12#[builder(setter(strip_option))]
13#[getset(get = "pub", set = "pub")]
14pub struct MockBatchWorkspace {
15 #[builder(default = "Arc::new(tempfile::tempdir().expect(\"Failed to create temp directory\"))")]
18 ephemeral_dir: Arc<tempfile::TempDir>,
19
20 #[builder(default = "PathBuf::from(\"mock_done_dir\")")]
23 done_dir: PathBuf,
24
25 #[builder(default = "PathBuf::from(\"mock_failed_json_repairs_dir\")")]
26 failed_json_repairs_dir: PathBuf,
27
28 #[builder(default = "PathBuf::from(\"mock_failed_items_dir\")")]
29 failed_items_dir: PathBuf,
30
31 #[builder(default = "PathBuf::from(\"mock_workdir\")")]
32 workdir: PathBuf,
33
34 #[builder(default = "\"text_storage_prefix\".to_string()")]
35 text_storage_prefix: String,
36
37 #[builder(default)]
38 input_ids: Vec<String>,
39
40 #[builder(default)]
41 output_ids: Vec<String>,
42
43 #[builder(default)]
44 error_ids: Vec<String>,
45
46 #[builder(default = "PathBuf::new()")]
50 ephemeral_done_dir: PathBuf,
51}
52
53#[async_trait]
54impl LoadSeedByCustomId for MockBatchWorkspace {
55 async fn load_seed_by_custom_id(
56 &self,
57 custom_id: &CustomRequestId,
58 ) -> Result<Box<dyn Named + Send + Sync>, BatchWorkspaceError> {
59 #[derive(Debug)]
61 struct Dummy(String);
62 impl Named for Dummy {
63 fn name(&self) -> std::borrow::Cow<'_, str> {
64 std::borrow::Cow::Borrowed(&self.0)
65 }
66 }
67 Ok(Box::new(Dummy(custom_id.as_str().to_owned())))
68 }
69}
70
71impl Default for MockBatchWorkspace {
72 fn default() -> Self {
73 let temp = tempfile::tempdir().expect("Could not create temp directory for MockBatchWorkspace");
74 info!("Created ephemeral directory for MockBatchWorkspace at: {:?}", temp.path());
75
76 let done_dir_path = temp.path().join("mock_done_dir");
79 if let Err(e) = std::fs::create_dir_all(&done_dir_path) {
80 warn!("Could not create ephemeral done directory: {} — continuing anyway", e);
81 }
82
83 Self {
84 ephemeral_dir: temp.into(),
85 done_dir: PathBuf::from("mock_done_dir"),
86 failed_json_repairs_dir: PathBuf::from("mock_failed_json_repairs_dir"),
87 failed_items_dir: PathBuf::from("mock_failed_items_dir"),
88 workdir: PathBuf::from("mock_workdir"),
89 text_storage_prefix: "text_storage_prefix".to_string(),
90 input_ids: vec![],
91 output_ids: vec![],
92 error_ids: vec![],
93 ephemeral_done_dir: done_dir_path,
94 }
95 }
96}
97
98impl GetInputFilenameAtIndex for MockBatchWorkspace {
99 fn input_filename(&self, batch_idx: &BatchIndex) -> PathBuf {
100 let path = self
101 .ephemeral_dir
102 .path()
103 .join(format!("mock_input_{}.json", batch_idx));
104 trace!("Returning ephemeral input filename for batch {:?}: {:?}", batch_idx, path);
105 path
106 }
107}
108
109impl GetOutputFilenameAtIndex for MockBatchWorkspace {
110 fn output_filename(&self, batch_idx: &BatchIndex) -> PathBuf {
111 let path = self
112 .ephemeral_dir
113 .path()
114 .join(format!("mock_output_{}.json", batch_idx));
115 trace!("Returning ephemeral output filename for batch {:?}: {:?}", batch_idx, path);
116 path
117 }
118}
119
120impl GetErrorFilenameAtIndex for MockBatchWorkspace {
121 fn error_filename(&self, batch_idx: &BatchIndex) -> PathBuf {
122 let path = self
123 .ephemeral_dir
124 .path()
125 .join(format!("mock_error_{}.json", batch_idx));
126 trace!("Returning ephemeral error filename for batch {:?}: {:?}", batch_idx, path);
127 path
128 }
129}
130
131impl GetMetadataFilenameAtIndex for MockBatchWorkspace {
132 fn metadata_filename(&self, batch_idx: &BatchIndex) -> PathBuf {
133 let path = self
134 .ephemeral_dir
135 .path()
136 .join(format!("mock_metadata_{}.json", batch_idx));
137 trace!("Returning ephemeral metadata filename for batch {:?}: {:?}", batch_idx, path);
138 path
139 }
140}
141
142impl GetSeedManifestFilenameAtIndex for MockBatchWorkspace {
143 fn seed_manifest_filename(&self, batch_idx: &BatchIndex) -> PathBuf {
144 let path = self
145 .ephemeral_dir
146 .path()
147 .join(format!("mock_seed_manifest_{}.json", batch_idx));
148 trace!("Returning ephemeral seed_manifest filename for batch {:?}: {:?}", batch_idx, path);
149 path
150 }
151}
152
153impl GetDoneDirectory for MockBatchWorkspace {
154 fn get_done_directory(&self) -> &PathBuf {
155 trace!(
156 "Returning ephemeral done directory for mock workspace: {:?}",
157 self.ephemeral_done_dir
158 );
159 &self.ephemeral_done_dir
160 }
161}
162
163impl GetFailedJsonRepairsDir for MockBatchWorkspace {
164 fn failed_json_repairs_dir(&self) -> PathBuf {
165 let path = self.ephemeral_dir.path().join(&self.failed_json_repairs_dir);
166 trace!("Returning ephemeral failed_json_repairs_dir: {:?}", path);
167 if let Err(e) = std::fs::create_dir_all(&path) {
168 warn!("Could not create ephemeral failed_json_repairs_dir: {} — continuing anyway", e);
169 }
170 path
171 }
172}
173
174impl GetFailedItemsDir for MockBatchWorkspace {
175 fn failed_items_dir(&self) -> PathBuf {
176 let path = self.ephemeral_dir.path().join(&self.failed_items_dir);
177 trace!("Returning ephemeral failed_items_dir: {:?}", path);
178 if let Err(e) = std::fs::create_dir_all(&path) {
179 warn!("Could not create ephemeral failed_items_dir: {} — continuing anyway", e);
180 }
181 path
182 }
183}
184
185impl GetTextStoragePath for MockBatchWorkspace {
186 fn text_storage_path(&self, batch_idx: &BatchIndex) -> PathBuf {
187 let path = if self.text_storage_prefix.is_empty() {
188 self.ephemeral_dir
189 .path()
190 .join(format!("text_storage_{}.txt", batch_idx))
191 } else {
192 self.ephemeral_dir
193 .path()
194 .join(&self.text_storage_prefix)
195 .join(format!("text_storage_{}.txt", batch_idx))
196 };
197 trace!("Returning ephemeral text storage path for batch {:?}: {:?}", batch_idx, path);
198 if let Some(parent) = path.parent() {
199 if let Err(e) = std::fs::create_dir_all(parent) {
200 warn!("Could not create parent dir for text storage: {} — continuing anyway", e);
201 }
202 }
203 path
204 }
205}
206
207impl GetWorkdir for MockBatchWorkspace {
208 fn workdir(&self) -> PathBuf {
209 let path = self.ephemeral_dir.path().join(&self.workdir);
210 trace!("Returning ephemeral workdir: {:?}", path);
211 if let Err(e) = std::fs::create_dir_all(&path) {
212 warn!("Could not create ephemeral workdir: {} — continuing anyway", e);
213 }
214 path
215 }
216}
217
218impl GetTargetPath for MockBatchWorkspace {
219 type Item = Arc<dyn GetTargetPathForAIExpansion + Send + Sync + 'static>;
220
221 fn target_path(
222 &self,
223 item: &Self::Item,
224 expected_content_type: &ExpectedContentType
225 ) -> PathBuf {
226 let subdir = match expected_content_type {
227 ExpectedContentType::Json => "json_output",
228 ExpectedContentType::PlainText => "text_output",
229 ExpectedContentType::JsonLines => "json_lines_output",
230 };
231 let base = self.workdir().join(subdir);
232 trace!("Constructing ephemeral target path for subdir {:?} and item", base);
233 item.target_path_for_ai_json_expansion(base.as_path(), expected_content_type)
234 }
235}
236
237#[async_trait]
238impl BatchWorkspaceInterface for MockBatchWorkspace {}
239
240impl GetTargetDir for MockBatchWorkspace {
241
242 fn get_target_dir(&self) -> PathBuf {
243 todo!()
244 }
245}
246
247#[cfg(test)]
248mod test_mock_workspace_ephemeral {
249 use super::*;
250
251 #[traced_test]
252 fn test_ephemeral_cleanup() {
253 let ephemeral_done: PathBuf;
254 {
255 let workspace = MockBatchWorkspace::default();
256 ephemeral_done = workspace.get_done_directory().to_path_buf();
257 assert!(
258 !ephemeral_done.as_os_str().is_empty(),
259 "Ephemeral done directory path should not be empty."
260 );
261 assert!(
263 ephemeral_done.exists(),
264 "Expected ephemeral directory to exist."
265 );
266 }
267 assert!(
270 !ephemeral_done.exists(),
271 "Ephemeral directory should have been cleaned up."
272 );
273 }
274
275 #[traced_test]
276 fn test_mock_workspace_interface() {
277 let w = MockBatchWorkspace::default();
278 let done = w.get_done_directory();
280 let fail_json = w.failed_json_repairs_dir();
281 let fail_items = w.failed_items_dir();
282 let input = w.input_filename(&BatchIndex::from(0));
283 let output = w.output_filename(&BatchIndex::from(1));
284 let error = w.error_filename(&BatchIndex::from(2));
285 let meta = w.metadata_filename(&BatchIndex::from(3));
286 let text = w.text_storage_path(&BatchIndex::from(4));
287 let wd = w.workdir();
288
289 assert!(!done.as_os_str().is_empty());
290 assert!(!fail_json.as_os_str().is_empty());
291 assert!(!fail_items.as_os_str().is_empty());
292 assert!(!input.as_os_str().is_empty());
293 assert!(!output.as_os_str().is_empty());
294 assert!(!error.as_os_str().is_empty());
295 assert!(!meta.as_os_str().is_empty());
296 assert!(!text.as_os_str().is_empty());
297 assert!(!wd.as_os_str().is_empty());
298 }
299}