8000 [Messenger] The Doctrine transport doesn't create the table when consuming · Issue #47005 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content
[Messenger] The Doctrine transport doesn't create the table when consuming #47005
Closed as not planned
@sylfabre

Description

@sylfabre

Symfony version(s) affected

  • 5.4.8 => Confirmed
  • 5.4.latest => Very probable
  • 6.1.latest => Very probable

I found the issue with Symfony 5.4.8 but I checked both 5.4 and 6.1 latest code and they haven't changed so I guess the issue exists there too.

Description

The Doctrine transport won't create the table when consuming.

I detail below the technical reason and a possible solution.

I also looked at the code about the message creation and it looks OK.

How to reproduce

Setup a Doctrine queue and start consuming with php bin/console messenger:consume async_crm

This exception is thrown:

In PDOStatement.php line 117:

  [PDOException (42S02)]
  SQLSTATE[42S02]: Base table or view not found: 1146 Table 'messenger_crm' doesn't exist


Exception trace:
  at /home/assoconnect/backend/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php:117
 PDOStatement->execute() at /home/assoconnect/backend/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php:117
 Doctrine\DBAL\Driver\PDOStatement->execute() at /home/assoconnect/backend/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:1527
 Doctrine\DBAL\Connection->executeStatement() at /home/assoconnect/backend/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:819
 Doctrine\DBAL\Connection->delete() at /home/assoconnect/backend/vendor/symfony/doctrine-messenger/Transport/Connection.php:161
 Symfony\Component\Messenger\Bridge\Doctrine\Transport\Connection->get() at /home/assoconnect/backend/vendor/symfony/doctrine-messenger/Transport/DoctrineReceiver.php:49
 Symfony\Component\Messenger\Bridge\Doctrine\Transport\DoctrineReceiver->get() at /home/assoconnect/backend/vendor/symfony/doctrine-messenger/Transport/DoctrineTransport.php:45
 Symfony\Component\Messenger\Bridge\Doctrine\Transport\DoctrineTransport->get() at /home/assoconnect/backend/vendor/symfony/messenger/Worker.php:102
 Symfony\Component\Messenger\Worker->run() at /home/assoconnect/backend/vendor/symfony/messenger/Command/ConsumeMessagesCommand.php:225
 Symfony\Component\Messenger\Command\ConsumeMessagesCommand->execute() at /home/assoconnect/backend/vendor/symfony/console/Command/Command.php:298
 Symfony\Component\Console\Command\Command->run() at /home/assoconnect/backend/vendor/symfony/console/Application.php:1042
 Symfony\Component\Console\Application->doRunCommand() at /home/assoconnect/backend/vendor/symfony/framework-bundle/Console/Application.php:96
 Symfony\Bundle\FrameworkBundle\Console\Application->doRunCommand() at /home/assoconnect/backend/vendor/symfony/console/Application.php:299
 Symfony\Component\Console\Application->doRun() at /home/assoconnect/backend/vendor/symfony/framework-bundle/Console/Application.php:82
 Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /home/assoconnect/backend/vendor/symfony/console/Application.php:171
 Symfony\Component\Console\Application->run() at /home/assoconnect/backend/vendor/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php:54
 Symfony\Component\Runtime\Runner\Symfony\ConsoleApplicationRunner->run() at /home/assoconnect/backend/vendor/autoload_runtime.php:35
 require_once() at /home/assoconnect/backend/bin/console:11

Possible Solution

The throw exception is \Doctrine\DBAL\Exception\TableNotFoundException

  • which extends \Doctrine\DBAL\Exception\DatabaseObjectNotFoundException
  • which extends \Doctrine\DBAL\Exception\ServerException
  • which extends \Doctrine\DBAL\Exception\DriverException
  • which extends \Doctrine\DBAL\Exception
  • which extends \Doctrine\DBAL\DBALException
  • which extends \Exception

The \Symfony\Component\Messenger\Bridge\Doctrine\Transport\Connection::get() has a try/catch block to ignore exception:

# use Doctrine\DBAL\Driver\Exception as DriverException;

if ($this->driverConnection->getDatabasePlatform() instanceof MySQLPlatform) {
    try {
        $this->driverConnection->delete($this->configuration['table_name'], ['delivered_at' => '9999-12-31']);
    } catch (DriverException $e) {
        // Ignore the exception
    }
}

The try/catch doesn't cover the thrown exception as \Doctrine\DBAL\Exception\TableNotFoundException doesn't extend Doctrine\DBAL\Driver\Exception (imported as DriverException in Symfony\Component\Messenger\Bridge\Doctrine\Transport\Connection)

However, once this first "delete" MySQL-specific step is done, the get() method wraps all the execution in another try/catch block which correctly handles the TableNotFoundException exception:

catch (\Throwable $e) {
	$this->driverConnection->rollBack();

	if ($this->autoSetup && $e instanceof TableNotFoundException) {
		$this->setup();
		goto get;
	}

	throw $e;
}

I suggest that this working try/catch block should cover the whole body of the get() method vs only a part of it as-is now.

Additional Context

No response

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

      0