| 271 | } |
| 272 | |
| 273 | pub(super) fn load_agent_rows_parallel( |
| 274 | specs: Vec<AgentLoadSpec<'_>>, |
| 275 | progress: &mut crate::progress::UsageLoadProgress, |
| 276 | ) -> Result<Vec<LoadedAgentRows>> { |
| 277 | for spec in &specs { |
| 278 | progress.start(spec.progress_agent); |
| 279 | } |
| 280 | |
| 281 | thread::scope(|scope| { |
| 282 | let (sender, receiver) = mpsc::channel(); |
| 283 | let mut handles = Vec::with_capacity(specs.len()); |
| 284 | for spec in specs { |
| 285 | let sender = sender.clone(); |
| 286 | handles.push(( |
| 287 | spec.index, |
| 288 | spec.progress_agent, |
| 289 | scope.spawn(move || { |
| 290 | let result = (spec.load)(); |
| 291 | let _ = sender.send((spec.index, spec.agent, spec.progress_agent, result)); |
| 292 | }), |
| 293 | )); |
| 294 | } |
| 295 | drop(sender); |
| 296 | |
| 297 | let mut loaded = Vec::with_capacity(handles.len()); |
| 298 | let mut errors = Vec::new(); |
| 299 | for (index, agent, progress_agent, result) in receiver { |
| 300 | match result { |
| 301 | Ok(agent_rows) => { |
| 302 | progress.succeed(progress_agent); |
| 303 | loaded.push(LoadedAgentRows { |
| 304 | index, |
| 305 | agent, |
| 306 | agent_rows, |
| 307 | }); |
| 308 | } |
| 309 | Err(error) => { |
| 310 | progress.fail(progress_agent); |
| 311 | errors.push((index, error)); |
| 312 | } |
| 313 | } |
| 314 | } |
| 315 | |
| 316 | for (index, progress_agent, handle) in handles { |
| 317 | if handle.join().is_err() { |
| 318 | progress.fail(progress_agent); |
| 319 | errors.push((index, crate::cli_error("agent loader panicked"))); |
| 320 | } |
| 321 | } |
| 322 | |
| 323 | errors.sort_by_key(|(index, _)| *index); |
| 324 | if let Some((_, error)) = errors.into_iter().next() { |
| 325 | return Err(error); |
| 326 | } |
| 327 | |
| 328 | loaded.sort_by_key(|loaded| loaded.index); |
| 329 | Ok(loaded) |
| 330 | }) |