Комментарии 9
Благодарю! Возьму в свой проект
В этой архитектуре есть один существенный изъян: при большой нагрузке авто вакуум будет сильно ресурсов кушать. Лучше модернизировать архитектуру так: добавляем интерфейс, в дефолтной реализации которого удаляем по одному, а при необходимости пользователь библиотеке переопределит этот интерфейс с использованием партиционирования
Удаление старых записей стоит еще и по статусу проверять, а то мало ли что.
Интересно. Плюсую
Есть еще вариант использовать debezium и kafka connect, для чтения outbox таблицы и пересылки сообщений в топики
Перед созданием велосипеда можно ещё поискать готовый
good
Что-то не могу понять код: если кто-то выдернет питание из сервера (упадём по OOM и т.п.) между строчками 1 и 2 - то кажется в Kafka всё улетит, но в БД не будет отмечено как отправленное и при следующем подходе к снаряду улетит ещё раз. КМК Exact Onсe не будет
1: val updateIds = waitingMessages.mapNotNull { it.id }
2: outboxMessageRepository.updateSentStatusByIds(updateIds)А если в ходе отправки в Kafka тоже вылетит исключение... тут я даже анализировать не хочу, что куда улетит и отметится, со Spring-овым transaction silentrly rolled back.
Да, дублирование возможно, но это не баг кода, а ограничение стандартного outbox-подхода без Kafka transactions. Понятно, что такое может случится и мы действительно пошлем сообщение 2 раза. Я писал, что показал самую дефолтную реализацию.
Но про питание и OOM можно много где написать, что нет защиты. Но как часто у вас были такие примеры, что выдернули шнур?
OOM можно стабилизировать кол-вом записей, которые мы достаем. Есть еще практика выделять шедулеры или консюмеры в отдельные инстансы, чтобы они работали независимо.
Как по мне подход к решению проблем, которые вы описали это больше комплексный подход всего проекта, а не конкретного стартера)

Spring-boot-starter для паттерна Transaction outbox Kafka