Как использовать событие kernel.terminate в службе

Я делаю службу, которая выполняет тяжелую задачу, эта служба вызывается в контроллере. Чтобы избежать слишком долгой загрузки страницы, я хочу вернуть ответ HTTP и запустить тяжелую задачу после этого.

Я читал, что для этого можно использовать событие kernel.terminate, но я не понимаю, как его использовать.

На данный момент я пытаюсь сделать прослушиватель на KernelEvent:TERMINATE, но я не знаю, как фильтровать, потому что прослушиватель выполняет задание только на хорошей странице...

Можно ли добавить функцию для выполнения при запуске события? Затем в моем контроллере я просто использую функцию, чтобы добавить свое действие, а Symfony выполняет ее позже.

Спасибо за вашу помощь.


person mpiot    schedule 25.04.2017    source источник


Ответы (1)


Наконец, я нашел, как это сделать, я использую EventDispatcher в своей службе и подключаю Listener здесь, PHP Closure: http://symfony.com/doc/current/components/event_dispatcher.html#connecting-listeners

use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\KernelEvents;

class MyService
{
  private $eventDispatcher;

  public function __construct(TokenGenerator $tokenGenerator, EventDispatcherInterface $eventDispatcher)
  {
   $this->tokenGenerator = $tokenGenerator;
   $this->eventDispatcher = $eventDispatcher;
  }

  public function createJob($query)
 {
    // Create a job token
    $token = $this->tokenGenerator->generateToken();

    // Add the job in database
    $job = new Job();
    $job->setName($token);
    $job->setQuery($query);

    // Persist the job in database
    $this->em->persist($job);
    $this->em->flush();

    // Call an event, to process the job in background
    $this->eventDispatcher->addListener(KernelEvents::TERMINATE, function (Event $event) use ($job) {
        // Launch the job
        $this->launchJob($job);
    });

    return $job;
 }
person mpiot    schedule 26.04.2017
comment
Будет ли он выполняться только один раз после KernelEvents::TERMINATE в этом контроллере, или он будет вызываться каждый раз в любом контроллере после того, как вы добавили этот прослушиватель? - person Andrew Vakhniuk; 23.05.2018
comment
В примере это служба, когда вы вызываете свою службу и используете метод createJob, вы добавляете прослушиватель на KernelEvents::TERMINATE, но только для этого Response. Когда пользователь загружает другую страницу, на KernelEvents::TERMINATE нет слушателя. - person mpiot; 24.05.2018
comment
Я использовал ваш пример для аналогичной ситуации, Symfony 5.0.8. Но он не отправляет запрос до завершения работы - все еще выполняет всю тяжелую работу и после этого отправляет ответ. Есть идеи, как это исправить? - person iVenGO; 19.05.2020
comment
Я не использую его повторно уже давно. Потому что теперь вы можете использовать компонент Messenger для запуска асинхронных задач. Это лучший способ, потому что у вас есть: ведение журнала, политика повторных попыток, хранилище неудачных заданий. symfony.com/doc/current/components/messenger.html - person mpiot; 20.05.2020