Skip to content

[messenger][DX] restart consumer when code changed in debug mode #29451

Closed
@mathroc

Description

@mathroc

Hi,

when working, it would be nice if the consumer would restart automatically when code (or configuration, etc.) has been updated

I've tried to write a middleware that would check if the cache is fresh and stop the command if not (in my case docker-compose would restart it) but I don't know how to check for that

here is what I tried:

<?php declare(strict_types=1);

namespace App\Messenger;

use Symfony\Component\Config\ConfigCache;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
use Symfony\Component\Messenger\Middleware\StackInterface;

class CodeChangedMiddleware implements MiddlewareInterface
{
    /** @var Kernel */
    private $kernel;

    public function __construct(KernelInterface $kernel)
    {
        assert($kernel instanceof Kernel);
        $this->kernel = $kernel;
    }

    public function handle(Envelope $envelope, StackInterface $stack): Envelope
    {
        if (!$this->cacheIsFresh()) {
            throw new \RuntimeException("Restarting consumer to update cache");
        }

        return $stack->next()->handle($envelope, $stack);
    }

    private function cacheIsFresh(): bool
    {
        // trying to mimick what's happening at the beginning of Kernel::initializeContainer
        $ro = new \ReflectionObject($this->kernel);
        $getContainerClass = $ro->getMethod("getContainerClass");
        $getContainerClass->setAccessible(true);

        $class = $getContainerClass->invoke($this->kernel);

        $warmupDirProperty = $ro->getParentClass()->getProperty("warmupDir");
        $warmupDirProperty->setAccessible(true);
        $cacheDir = $warmupDirProperty->getValue($this->kernel) ?: $this->kernel->getCacheDir();

        $debugProperty = $ro->getProperty("debug");
        $debugProperty->setAccessible(true);
        $cache = new ConfigCache("$cacheDir/$class.php", $debugProperty->getValue($this->kernel));

        return $cache->isFresh();
    }
}

but this cache is always fresh

Do you think this is something worth integrating into symfony ? (maybe directly into the consumer command instead)

and, any idea why the middleware I wrote does not detect code changes ?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions