dmarko484

dmarko484

Umbrella apps and internal microservices like communication

Still trying to find some nice way how to decouple apps within my umbrella based application. Lets assume I have umbrella base CRM/ERP like app. I have apps like:

  • customers
  • projects
  • helpdesk

Now what when project app requires the list of customers for selection box. Common approach to decouple such apps is to expose their api as microservices. But its rather too big for app that contains all the code. But I still want to make straight borders among apps internaly and don’t want apps to reference each other direcly (e.g. by calling Crm.Customers.Repo.list() from project app). I’m thinking about the internal microservice architecture, where each umbrella app would exposes its API via GenServer like process. So when project requires list of customers then project code will not call customers module directly (not calling Crm.Customers.Repo.list()) but rather ask GenServer process for list of users. GenServer message like communication seems to make nice decoupling for inter app comunication.

Using this approach each individual umbrella app would run GenServer api process that would handle inter app communication. Is this right idea or how do you suppose to handle such code decoupling? Do you see any bottlenecks for such approach ?

e.g. having  genserver: Customers.API, Projects.API - now I can send message to Customers.API process (via Registry???) with payload {:customers-list} to get list of contacts. The same way I can call {:company-save, %{ data to be saved }} to save record etc.

I this good idea?

Most Liked

peerreynders

peerreynders

Right out of the gate we need to understand

there is a price for loose coupling: complexity. Loosely coupled distributed systems are harder to develop, maintain, and debug.

(more)

That being said loose coupling is an important aspect in designing for replace-bility.

Is the data for these applications actually stored in distinct databases? If it isn’t, you may already be in trouble from the autonomy perspective. If it is all stored in the same database it may make sense to create a separate set of queries for each application - if you have a look at diagram in the Bounded Context article you will notice that both the Sales and Support context have their own, separate Customer representation tailored to the specific needs of that context rather some singular canonical representation - because sharing of all-in-one representations can lead to coupling to irrelevant details.

Even it you decide to go the GenServer route you may want to think about Consumer Driven Contracts - i.e. have the GenServer(s) under the control of the Customer application but deploy a separate GenServer for each distinct Customer representation.

Another tactic is Command Query Responsibility Separation. I.e. if modifications to customers is permitted from outside of the Customer application the simplest implementation could offer separate GenServers for query messages and for update messages - simply to get the benefit of keeping these concerns separate.

Now I’m not saying that any of the above applies to your particular case, likely most if not all would be considered over-engineering. But it’s probably worth your time to explore these options and document why any particular option was dismissed (in many cases it is just as important to know what was considered in the past and why particular avenues were not pursued).

Spolier

https://pbs.twimg.com/media/CrMQLVYXYAETGuW.jpg

DianaOlympos

DianaOlympos

Ok so… there are so much things to say here…

  1. Loose coupling reduce complexity to me :smiley: there is a fight to do here..

  2. [quote=“dmarko484, post:1, topic:3636”]
    But I still want to make straight borders among apps internaly and don’t want apps to reference each other direcly (e.g. by calling Crm.Customers.Repo.list() from project app)
    [/quote]

Why ? Where is the problem that make you want to do things like that?

Why not have a client lib and a server lib? There are use case when you may want to not call code directly but… you lose all the advantage of functions and public API idea. The whole idea of a public API is to exactly hide these gateways.

kelvinst

kelvinst

I like the idea, but I would be very cautious about the granularity of this services. Sometimes we tend to overengineer when it comes to microservices. Instead of doing the microservices separated by resources themselves, I would separate them by bounded contexts (thank you @peerreynders for giving me the name of the concept).

Where Next?

Popular in Questions Top

New
Kurisu
For example for a current url like http://localhost:4000/cosmetic/products?_utf8=✓&query=perfume&page=2, I would like to get: ...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lists...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

Other popular topics Top

danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29377 241
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
marick
I had some trouble figuring out how to make many-to-many associations work. Once I got it working, I wrote a blog post. Because I’m a nov...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New

We're in Beta

About us Mission Statement