perf: prevent N+1 on watchlist fetch

This commit is contained in:
vinceh121
2025-11-02 03:12:46 +01:00
parent a1aec6b463
commit 0739ef5ca9
4 changed files with 45 additions and 19 deletions

View File

@@ -11,7 +11,6 @@ use App\Repository\DomainRepository;
use App\Repository\WatchlistRepository;
use App\Service\CalendarService;
use App\Service\RDAPService;
use Doctrine\Common\Collections\Collection;
use Eluceo\iCal\Domain\Entity\Calendar;
use Eluceo\iCal\Presentation\Component\Property;
use Eluceo\iCal\Presentation\Component\Property\Value\TextValue;
@@ -36,23 +35,6 @@ class WatchlistController extends AbstractController
) {
}
#[Route(
path: '/api/watchlists',
name: 'watchlist_get_all_mine',
defaults: [
'_api_resource_class' => Watchlist::class,
'_api_operation_name' => 'get_all_mine',
],
methods: ['GET']
)]
public function getWatchlists(): Collection
{
/** @var User $user */
$user = $this->getUser();
return $user->getWatchlists();
}
/**
* @throws ParseException
* @throws EofException

View File

@@ -10,6 +10,7 @@ use ApiPlatform\Metadata\Patch;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Put;
use App\Repository\WatchlistRepository;
use App\State\MyWatchlistsProvider;
use App\State\WatchlistUpdateProcessor;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
@@ -25,7 +26,6 @@ use Symfony\Component\Validator\Constraints as Assert;
shortName: 'Watchlist',
operations: [
new GetCollection(
routeName: 'watchlist_get_all_mine',
normalizationContext: [
'groups' => [
'watchlist:list',
@@ -34,6 +34,7 @@ use Symfony\Component\Validator\Constraints as Assert;
],
],
name: 'get_all_mine',
provider: MyWatchlistsProvider::class,
),
new GetCollection(
uriTemplate: '/tracked',

View File

@@ -2,6 +2,7 @@
namespace App\Repository;
use App\Entity\User;
use App\Entity\Watchlist;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
@@ -33,6 +34,24 @@ class WatchlistRepository extends ServiceEntityRepository
->getQuery()->execute();
}
/**
* @return Watchlist[]
*/
public function fetchWatchlistsForUser(User $user): array
{
return $this->createQueryBuilder('w')
->addSelect('d')
->addSelect('e')
->addSelect('p')
->leftJoin('w.domains', 'd')
->leftJoin('d.events', 'e')
->leftJoin('d.domainPurchases', 'p')
->where('w.user = :user')
->setParameter('user', $user)
->getQuery()
->getResult();
}
// /**
// * @return Watchlist[] Returns an array of Watchlist objects
// */

View File

@@ -0,0 +1,24 @@
<?php
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\Entity\User;
use App\Repository\WatchlistRepository;
use Symfony\Bundle\SecurityBundle\Security;
readonly class MyWatchlistsProvider implements ProviderInterface
{
public function __construct(private Security $security, private WatchlistRepository $watchlistRepository)
{
}
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
{
/** @var User $user */
$user = $this->security->getUser();
return $this->watchlistRepository->fetchWatchlistsForUser($user);
}
}