10

I would like to clarify what'd be the best way of organizing architecture.

I've got rest api and microservices architecture. I have applied the Database per Service pattern.

So let's imagine that the user wants to create an order(an e-commerce system). But users can have a credit limit. So the flow will be as below:

  • OrderService creates a pending order. Then push an event about it.

  • UserService processes that event and publishes either a credit limit exceeded event or a credit reserved event.

  • OrderService receives the event and changes the state of the order to either approved or canceled.

All look good. But the question is what the user will do during this simple flow? I mean: the user makes a POST request /orders and ...

  1. Web-service awaits until the order gets approved or canceled(includes surely timeout)?
  2. Web-service returns 200 ok and then the user needs to check the order state with some interval?
  3. use web sockets?
  4. something else?

Unfortunately, Any option from above has its advantages and its disadvantages.

The challenge is that I described the simplest case. In reality, tens services(even third party) could be involved. And of course, I am expecting a high load. So the queue may be filled.

Please propose the solution to discuss. I'm greatly appreciating for an answer as well as links to production ready system documentation.

  • 1
    Hi~ David it been a while for this question, do you get any idea for this question? – cYee Jun 01 '21 at 15:59

4 Answers4

1

Kudos for a good question. If we look at Saga Pattern, it offers to do ACID like transactions in a distributed system but with some trade-off. One of the trade-offs is Ensuring Rollback if any of the service or entity fails to do what it was supposed to do. This can go even complex if you have more than 5 services completing a Saga. Though it will be a Highly Scalable option if you can orchestrate.

Here I will propose Following,

  • User Does a POST request for order
  • OrderService first checks with UserService regarding credit Limit (It can be a REST API call as it might be a simple DB call for UserService)
  • Then OrderService can act upon based on the return response from UserService

Advantages of this approach

  • User can see an immediate response
  • Less Complex to code thus testable and maintainable Code

Disadvantages of this approach

  • This solution will not be effective if there are too many external (third party) rest api calls
  • It can introduce single point of failure

The main thing is, all the options will have trade-offs. It is on you to decide which one suits you the best.

0

According to me

Follow the my rule - Validate First then action

Validate the order before its goes to order service on UI. You can call the userservice api on UI which gives info user can make a order or not.

Step 1. On UI call the userservice API , which validate the user credit limit

Step 2. If validation success or fail

Step 3. Take the action according to step2 result . If success call the order service if not do what you want to do (Call other service etc..)

Advantage

  1. A good user exprience - User get the validation message "you can not make a order your limit is low" or something like that when trying to make the order. Not at the end get a message "You limit is low/or anything"

  2. Less Complexity of code

  3. A more microservice Arch. -

Since your are follow the microservices then if you call the userservice inside the orderservice means orderservice is dependent on it or you can say tightly bound - here your are lossing the benifit of mircroservice arch.

What happen if the userservice is down. The customer cannot make the order or if you change anything in userservice response then you have to change the orderservice also.

What you do if some more validation (to call other service) need in future before making the order.

  1. Redirection Flexibility - Suppose if on fail of validation from userservice then you have to call other service( other independent microservice ) and if you are using the other service inside the orderservice the no of service increases as project grow

  2. Less Request on OrderService - Request goes orderservice only when the validation is passed from the other service or other thing.

So from my point of view

  1. Try to make microservice independent as much possible.

  2. Validate First and action.

  3. A good user exprience

  4. Easy to handle load (if you think)

With all that , now you less dependent on saga.

Its only my opinion - choose what you think best according to your domain

Ashwani Tiwari
  • 1,497
  • 18
  • 28
  • Have any confusion ask in comment – Ashwani Tiwari Jul 14 '19 at 20:23
  • I totally agree with about validation on client side for better user experience. Thanks. But orderservices does not depend upon userservice at all. It just sends an event and subsribes&waits for credit reserved or credit limit exceeded event – David Markwell Jul 15 '19 at 14:55
0

The question is what the user will do during this simple flow? I mean: the user makes a POST request /orders and ...

You can reply to user the created orderId with status 'pending' while your saga is running. The request should be ended in 200.

How does user get the status?

Push notification, websocket, email, sms. it is up to you to notify the user about the status of event, success, failure, waiting_for_approval.

1. Web-service awaits until the order gets approved or canceled?
2. Web-service returns 200 ok and the user check the order state with some interval?
3. use web sockets?
4. something else?
  1. Not recommended. Saga should be asynchronous. Waiting for reply is synchronous (request/reply style).
  2. This will work, but if your saga is long running, it might be problematic, eg: anything with validation/approval by a human.
  3. This will work assuming you are replying 200 after order creation in pending state, one thing is that you have to make sure your websocket is active, or else, you still have to notify them through email, sms.

Unfortunately, Any option from above has its advantages and its disadvantages.

You have to choose your poison.

The challenge is that I described the simplest case. In reality, tens services(even third party) could be involved. And of course, I am expecting a high load. So the queue may be filled.

Use orchestrated saga (sort like) Netflix conductor, Uber Cadence, Temporal (Similar to Cadence). This will allow you to do something as shown below. At least, easier.

A flow diagram from google shopping api and how they handle it. enter image description here

Link for more: https://developers.google.com/shopping-content/guides/about-orders

cYee
  • 1,915
  • 1
  • 16
  • 24
0

There is little difference in cancelling an order because there was a problem with the credit limit vs. cancelling it because a forklift ran over the package in the logistics facility.

So a relatively simple solution is to reply with an order accepted and status 200 when the order is placed put that in a queue and let the saga run asynchronously. You should provide both an API (and UI) for the user to check the order status and proactively send status updates like billing going through (which is your fist saga) and also other sagas in the order lifecycle Regarding how to send notifications that depends on the usage scenario (e.g. you can do a callback for a system-to-system integration, but maybe you want to send an email/sms to an end-user etc)

Arnon Rotem-Gal-Oz
  • 25,469
  • 3
  • 45
  • 68