first-programmer
@first-programmer
Backend software engineer

Стоит ли добавлять декоратор для обработки исключений?

Всем привет.

Есть класс консьюмера (обработчика) принимающий сообщения из очереди. В нем идет блок try catch, внутри вызываются методы сервисов, эти методы сервисов могут кидать исключения, еще эти методы обращаются к репозиториям, типа для создания записей в базе и обновления, соответсвенно репозитории тоже могут кидать исключения типа PDOException. Все эти ошибки ловятся в консьюмере (обработчике), то есть на самом верху. Мне предложили вынести обработку исключений из консьюмера в отдельный декоратор, который соотвественно уже будет дергать метод консьюмера (обработчика), который работает с сервисами. То есть по логике декоратор в данном случае станет консьюмером, так как это будет входная точка сообщения. Нужна ли такая прослойка? Чем это сделает код удобнее? Пока мне кажется, что это лишнее усложнение.

Вот код

public function __invoke(OfdTicketMessage $ofdTicketMessage): void
    {
        $this->logger->info(
            'OfdTicketMessage was received',
            ['data' => $ofdTicketMessage->toArray()]
        );

        try {
            $this->ofdTicketService->create($ofdTicketMessage);
            $this->orangeApiOfdTicketService->createTicket($ofdTicketMessage);

            $this->ofdTicketService->update(
                $ofdTicketMessage,
                [
                    'processed' => true,
                    'statusCode' => OrangeApiResponseStatus::RESPONSE_CREATED
                ]
            );
        } catch (AlreadyCreatedException|AlreadyProcessedException|ConflictException $e) {
            $this->logger->info(
                'Need to ack message because: ' . $e->getMessage(),
                ['ofdTicketId' => $ofdTicketMessage->getId()]
            );

            throw new  UnrecoverableMessageHandlingException($e->getMessage(), $e->getCode());
        } catch (OfdOrangeApiException $e) {
            $this->logger->error(
                'Ofd orange api error: ' . $e->getMessage(),
                ['ofdTicketId' => $ofdTicketMessage->getId()]
            );

            $this->ofdTicketService->update(
                $ofdTicketMessage,
                [
                    'error' => 'Ofd orange api error: ' . $e->getMessage(),
                    'statusCode' => $e->getCode()
                ]
            );
        } catch (TransportExceptionInterface $e) {
            $this->logger->error(
                'Can\'t send request to ofd orange api: ' . $e->getMessage(),
                ['ofdTicketId' => $ofdTicketMessage->getId()]
            );

            $this->ofdTicketService->update(
                $ofdTicketMessage,
                [
                    'error' => 'Can\'t send request to ofd orange api: ' . $e->getMessage(),
                    'statusCode' => $e->getCode()
                ]
            );
        } catch (\Exception|\Throwable $e) {
            $this->logger->error(
                'Something went wrong: ' . $e->getMessage(),
                ['ofdTicketId' => $ofdTicketMessage->getId()]
            );

            $this->ofdTicketService->update(
                $ofdTicketMessage,
                [
                    'error' => 'Something went wrong: ' . $e->getMessage(),
                    'statusCode' => InternalExceptionStatus::INTERNAL_ERROR
                ]
            );

            throw new  UnrecoverableMessageHandlingException($e->getMessage(), $e->getCode());
        }
    }
  • Вопрос задан
  • 240 просмотров
Пригласить эксперта
Ответы на вопрос 2
@Akela_wolf
Extreme Programmer
Зависит от того какая в обработчиках исключений выполняется логика. Если там просто логирование исключений, никак не связанное с логикой консьюмера - то вполне оправданно эту логику отделить. Но можно и не отделять. Тут все зависит от желания переиспользовать консьюмер и декоратор. Также оправданно отделять подобные независимые вещи для облегчения юнит-тестирования.

Но если же в обработке исключений более сложная логика, например, связанная с восстановлением после ошибки, переплетенная с логикой консьюмера - то отделять такую логику будет сложно и не всегда можно сказать нужно ли это делать не видя код.
Ответ написан
SilenceOfWinter
@SilenceOfWinter Куратор тега PHP
та еще зажигалка...
Это не декоратор, а прокси. Я бы скорее сделал логирование ошибок в самих исключениях. Если запрос к api может не пройти из-за серверных проблем api или сети, то лучше не выбрасывать исключение сразу, а попытаться сделать еще пару попыток, а уже потом выбрасывать исключение.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы