0

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 ?

1 Answers1

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

Ewan
  • 83,178