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).

Davidsoff

Davidsoff

my two cents:

Microservices should be decoupled in time. This means that your project should not be dependent on your CRM system to be up.

this means that you can have your Project service listen for Change Events published by the CRM system and save the relevant information in its own database

that way even if you manage to completely destroy your CRM system you will still have a fully functional Project system

other good information on the topic: https://plainoldobjects.com/2015/09/02/does-each-microservice-really-need-its-own-database-2/

Where Next?

Popular in Questions Top

shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
pgiesin
This should be a simple problem but I just can’t seem to figure it out. I have a standalone Elixir app that won’t find the database. Dep...
New
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
chewm
Hi guys, nice to meet you to the whole forum, I’m new here, I’m trying to configure visual studio code for elixir, right now the intellis...
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
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs & Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3268 119930 1237
New
JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
peerreynders
Manning 2016 Halloween weekend sale via Deal of the Day Friday, October 28 - Half off all MEAPs - code WM102816LT Saturday, October 29 ...
326 29600 154
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
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
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New

We're in Beta

About us Mission Statement