perf: batch Wikidata SPARQL queries per film instead of per actor

Use a VALUES clause to fetch awards for all actors of a film in a
single SPARQL request, reducing Wikidata API calls from ~20 per film
to 1 and avoiding idle timeout errors from rate limiting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
thibaud-leclere
2026-04-01 20:37:13 +02:00
parent 369893a77e
commit 116d7b409e
4 changed files with 119 additions and 46 deletions

View File

@@ -23,15 +23,25 @@ readonly class AwardImporter
public function importForActor(Actor $actor): void
{
if ($actor->isAwardsImported()) {
$this->importForActors([$actor]);
}
/**
* @param list<Actor> $actors
*/
public function importForActors(array $actors): void
{
$actorsToFetch = array_filter($actors, fn (Actor $a) => !$a->isAwardsImported());
if ([] === $actorsToFetch) {
return;
}
try {
$wikidataAwards = $this->wikidataGateway->getAwards($actor);
$allAwards = $this->wikidataGateway->getAwardsForActors(array_values($actorsToFetch));
} catch (\Throwable $e) {
$this->logger?->warning('Failed to fetch awards from Wikidata', [
'actor' => $actor->getName(),
'actors' => array_map(fn (Actor $a) => $a->getName(), $actorsToFetch),
'error' => $e->getMessage(),
]);
@@ -40,19 +50,23 @@ readonly class AwardImporter
$knownTypes = $this->awardTypeRepository->findAll();
foreach ($wikidataAwards as $wikidataAward) {
$awardType = $this->resolveAwardType($wikidataAward['name'], $knownTypes);
foreach ($actorsToFetch as $actor) {
$wikidataAwards = $allAwards[$actor->getName()] ?? [];
$award = new Award();
$award->setName($wikidataAward['name']);
$award->setYear($wikidataAward['year']);
$award->setActor($actor);
$award->setAwardType($awardType);
foreach ($wikidataAwards as $wikidataAward) {
$awardType = $this->resolveAwardType($wikidataAward['name'], $knownTypes);
$this->em->persist($award);
$award = new Award();
$award->setName($wikidataAward['name']);
$award->setYear($wikidataAward['year']);
$award->setActor($actor);
$award->setAwardType($awardType);
$this->em->persist($award);
}
$actor->setAwardsImported(true);
}
$actor->setAwardsImported(true);
}
/**