Skip to content

"Tried to run command without establishing a connection" with Firefox client - Panther Symfony #660

@Ooogeid

Description

@Ooogeid

Hello,

I'm encountering an issue while trying to run a Symfony Messenger command that utilizes Panther to perform tests. The error message I receive is:

[CRITICAL] CONSOLE Error thrown while running command "ProcessCommand".
Message: "Tried to run command without establishing a connection" command="ProcessCommand"

Here's the context:

Goal
I want to dispatch a Symfony Messenger message (RunCommandMessage) to execute the ProcessCommand in the background. The command fetches URLs and processes them using Panther.

Code Overview

In my controller : $this->messageBus->dispatch(new RunCommandMessage('ProcessCommand'));

The Command
class ProcessCommand extends Command
{
private $urlService;
private $pantherService;
private $entityManager;
private $crawlerService;
private $client;

protected static $defaultName = 'ProcessCommand';  

public function __construct(UrlService $urlService, PantherService $pantherService, EntityManagerInterface $entityManager, CrawlerService $crawlerService)  
{  
    $this->urlService = $urlService;  
    $this->pantherService = $pantherService;  
    $this->entityManager = $entityManager;  
    $this->crawlerService = $crawlerService;  
    parent::__construct();  
}  

protected function configure(): void  
{  
    $this->setDescription('Run automatic tests.');  
}  

protected function execute(InputInterface $input, OutputInterface $output): int  
{  
    $client = $this->pantherService->getPantherClient();  
    $url = 'https://example.com';  

    // Fetch the URL  
    $crawler = $client->request('GET', $url);  
    $this->document = $this->crawlerService->fetchPage($url);  

    return Command::SUCCESS;  
}  

}

The PantherService
class PantherService extends PantherTestCase
{
private ?Client $client = null;
private Crawler $crawler;

public function __construct()  
{  
    $this->checkAndKillFirefoxProcesses();  
    $this->client = Client::createFirefoxClient(options: ['port' => 4444]);  
}  

public function requestPage(string $url): Crawler  
{  
    $this->crawler = $this->client->request('GET', $url);  
    return $this->crawler;  
}  

public function getPantherClient(): Client  
{  
    $availablePort = $this->getAvailablePort();  
    $this->client = Client::createFirefoxClient(  
        options: [  
            'port' => $availablePort,  
        ],  
    );  

    return $this->client;  
}  

private function getAvailablePort(): int  
{  
    $socket = socket_create_listen(0);  
    socket_getsockname($socket, $address, $port);  
    socket_close($socket);  
    return $port;  
}  

}

private function checkAndKillFirefoxProcesses()
{
// Vérifie les processus firefox
$processList = [];
exec('ps aux | grep [f]irefox', $processList); // Ajout de [f] pour éviter de capturer la commande grep elle-même

    // Récupère tous les PID pour firefox
    $firefoxPids = [];
    foreach ($processList as $process) {
        preg_match('/\b(\d+)\b/', $process, $matches);
        if (!empty($matches[1])) {
            $firefoxPids[] = $matches[1];  // Enregistre le PID de firefox
        }
    }

    // Ne tuer que si plusieurs processus sont trouvés (laissez toujours deux processus)
    if (count($firefoxPids) > 2) {
        array_splice($firefoxPids, 0, 2); // Laissez les deux premiers processus en cours
        foreach ($firefoxPids as $pid) {
            // Vérifie si le processus existe avant de le tuer
            if ($this->processExists($pid)) {
                exec("kill -9 $pid");  // Force kill le processus
            }
        }
    }

    // Vérifie les processus geckodriver
    $processList = [];
    exec('ps aux | grep [g]eckodriver', $processList);  // Ajout de [g] pour éviter de capturer la commande grep elle-même

    // Récupère tous les PID pour geckodriver
    $geckoDriverPids = [];
    foreach ($processList as $process) {
        preg_match('/\b(\d+)\b/', $process, $matches);
        if (!empty($matches[1])) {
            $geckoDriverPids[] = $matches[1];  // Enregistre le PID de geckodriver
        }
    }

    // Ne tuer que si plusieurs processus sont trouvés (laissez toujours deux processus)
    if (count($geckoDriverPids) > 2) {
        array_splice($geckoDriverPids, 0, 2); // Laissez les deux premiers processus en cours
        foreach ($geckoDriverPids as $pid) {
            // Vérifie si le processus existe avant de le tuer
            if ($this->processExists($pid)) {
                exec("kill -9 $pid");  // Force kill le processus
            }
        }
    }

}

The Issue
The error "Tried to run command without establishing a connection" appears when the command is executed. I suspect it is related to the Panther client initialization or the connection to Firefox.

What I Tried
Ensured that Geckodriver is running and correctly set up.
Verified that the port (4444) is available and not in use by other processes.
Used Client::createFirefoxClient() directly in the service without dynamic port assignment, but the error persists.

When I manually execute the command (php bin/console ProcessCommand) from the terminal, it works perfectly. However, when the same command is dispatched via the Symfony Messenger and executed by the Messenger worker, I get the above error.

Questions
Is there something wrong with how I initialize the Panther client in the PantherService?
Could the Messenger worker context cause the issue with the Firefox client connection?
How can I properly establish and maintain the Panther client connection within the Symfony Messenger context?
Any insights or suggestions would be greatly appreciated! Thank you!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions