0

This question already has an answer here:

We're starting to work on microservices to rebuild our legacy application, piece by piece. We started by building a register module which is responsible for the whole register process.

To simplify, let's say the RegisterModule will use a CustomerModule to persist a customer, and then a PhoneModule that needs a customer_id to persist a phone in the database.

CustomerModule would look like this in pseudocode :

<?php

class CustomerModule 
{
    public function createCustomer(array $inputs)
    {
        $this->checkInputs($inputs);
        $customer = $this->repository->create($inputs);
        $this->phoneModule->createPhone($customer->getId(), $inputs);

        return json_encode(['data' => '1']);
    }
}

checkInputs would throw an exception handled by the upper layers in the module which would return the errors to the RegisterModule with the right HTTP code. Nothing persisted, data is consistent.

Now with the PhoneModule pseudocode :

<?php

class PhoneModule
{
    public function createPhone(integer $customerId, array $inputs)
    {
        $this->checkInputs($inputs);
        $phone = $this->repository->create($customerId, $inputs);

        return json_encode(['data' => '1']);
    }
}

Again, when checkInputs encounters a validation error, nothing will be persisted for that microservice. But the problem here is that the CustomerModule has already persisted a customer in its database. But this customer has no phone associated which is not what we want.

I have read a lot about distributed transactions. My CTO does not want to hear about eventual consistency (and in this case I'm 100% on his side). Most solutions I have seen look very hard to implement, and I'm not even sure those are the tools we need to solve this problem.

A solution could be to do all the checking beforehand, and then do the persisting actions. But that either would mean duplication of checking in both the persisting and the checking routes, or that mean we could persist without any check if we "forget" to do the checks beforehand.

How do you handle this in the most simple way ?

marked as duplicate by Doc Brown, Bart van Ingen Schenau, gnat, Laiv, Community Feb 20 '18 at 10:48

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    This is very common problem. Whether your CTO dislike eventual consistency or not. The problem will remain the same. Forget the concept of ACID transacations in distributed computing. Embrace its falacies :-). – Laiv Feb 6 '18 at 22:29
  • 2
    You will need to embrace Eventual Consistency in Distributed Environment. But in your case break up of your applications in diff. services is not correct. For eg: why phone is a separate module , i would have a CustomerAggregate(if notion of aggregate is not clear, consider it one logical service for now), and i will provide phone to Customer only and it will be persist in single transaction. Creating a diff. phone module why??? Also you could read about Domain Driven Design to better breakup your services – techagrammer Feb 7 '18 at 5:25
  • @techagrammer I agree with your comment, even though it doesn't really answer my question I think you're 100% right. – Steve Chamaillard Feb 7 '18 at 9:00
  • Here is a series that describe how to build an SOA project the right way. – Zapadlo Feb 7 '18 at 9:05
2

If you don't want to ever have a customer without a phone or a phone without a customer then they should be in the same repository.

You can then use transactions as normal to roll back failures

Not the answer you're looking for? Browse other questions tagged or ask your own question.