perf(agent): paralléliser les sondes de DetectProfiles::execute (#31)

Les sondes de détection de profils étaient exécutées séquentiellement, portant
le coût total au pire à N×800 ms (N × timeout par candidat).

Chaque candidat est désormais sondé dans une tâche Tokio dédiée (tokio::spawn),
les JoinHandle étant attendus dans l'ordre de création : le coût total tombe à
~1×timeout tout en préservant un ordre de sortie déterministe. Aucune dépendance
ajoutée, aucun changement de contrat.

Test : crates/application/tests/profile_usecases.rs (concurrence multi-thread +
ordre déterministe). profile_usecases 20/20, suite application verte.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 19:31:57 +02:00
parent 51b5d07f35
commit 2d7396a86b
2 changed files with 91 additions and 2 deletions

View File

@ -74,9 +74,18 @@ impl DetectProfiles {
input: DetectProfilesInput,
) -> Result<DetectProfilesOutput, AppError> {
let mut results = Vec::with_capacity(input.candidates.len());
let mut probes = Vec::with_capacity(input.candidates.len());
for profile in input.candidates {
let available = self.runtime.detect(&profile).await.unwrap_or(false);
results.push(ProfileAvailability { profile, available });
let runtime = Arc::clone(&self.runtime);
probes.push(tokio::spawn(async move {
let available = runtime.detect(&profile).await.unwrap_or(false);
ProfileAvailability { profile, available }
}));
}
for probe in probes {
results.push(probe.await.map_err(|err| {
AppError::Process(format!("profile detection task failed: {err}"))
})?);
}
Ok(DetectProfilesOutput { results })
}