Merge branch '6.4' into 7.2

* 6.4:
  remove return type from AbstractObjectNormalizer::getAllowedAttributes()
  Bump Symfony version to 6.4.24
  Update VERSION for 6.4.23
  Update CONTRIBUTORS for 6.4.23
  Update CHANGELOG for 6.4.23
  [Console][Messenger] Fix: Allow UnrecoverableExceptionInterface to bypass retry in RunCommandMessageHandler
This commit is contained in:
Christian Flothmann
2025-07-01 10:34:30 +02:00
2 changed files with 50 additions and 0 deletions

View File

@@ -16,6 +16,8 @@ use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\RunCommandFailedException;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Messenger\Exception\RecoverableExceptionInterface;
use Symfony\Component\Messenger\Exception\UnrecoverableExceptionInterface;
/**
* @author Kevin Bond <kevinbond@gmail.com>
@@ -36,6 +38,8 @@ final class RunCommandMessageHandler
try {
$exitCode = $this->application->run($input, $output);
} catch (UnrecoverableExceptionInterface|RecoverableExceptionInterface $e) {
throw $e;
} catch (\Throwable $e) {
throw new RunCommandFailedException($e, new RunCommandContext($message, Command::FAILURE, $output->fetch()));
}

View File

@@ -20,6 +20,10 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Messenger\RunCommandMessage;
use Symfony\Component\Console\Messenger\RunCommandMessageHandler;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Messenger\Exception\RecoverableExceptionInterface;
use Symfony\Component\Messenger\Exception\RecoverableMessageHandlingException;
use Symfony\Component\Messenger\Exception\UnrecoverableExceptionInterface;
use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException;
/**
* @author Kevin Bond <kevinbond@gmail.com>
@@ -81,6 +85,38 @@ final class RunCommandMessageHandlerTest extends TestCase
$this->fail('Exception not thrown.');
}
public function testExecutesCommandThatThrownUnrecoverableException()
{
$handler = new RunCommandMessageHandler($this->createApplicationWithCommand());
try {
$handler(new RunCommandMessage('test:command --throw-unrecoverable'));
} catch (UnrecoverableExceptionInterface $e) {
$this->assertSame('Unrecoverable exception message', $e->getMessage());
$this->assertNull($e->getPrevious());
return;
}
$this->fail('Exception not thrown.');
}
public function testExecutesCommandThatThrownRecoverableException()
{
$handler = new RunCommandMessageHandler($this->createApplicationWithCommand());
try {
$handler(new RunCommandMessage('test:command --throw-recoverable'));
} catch (RecoverableExceptionInterface $e) {
$this->assertSame('Recoverable exception message', $e->getMessage());
$this->assertNull($e->getPrevious());
return;
}
$this->fail('Exception not thrown.');
}
private function createApplicationWithCommand(): Application
{
$application = new Application();
@@ -92,6 +128,8 @@ final class RunCommandMessageHandlerTest extends TestCase
$this
->setName('test:command')
->addOption('throw')
->addOption('throw-unrecoverable')
->addOption('throw-recoverable')
->addOption('exit', null, InputOption::VALUE_REQUIRED, 0)
;
}
@@ -100,6 +138,14 @@ final class RunCommandMessageHandlerTest extends TestCase
{
$output->write('some message');
if ($input->getOption('throw-unrecoverable')) {
throw new UnrecoverableMessageHandlingException('Unrecoverable exception message');
}
if ($input->getOption('throw-recoverable')) {
throw new RecoverableMessageHandlingException('Recoverable exception message');
}
if ($input->getOption('throw')) {
throw new \RuntimeException('exception message');
}