Комментарии 2
Как-то не очень понятно, каким образом брокер сообщений сохраняет метаданные и обеспечивает обновление статуса сообщений, да и пунктик про «не боялся большого количества сообщений (читай нагрузки)». Брокеры ведь тоже разными бывают: к примеру, IBM MQ из коробки гарантирует доставку сообщений exactly once, но относительно плохо масштабируется в сравнении с Kafka, которая гарантию доставки дает менее строгую (если речь о потребителе), и потому чаще требует использования различных паттернов для обеспечения идемпотентности. Также в статье не хватает, собственно, решения, как и не совсем ясно, зачем был перечислен стек технологий, если кода в статье нет :)
Также было бы интересно узнать, каким образом обеспечивается смена статусов сообщения, коих в вашем случае довольно много, что, вероятно, подразумевает наличие более чем одного сервиса, производящих некую обработку, что тоже может вызвать свои проблемы. Про SELECT FOR UPDATE SKIP LOCKED было сказано неплохо, хоть и в общих чертах.
Подводя итог, скажу, что Outbox как раз один из более простых в реализации паттернов, в отличии от какой-нибудь SAGA, где есть распределенные транзакции, но и тут много мест где можно споткнуться, и понимание концепции «сверху» далеко не гарантирует правильности итоговой реализации
«Как брокер сообщений сохраняет метаданные?»
— Тут я имел в виду, что при использовании паттерна «outbox» у нас появляется возможность без проблем сохранить данные и метаданные в табличку.«Как брокер сообщений обеспечивает обновление статуса сообщений?»
— Тут опять же речь не про брокер) Смена статусов происходит, в основном, внутри методов‑шедулеров. Если кратко, то, например: успешно отправили письмо из базы в брокер — перевели сообщение в статус «SUCCESS_SENT», получили ошибку при отправке — перевели в статус «REQUIRED_RESEND».«Не очень понятно про „не боялся большого количества сообщений (читай нагрузки)“»
— Здесь я имел в виду, что в случае использования «outbox» мы не обязаны обрабатывать каждый запрос на месте и бояться, что что‑то может пойти не так при большой нагрузке. Мы можем сохранять запросы в базу, и затем настроить параметры шедулера для отправки сообщений таким образом, чтобы не сильно нагружать ни себя, ни внешнюю систему. Да, при таком подходе в базе может быстро накопиться большое количество сообщений, но здесь уже «trade‑off»)«Брокеры ведь тоже разными бывают: к примеру, IBM MQ из коробки гарантирует доставку сообщений exactly once, но относительно плохо масштабируется в сравнении с Kafka»
— Пока что у меня опыта не так много, и про IBM MQ я даже не слышал)«Также в статье не хватает, собственно, решения»
— Здесь согласен, на будущее буду показывать фрагменты кода, чтобы добавлять больше конкретики. Спасибо!«Не совсем ясно, зачем был перечислен стек технологий, если кода в статье нет»
— Стек перечислил для того, чтобы в данном случае быть ближе к аудитории джавистов) Например, далее, в конце статьи, указал ссылку на подробное объяснение работы с шедулерами именно в Spring. Но в целом соглашусь — паттерн от языка вообще никак не зависит, и поэтому, может быть, стек действительно смотрится лишним.«Также было бы интересно узнать, каким образом обеспечивается смена статусов сообщения»
— Частично уже ответил на этот вопрос в 3-м пункте, но давайте еще подробнее. При получении запроса создается новая сущность для записи в базу, где по умолчанию подставляется статус «NOT_YET_SENT». Когда шедулер для отправки сообщений вытаскивает батч записей из базы — они на время локаются с помощью «FOR UPDATE SKIP LOCKED», а после — сразу же все переходят в статус «IN_PROCESS» + на записи здесь накладывается так называемое время аренды, чтобы другие транзакции не имели доступа к данным сущностям. После этого в цикле прохожусь по батчку, формирую запрос для внешнего сервиса доставки, и если сообщение получилось отправить в брокер — перевожу в статус «SUCCESS_SENT», если словил исключение, то перевожу в статус «REQUIRED_RESEND» или «FAILED_AFTER_SEVERAL_RESEND» в зависимости от типа ошибки. И соответственно, в статус «FAILED_AFTER_SEVERAL_RESEND» сообщение переводится, если замечено, что оно достигло лимита попыток отправки, например, в количестве 10 штук. И да, действительно, смена статусов происходит не в одном месте, но тут уже решают тесты и отладка)
В целом, большое спасибо за вопросы и замечания. Многое учту на будущее!

Мой первый outbox