Skip to content

Commit

Permalink
Retry failed messages from admin
Browse files Browse the repository at this point in the history
  • Loading branch information
DumitracheAdrian committed May 3, 2024
1 parent 29d2fb5 commit 94bffd2
Show file tree
Hide file tree
Showing 12 changed files with 173 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use Draw\Component\Messenger\Message\AsyncHighPriorityMessageInterface;
use Draw\Component\Messenger\Message\AsyncLowPriorityMessageInterface;
use Draw\Component\Messenger\Message\AsyncMessageInterface;
use Draw\Component\Messenger\MessageHandler\RetryFailedMessageMessageHandler;
use Draw\Component\Messenger\Retry\EventDrivenRetryStrategy;
use Draw\Component\Messenger\Searchable\EnvelopeFinder;
use Draw\Component\Messenger\Searchable\TransportRepository;
Expand Down Expand Up @@ -167,6 +168,12 @@ public static function provideTestLoad(): iterable
TransportRepository::class,
]
),
new ServiceConfiguration(
'draw.messenger.message_handler.retry_failed_message_message_handler',
[
RetryFailedMessageMessageHandler::class,
]
),
new ServiceConfiguration(
'draw.messenger.manual_trigger.action.click_message_action',
[ClickMessageAction::class]
Expand Down
34 changes: 34 additions & 0 deletions packages/messenger/Message/RetryFailedMessageMessage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Draw\Component\Messenger\Message;

use App\Entity\MessengerMessage;
use Draw\Component\Messenger\DoctrineEnvelopeEntityReference\Message\DoctrineReferenceAwareInterface;
use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException;

class RetryFailedMessageMessage implements DoctrineReferenceAwareInterface
{
private ?MessengerMessage $message;

public function __construct(
MessengerMessage $message,
) {
$this->message = $message;
}

public function getMessage(): MessengerMessage
{
if (null === $this->message) {
throw new UnrecoverableMessageHandlingException('Message is not set.');
}

return $this->message;
}

public function getPropertiesWithDoctrineObject(): array
{
return ['message'];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace Draw\Component\Messenger\MessageHandler;

use Draw\Component\Messenger\Message\RetryFailedMessageMessage;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;

class RetryFailedMessageMessageHandler
{
public function __construct(
private KernelInterface $kernel,
) {
}

#[AsMessageHandler]
public function handleRetryFailedMessageMessage(RetryFailedMessageMessage $message): void
{
$application = new Application($this->kernel);
$application->setAutoExit(false);

$application->run(
new ArrayInput(
[
'command' => 'messenger:failed:retry',
'id' => [
$message->getMessage()->getId(),
],
'--force' => true,
]
),
new NullOutput()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Draw\Bundle\SonataIntegrationBundle\Console\Controller\ExecutionController;
use Draw\Bundle\SonataIntegrationBundle\CronJob\Controller\CronJobController;
use Draw\Bundle\SonataIntegrationBundle\CronJob\Controller\CronJobExecutionController;
use Draw\Bundle\SonataIntegrationBundle\Messenger\Controller\MessageController;
use Draw\Bundle\SonataIntegrationBundle\User\Extension\TwoFactorAuthenticationExtension;
use Draw\Bundle\UserBundle\DrawUserBundle;
use Draw\Bundle\UserBundle\Entity\UserLock;
Expand Down Expand Up @@ -143,8 +144,10 @@ private function createMessengerNode(): ArrayNodeDefinition
(new SonataAdminNodeConfiguration(MessengerMessage::class, 'Messenger', 'admin'))
->addDefaultsIfNotSet()
->pagerTypeDefaultValue('simple')
->controllerClassDefaultValue(MessageController::class)
->iconDefaultValue('fas fa-rss')
->labelDefaultValue('Message')
->translationDomainDefaultValue('DrawMessengerAdmin')
->canBeDisabled()
)
->end();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ private function configureMessenger(array $config, Loader\FileLoader $loader, Co
->setAutowired(true)
->setAutoconfigured(true)
);

$this->setControllerClassDefinition($config['admin'], $container);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,20 @@ protected function configureListFields(ListMapper $list): void
->add('availableAt')
->add('deliveredAt')
->add('expiresAt')
->add('tags', 'list');
->add('tags', 'list')
->add(
ListMapper::NAME_ACTIONS,
ListMapper::TYPE_ACTIONS,
[
'actions' => [
'show' => [],
'retry' => [
'template' => '@DrawSonataIntegration/Messenger/Message/list__action_retry.html.twig',
],
'delete' => [],
],
]
);
}

public function dumpMessage(DrawMessageInterface $message): string
Expand All @@ -109,6 +122,7 @@ public function dumpMessage(DrawMessageInterface $message): string

protected function configureRoutes(RouteCollectionInterface $collection): void
{
$collection->add('retry', sprintf('%s/retry', $this->getRouterIdParameter()));
$collection->remove('create');
$collection->remove('edit');
}
Expand All @@ -130,4 +144,15 @@ protected function configureQuery(ProxyQueryInterface $query): ProxyQueryInterfa

return $query;
}

protected function configureActionButtons(array $buttonList, string $action, ?object $object = null): array
{
if ('show' === $action && 'failed' === $object?->getQueueName()) {
$buttonList['retry'] = [
'template' => '@DrawSonataIntegration/Messenger/Message/show__action_retry.html.twig',
];
}

return $buttonList;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace Draw\Bundle\SonataIntegrationBundle\Messenger\Controller;

use App\Entity\MessengerMessage;
use Draw\Component\Messenger\Message\RetryFailedMessageMessage;
use Sonata\AdminBundle\Controller\CRUDController;
use Symfony\Component\Messenger\MessageBusInterface;

class MessageController extends CRUDController
{
public function retryAction(
MessengerMessage $message,
MessageBusInterface $messageBus
) {
if ('failed' !== $message->getQueueName()) {
$this->addFlash(
'sonata_flash_error',
$this->trans('message_cannot_be_retried')
);

return $this->redirectToList();
}

$messageBus->dispatch(
new RetryFailedMessageMessage($message)
);

$this->addFlash(
'sonata_flash_success',
$this->trans('retry_message_successfully_dispatched')
);

return $this->redirectToList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
message_cannot_be_retried: Message cannot be retried.
retry_message_successfully_dispatched: Retry message successfully dispatched.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{% if 'failed' == object.getQueueName() %}
<a href="{{ admin.generateObjectUrl('retry', object) }}"
class="btn btn-sm btn-default"
title="Retry"
>
<i class="fa fa-rotate-right"></i> Retry
</a>
{% endif %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<li>
<a class="sonata-action-element"
href="{{ admin.generateObjectUrl('retry', object ) }}"
title="Retry"
>
<i class="fa fa-rotate-right"></i> Retry
</a>
</li>
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Draw\Bundle\SonataIntegrationBundle\CronJob\Controller\CronJobController;
use Draw\Bundle\SonataIntegrationBundle\CronJob\Controller\CronJobExecutionController;
use Draw\Bundle\SonataIntegrationBundle\DependencyInjection\Configuration;
use Draw\Bundle\SonataIntegrationBundle\Messenger\Controller\MessageController;
use Draw\Bundle\SonataIntegrationBundle\User\Extension\TwoFactorAuthenticationExtension;
use Draw\Bundle\UserBundle\Entity\UserLock;
use Draw\Component\Application\Configuration\Entity\Config;
Expand Down Expand Up @@ -103,12 +104,12 @@ public function getDefaultConfiguration(): array
'admin' => [
'group' => 'Messenger',
'entity_class' => MessengerMessage::class,
'controller_class' => 'sonata.admin.controller.crud',
'controller_class' => MessageController::class,
'icon' => 'fas fa-rss',
'label' => 'Message',
'pager_type' => 'simple',
'show_in_dashboard' => true,
'translation_domain' => 'SonataAdminBundle',
'translation_domain' => 'DrawMessengerAdmin',
'enabled' => true,
],
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Draw\Bundle\SonataIntegrationBundle\DependencyInjection\DrawSonataIntegrationExtension;
use Draw\Bundle\SonataIntegrationBundle\Messenger\Admin\MessengerMessageAdmin;
use Draw\Bundle\SonataIntegrationBundle\Messenger\Controller\MessageController;
use Draw\Bundle\SonataIntegrationBundle\Messenger\EventListener\FinalizeContextQueueCountEventListener;
use Draw\Bundle\SonataIntegrationBundle\Messenger\Security\CanShowMessageVoter;
use PHPUnit\Framework\Attributes\CoversClass;
Expand All @@ -28,6 +29,7 @@ public function getConfiguration(): array
public static function provideTestHasServiceDefinition(): iterable
{
yield [MessengerMessageAdmin::class];
yield [MessageController::class];
yield [FinalizeContextQueueCountEventListener::class];
yield [CanShowMessageVoter::class];
}
Expand Down

0 comments on commit 94bffd2

Please sign in to comment.