Sobes.tech
Senior

How to implement a scenario: save to database, call an HTTP request, enrich data, and save again — transactionally?

sobes.tech AI

Answer from AI

Implementing such a scenario transactionally is complex because an HTTP request is an external operation that does not directly support database transactions. Here's how you can approach the solution:

  1. Save to the database — start a transaction and save the initial data.
  2. Make the HTTP request — this is outside the database transaction, and if it fails, changes need to be rolled back.
  3. Enrich data and save again — update the data in the database.

To ensure atomicity, you can:

  • Use @Transactional for the database.
  • Perform the HTTP request within the transaction, but this is risky as the external operation might be long or unstable.
  • Or apply a "saga" pattern or compensating transactions, where on HTTP request failure, changes are manually rolled back.

Example with Spring:

@Transactional
public void processData(Data data) {
    repository.save(data); // save

    Response response = restTemplate.postForObject(...); // HTTP request
    if (response == null || !response.isSuccessful()) {
        throw new RuntimeException("HTTP request error"); // triggers transaction rollback
    }

    data.enrich(response.getData());
    repository.save(data); // update
}

It is important to remember that HTTP requests are not part of the database transaction, so if the request succeeded but the transaction commit did not happen, data may be in an inconsistent state. For critical systems, more complex schemes with queues, sagas, or distributed transactions are used.