From fc278420a483733c61fc125df8bf6d2f526d0b50 Mon Sep 17 00:00:00 2001 From: Aina Sitraka <35221835+aynsix@users.noreply.github.com> Date: Wed, 11 Jan 2023 16:52:22 +0300 Subject: [PATCH] PHRAS-3598 Webhook - Emit improvement - Count and Log errors - stop to notify endpoint in error (#4209) * deactivate webhook when many times undelivered * fix * fix log --- .../WebhookEventDeliveryManipulator.php | 23 ++++++++++++++++--- .../WebhookEventDeliveryRepository.php | 21 ++++++++++++++++- .../WorkerManager/Worker/WebhookWorker.php | 10 ++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/lib/Alchemy/Phrasea/Model/Manipulator/WebhookEventDeliveryManipulator.php b/lib/Alchemy/Phrasea/Model/Manipulator/WebhookEventDeliveryManipulator.php index a58abc0f12..71c0b2ff0e 100644 --- a/lib/Alchemy/Phrasea/Model/Manipulator/WebhookEventDeliveryManipulator.php +++ b/lib/Alchemy/Phrasea/Model/Manipulator/WebhookEventDeliveryManipulator.php @@ -11,19 +11,18 @@ namespace Alchemy\Phrasea\Model\Manipulator; -use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Model\Entities\ApiApplication; use Alchemy\Phrasea\Model\Entities\WebhookEvent; use Alchemy\Phrasea\Model\Entities\WebhookEventDelivery; +use Alchemy\Phrasea\Model\Repositories\WebhookEventDeliveryRepository; use Doctrine\Common\Persistence\ObjectManager; -use Doctrine\ORM\EntityRepository; class WebhookEventDeliveryManipulator implements ManipulatorInterface { private $om; private $repository; - public function __construct(ObjectManager $om, EntityRepository $repo) + public function __construct(ObjectManager $om, WebhookEventDeliveryRepository $repo) { $this->om = $om; $this->repository = $repo; @@ -65,4 +64,22 @@ class WebhookEventDeliveryManipulator implements ManipulatorInterface $delivery->setDeliverTries($delivery->getDeliveryTries() + 1); $this->update($delivery); } + + public function isWebhookDeactivate(ApiApplication $apiApplication) + { + $r = $this->repository->findUndeliveredEventsFromLastAppUpdate($apiApplication); + + // if failed to deliver webhook to the url in 5 different events + // calculation based after app update ( any change on api application ) + // so deactivate the webhook + if (count($r) >= 5) { + $apiApplication->setWebhookActive(false); + $this->om->persist($apiApplication); + $this->om->flush(); + + return true; + } + + return false; + } } diff --git a/lib/Alchemy/Phrasea/Model/Repositories/WebhookEventDeliveryRepository.php b/lib/Alchemy/Phrasea/Model/Repositories/WebhookEventDeliveryRepository.php index f162a12ff3..1c5301f2d4 100644 --- a/lib/Alchemy/Phrasea/Model/Repositories/WebhookEventDeliveryRepository.php +++ b/lib/Alchemy/Phrasea/Model/Repositories/WebhookEventDeliveryRepository.php @@ -23,7 +23,6 @@ use Doctrine\ORM\EntityRepository; */ class WebhookEventDeliveryRepository extends EntityRepository { - /** * @return WebhookEventDelivery[] */ @@ -40,6 +39,26 @@ class WebhookEventDeliveryRepository extends EntityRepository return $qb->getQuery()->getResult(); } + /** + * @param $apiApplication + * @return WebhookEventDelivery[] + */ + public function findUndeliveredEventsFromLastAppUpdate(ApiApplication $apiApplication) + { + $qb = $this->createQueryBuilder('e'); + + $qb + ->join('e.application', 'a') + ->where('e.application = :app') + ->andWhere($qb->expr()->eq('e.delivered', $qb->expr()->literal(false))) + ->andWhere('e.deliveryTries = 3') + ->andWhere('e.created > a.updated') + ->setParameter(':app', $apiApplication) + ; + + return $qb->getQuery()->getResult(); + } + /** * @param ApiApplication $apiApplication * @param int $count diff --git a/lib/Alchemy/Phrasea/WorkerManager/Worker/WebhookWorker.php b/lib/Alchemy/Phrasea/WorkerManager/Worker/WebhookWorker.php index 22c6ecb79e..3dd5305f04 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Worker/WebhookWorker.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Worker/WebhookWorker.php @@ -330,6 +330,16 @@ class WebhookWorker implements WorkerInterface ); $app['webhook.delivery_payload_repository']->save($deliveryPayload); + + // deactivate webhook for the app if it's always failed for different event + if ($app['manipulator.webhook-delivery']->isWebhookDeactivate($delivery->getThirdPartyApplication())) { + $message = sprintf('Webhook for app "%s" is deactivated, cannot deliver data in the url "%s" from different events (more than 5 times)', + $delivery->getThirdPartyApplication()->getName(), + $delivery->getThirdPartyApplication()->getWebhookUrl() + ); + + $app['alchemy_worker.message.publisher']->pushLog($message, 'info'); + } } };