core: VarnishPurger cannot handle alot of entities

Based on this commit: https://github.com/Simperfit/api-perf/commit/4201cc28c4ddb7c493df31a095d8ad71b8fe1297#diff-c828d4117439a2216f86c406d522c79c

To reproduce it

docker-compose pull
docker-compose up -d
docker-compose exec php bin/console d:f:l

Results in:


In RequestException.php line 113:
                                                                                   
  Client error: `BAN http://cache-proxy` resulted in a `400 Bad Request` response  
 

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 9
  • Comments: 24 (18 by maintainers)

Commits related to this issue

Most upvoted comments

Hello, I managed to fix the problem temporarily by modifying the VarnishPurger class like bellow :

<?php

/*
 * This file is part of the API Platform project.
 *
 * (c) Kévin Dunglas <dunglas@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

declare(strict_types=1);

namespace ApiPlatform\Core\HttpCache;

use GuzzleHttp\ClientInterface;

/**
 * Purges Varnish.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @experimental
 */
final class VarnishPurger implements PurgerInterface
{
    private $clients;

    /**
     * @param ClientInterface[] $clients
     */
    public function __construct(array $clients)
    {
        $this->clients = $clients;
    }

    /**
     * {@inheritdoc}
     */
    public function purge(array $iris)
    {
        if (!$iris) {
            return;
        }

        // Create the regex to purge all tags in just one request
        $parts = array_map(function ($iri) {
            return sprintf('(^|\,)%s($|\,)', preg_quote($iri));
        }, $iris);

        $parts = array_chunk($parts,10);
        foreach ($parts as $part) {
            $regex = \count($part) > 1 ? sprintf('(%s)', implode(')|(', $part)) : array_shift($part);
            foreach ($this->clients as $client) {
                $client->request('BAN', '', ['headers' => ['ApiPlatform-Ban-Regex' => $regex]]);
            }
        }

    }
}

But I do not know how to extend that class as it is declared final, for now I have modified directly the file on vendor/api-platform/core/src/HttpCache/VarnishPurger.php

As a workaround, you can do that: https://github.com/api-platform/demo/pull/24/commits/0bc68491cf2859538f6749218a227095ec0ec852#diff-628212751f227bfce20484adbd0d4191R1

Maybe can we enable the Varnish subsystem only for the prod env in the default skeleton too?

To prevent the problem when loading fixtures, you can enable the cache invalidation mechanism only for the prod environment. It’s what we’ve done in the demo: https://github.com/api-platform/demo/blob/master/api/config/packages/prod/api_platform.yaml#L7-L11

Let’s do that then

I also have the issue in a prod environment when invalidating an object with a lot of relations, so it’s definitely not only related to dev commands

I’m also having this issue trying to import data with Doctrine from a command (Which I need to do in production too). Do we have a workaround ? For now I’ve simply reduced my bulk size to avoid this.

We may at least disable it in CLI + dev to allow such commands to work.

I’d again argue that there’s a need for the developer to verify that the caching (especially the invalidation) by reverse proxy works as expected in the dev env. Surprises are bad.

Would #1776 help? 😄