Comments 9
Если сторонний сервис вернул вам 500, то это не значит, что он не отправил письмо. Делая 10 попыток, вы рискуете отправить клиенту 10 одинаковых писем, если у стороннего сервиса нет защиты от повторной отправки. И еще, возможно, заплатить за эти 10 писем.
Абсолютно верно. Поэтому я говорю о важности идемпотентности — повторный вызов сервиса не должен приводить к дубликатам писем. С другой стороны, даже если внешний сервис не предоставляет никаких ключей идемпотентности в своих API, 500 ошибка скорее идентифицирует некорректное поведение и провал запрошенной операции — что говорит в пользу Retry.
Когда пришло 500, значит, они там что-то не обработали. Может быть как раз не записался у них ключ идемпотентности в базу после отправки )
Тут, конечно, сам каждый решает, что делать, но в общем случае 500 у стороннего сервиса - это полная неопределенность, и нужно просто определить, что хуже - не отправить письмо, или же возможно отправить его повторно.
client-generated ID
Не развернёшь мысль пожалуйста? Автор комментария имел в виду, что даже используя ключи идемпотентности, 500 ошибка может также означать риски нарушения самой идемпотентности. В таком случае, у нас появляется большая проблема в валидации текущего состояния.
Например, мы отправляем сообщение группе людей из 3 человек, двум сообщение пришло, а одному нет из-за ошибки. Что должно произойти при следующем запросе на отправку этого же сообщения. Видимо это зависит от гарантий на стороне сервиса и имплементации идемпотетности сервиса, и это всегда стоит иметь в виду.
Я имел в виду, то что ключом идемпотентности может быть ид сгенерированный на стороне клиента, если у нас у клиента есть уникальный ИД. Если нет, то мы перед тем как что-то рассылать кому-то можем запросить уникальный ключ идемпотентности на сервере.
В случае с рассылкой сообщений мы можем организовать таблицы так [сообщение][ключ-идемпотентности] <-> пользователь. У нас на момент повторной отправки сообщения окажутся две записи. Следовательно, мы сможем отправить сообщение только одному пользователю.
Самыми популярными очередями сообщений являются Apache Kafka, Rabbit MQ, AWS SQS, Azure Message Queue
Или — просто SMTP-сервер, самый простейший. Потому что многое желательное из того, что описано статье (за «все» не скажу, там надо анализировать подробнее), является стандартными возможностями самого протокола SMTP.
«На земле» сервер SMTP можно было поднять на любом сервере — в Windows Server он является стандартным компонентом, и никаких дополнительных денег MS за него не просит, а в Linux Postfix AFAIK (однако не специалист я по всяким разным дистрибутивам Linux, чтобы утверждать это с уверенностью) тоже входит в стандартный комплект.
Но вот как дело обстоит в облаке — за это я не скажу.
Сам я неоднократно использовал именно компонент SMTP-сервера из Windows Server как раз для безотказного приема уведомлений от всяких капризных служб (внутренний мониторинг железок, не слишком хорошо написанные программы), потому как штатный MS Exchange, бывает, считает, что он сейчас перегружен и возвращает 4xx код (ну, вообще-то это — штатное поведение SMTP, но почему-то не все его учитывают).
Спасибо за интересное замечание. Знаешь ли ты какие есть недостатки у этого подхода с использованием, например, MS Exchange? Поправь или дополни пожалуйста, если где буду не прав:
Время приёма сообщения может варьироваться в зависимости от настроек батчинга, т.е. например через 5 секунд от времени отправки.
Производительность самого протокола достаточно лимитированная, из источников в интернете ~10.
В отличие от Message Queue, где автоматически реализованы peek-lock/иные механизмы, в MS Exchange нам придётся реализовывать всё самим?
Техники обработки отказов сервиса в микросервисных архитектурах, или Альтернативы Circuit Breaker