core icon indicating copy to clipboard operation
core copied to clipboard

Purge parent collections in inheritance cases

Open CvekCoding opened this issue 8 months ago • 3 comments

Description
In the case when we clear the cache, we haven't covered the scenario where an entity is part of a class hierarchy (such as STI). In this case, the cache for all parent collections should also be cleared.

For example, we have a Product and its subclass ChildProduct. If we already have a Products collection in the cache, when a new ChildProduct is created, only the cache for the ChildProduct collection will be purged, while the parent collection will remain unchanged.

In my opinion, this is more of a bug than a feature request.

CvekCoding avatar Mar 20 '25 14:03 CvekCoding

For now I created the following processor decorator to work-around the issue:

#[AsDecorator(decorates: 'api_platform.doctrine.orm.state.persist_processor')]
final readonly class PurgeParentCacheCollection implements ProcessorInterface
{
    public function __construct(
        #[Autowire(service: 'api_platform.http_cache.purger')]
        private PurgerInterface $purger,
        private PersistProcessor $persistProcessor,
        private IriConverterInterface $iriConverter,
        private ResourceClassResolverInterface $resourceClassResolver,
        private EntityManagerInterface $entityManager,
    ) {}

    public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed
    {
        $toReturn = $this->persistProcessor->process($data, $operation, $uriVariables, $context);

        $classMetadata = $this->entityManager->getClassMetadata($data::class);
        if ($classMetadata->isInheritanceTypeNone()) {
            return $toReturn;
        }

        foreach ($classMetadata->parentClasses as $parentClass) {
            if ($this->resourceClassResolver->isResourceClass($parentClass)) {
                $iris[] = $this->iriConverter->getIriFromResource($parentClass, UrlGeneratorInterface::ABS_PATH, new GetCollection());
            }
        }

        if (!empty($iris)) {
            $this->purger->purge($iris);
        }

        return $toReturn;
    }
}

CvekCoding avatar Mar 20 '25 15:03 CvekCoding

Interesting, we should probably handle this directly inside the PurgeListener, would you be able to patch this? Thanks!

soyuka avatar Mar 21 '25 09:03 soyuka

Ok I'll try. I think you need tests for this too? @soyuka

CvekCoding avatar Mar 21 '25 11:03 CvekCoding