Baldinof / roadrunner-bundle

A RoadRunner worker integrated in your Symfony app
MIT License
255 stars 46 forks source link

Event dispatcher doesn't reset automatically after next request #135

Closed dmitryuk closed 5 months ago

dmitryuk commented 5 months ago

Example code

// some business logic here...
        $this->eventDispatcher->addListener(
            KernelEvents::TERMINATE,
            fn () => sendEmailForExample()
        );

Next request will cause n+1 call of sendEmailForExample

I need to reset EventDispatcher manually with removing these listeners

Baldinof commented 5 months ago

No, it is not resetted unless a kernel reboot happens.

So if you call addListener() within your code (in a controller), listeners will stack ups.

If you want to do stuff in the background I would recommend to use Symfony Messenger, or write a custom service that listen KernelEvents::TERMINATE and empty the tasks list right after.

Something like

class RunAfterRequest
{
    private array $tasks = [];

    public function add(\Closure $callback): void
    {
        $this->tasks[] = $callback;
    }

    #[AsEventListener(KernelEvents::TERMINATE)]
    public function run()
    {
        while (count($this->tasks) > 0) {
            $task = array_shift($this->tasks);
            $task();
        }
    }
}

Then you can inject the RunAfterRequest service and call add() to add a task to be run after the kernel terminate.

Still, I think Messenger is the best option