Home > OS >  How to implement synchronous transactional system?
How to implement synchronous transactional system?

Time:07-09

Let's image that we have a simple endpoint called CreateEntity in some .NET Core controller and we have two services which saves the entity to the Mongo and Neo4j databases (in this particular order).

I want to implement some pattern to make sure that we have consistent data.

Why ?

Because we might have situations when entity is added to Mongo, but the call to the Neo4j crashes. And that means the data remains inserted in the Mongo.

One solution is to use try-catch statement for second service call and use compensating transactions for Mongo insert. In this case, remove the entity from Mongo. Another one could be using a state for entity and put Pending as initial state and mark it as Completed after Neo4j call is made with success.

I also looked over SAGA and 2PC patterns but they are used in asynchronous contexts and across microservices (you know, by communicating between microservices with RabbitMQ, Kafka, Service Bus & other)

But in my case there is a single microservice. Any ideas on this ?

CodePudding user response:

You want to wrap your mongo operations in a transaction. If the Neo4j fails, roll back the mongo transaction, if it succeeds, commit it.

CodePudding user response:

Temporal open source project can be used to implement compensations and SAGAs in synchronous scenarios. The basic idea of Temporal is that you write your code as a failure of the code that performs remote calls cannot happen. In case of a process failure Temporal is going to migrate the execution to a different machine in exactly the same state as before the crash. The state includes all local variables and blocking calls. Here is a SAGA example using Temporal Java SDK:

public void bookTrip(String name) {
    // Configure SAGA to run compensation activities in parallel
    Saga.Options sagaOptions = new Saga.Options.Builder().setParallelCompensation(true).build();
    Saga saga = new Saga(sagaOptions);
    try {
      String carReservationID = activities.reserveCar(name);
      saga.addCompensation(activities::cancelCar, carReservationID, name);

      String hotelReservationID = activities.bookHotel(name);
      saga.addCompensation(activities::cancelHotel, hotelReservationID, name);

      String flightReservationID = activities.bookFlight(name);
      saga.addCompensation(activities::cancelFlight, flightReservationID, name);
    } catch (ActivityFailure e) {
      saga.compensate();
      throw e;
    }
  }

Unfortunately, the .NET SDK for Temporal is still under development as of the summer of 2022. The currently supported languages are Typescript/Javascript, Go, Java, Python & PHP.

For .NET you can also use Durable Task Framework and/or Azure Durable Functions that are based on the same idea as Temporal.

  • Related