Description
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