Назад к вопросам
Senior
4
Как реализовать сценарий: сохранить в базу, вызвать HTTP-запрос, обогатить данные и снова сохранить — транзакционно?
Компании, где спрашивали
Salmon
Ответ от нейросети
sobes.tech AI
Реализовать такой сценарий транзакционно сложно, потому что HTTP-запрос — внешняя операция, не поддерживающая транзакции базы данных напрямую. Вот как можно подойти к решению:
- Сохранить в базу — начать транзакцию и сохранить начальные данные.
- Вызвать HTTP-запрос — это вне транзакции базы, и если он упадёт, нужно откатить изменения.
- Обогатить данные и снова сохранить — обновить данные в базе.
Чтобы обеспечить атомарность, можно:
- Использовать
@Transactionalдля базы данных. - Выполнить HTTP-запрос внутри транзакции, но это рискованно, так как внешняя операция может быть долгой или нестабильной.
- Либо применить паттерн "саги" или компенсирующие транзакции, где при ошибке HTTP-запроса выполняется откат изменений вручную.
Пример с Spring:
@Transactional
public void processData(Data data) {
repository.save(data); // сохраняем
Response response = restTemplate.postForObject(...); // HTTP-запрос
if (response == null || !response.isSuccessful()) {
throw new RuntimeException("Ошибка HTTP запроса"); // вызовет откат транзакции
}
data.enrich(response.getData());
repository.save(data); // обновляем
}
Важно помнить, что HTTP-запросы не входят в транзакцию базы, поэтому если запрос прошёл, а коммит транзакции не случился, данные могут быть в несогласованном состоянии. Для критичных систем применяют более сложные схемы с очередями, сагами или распределёнными транзакциями.