Sobes.tech
Назад к вопросам
Senior
4

Как реализовать сценарий: сохранить в базу, вызвать HTTP-запрос, обогатить данные и снова сохранить — транзакционно?

Компании, где спрашивали
Salmon

Ответ от нейросети

sobes.tech AI

Реализовать такой сценарий транзакционно сложно, потому что HTTP-запрос — внешняя операция, не поддерживающая транзакции базы данных напрямую. Вот как можно подойти к решению:

  1. Сохранить в базу — начать транзакцию и сохранить начальные данные.
  2. Вызвать HTTP-запрос — это вне транзакции базы, и если он упадёт, нужно откатить изменения.
  3. Обогатить данные и снова сохранить — обновить данные в базе.

Чтобы обеспечить атомарность, можно:

  • Использовать @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-запросы не входят в транзакцию базы, поэтому если запрос прошёл, а коммит транзакции не случился, данные могут быть в несогласованном состоянии. Для критичных систем применяют более сложные схемы с очередями, сагами или распределёнными транзакциями.