1

I am using Symfony version 4.2 . I use other packages I write below.

"php": "^7.1.3",
"ext-ctype": "*",
"ext-iconv": "*",
"enqueue/enqueue-bundle": "^0.9.7",
"enqueue/pheanstalk": "^0.9.7",
"friendsofsymfony/elastica-bundle": "^5.0",
"nelmio/cors-bundle": "^1.5",
"nesbot/carbon": "^2.10",
"symfony/console": "*",
"symfony/flex": "^1.1",
"symfony/framework-bundle": "*",
"symfony/orm-pack": "^1.0",
"symfony/serializer-pack": "^1.0",
"symfony/yaml": "*"

I am running the cosume command using a supervisor. I write my supervisor setting below.

[program:devlog-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/project-directory/bin/console enqueue:consume --setup-broker
autostart=true
autorestart=true
user=nginx
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/project-directory/worker.log

Entity manager is closed after working for a certain period of time. I think I need to start again. But I could not do it in the code. But when the supervisor restarts, everything starts working. How can I solve this problem because I cant always restart supervisor from the beginning.

I'm writing the sample process below.

<?php

namespace App\Processor;

use App\Entity\Main\Event;
use Doctrine\ORM\EntityManagerInterface;
use Interop\Queue\Message;
use Interop\Queue\Context;
use Interop\Queue\Processor;
use Enqueue\Client\TopicSubscriberInterface;

class FooProcessor implements Processor, TopicSubscriberInterface
{
    protected $entityManager;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public function process(Message $message, Context $session)
    {
        try {
            $event = new Event();
            $event->setAction('example');

            if (!$this->entityManager->isOpen()) {
                echo "Entity Manger is closed...\n";
                // here i need to restart the entity manager or another solution
            }

            $this->entityManager->persist($event);
            $this->entityManager->flush();
            $this->entityManager->clear();

            echo "Success\n";
            return self::ACK;

        } catch (\Exception $e){
            echo ($e->getMessage())." \n";
            return self::REJECT;
        }
    }

    public static function getSubscribedTopics()
    {
        return ['aFooTopic'];
    }
}
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
ahmet
  • 363
  • 2
  • 5
  • 16

3 Answers3

2

If you will look into Doctrine sources - you will see (1, 2) that EntityManager get closed in a case if some exception was thrown in transaction context.

It means that if your EntityManager get closed - there is probably something wrong with either application or database (e.g. connection to database was lost or there was some data inconsistency and so on). From Doctrine sources you can also see (1, 2) that exception is thrown in a case of EntityManager closing so, looking into your sources, you should see this exception being echoed right after closing happens.

Of course first thing you should do is to check these exceptions to examine reason for your EntityManager get closed and eliminate reasons for them if possible. This is recommended way.

There is no built-in way to re-open closed EntityManager, but since "closed" state is just a flag inside Doctrine - you can clear it through Reflection:

$reflection = new \ReflectionObject($this->entityManager);
$prop = $reflection->getProperty('closed');
$prop->setAccessible(true);
$prop->setValue($this->entityManager, false);
$prop->setAccessible(false);

but this is a "hacky" way and I would not recommend it until absolutely necessary.

Flying
  • 4,422
  • 2
  • 17
  • 25
1

The problem was solved by changing supervisor settings. I missed the setting.

new supervisor setting

[program:devlog-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/project-directory/bin/console enqueue:consume --setup-broker --env=prod --no-debug --time-limit="now + 5 minutes"
autostart=true
autorestart=true
user=nginx
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/project-directory/worker.log

Thanks

ahmet
  • 363
  • 2
  • 5
  • 16
0

I believe what you are looking for is the DoctrinePingConnectionExtension for the enqueue library.

Here is the services.yaml configuration you need to enable this:

services:
    app.enqueue.doctrine_ping_connection_extension:
        class: 'Enqueue\Bundle\Consumption\Extension\DoctrinePingConnectionExtension'
        tags:
            - { name: 'enqueue.consumption.extension', priority: 10, client: 'all' }
Dharman
  • 30,962
  • 25
  • 85
  • 135
Zac Fair
  • 1
  • 2