<div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><span style="font-family:Arial,Helvetica,sans-serif">On Wed, Apr 29, 2020 at 6:47 AM <<a href="mailto:jdmeta@gmail.com">jdmeta@gmail.com</a>> wrote:</span><br></div></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div lang="EN-US"><div class="gmail-m_8493333390461536999WordSection1"><p class="MsoNormal"> <br></p><p class="MsoNormal"><u></u></p><p class="MsoNormal">below is a trivial example of this scenario where a top-level service is decomposed into xService and yService which run concurrently.<u></u><u></u></p><p class="MsoNormal">however, while yService performs some sub-task concurrently, it ultimately needs the output of xService to finish this sub-task (in this contrived case, to know which downstream service to send a message to where said message is some union of the work of xService and yService).<u></u><u></u></p><p class="MsoNormal"><u></u></p></div></div></blockquote><div><br></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">To me, this is the key dependency. Since yService needs the output of xService, There is a dependency x -> y. Hence, it is not clear to me why it has to be two services in the first place. I'd probably just spawn a process per work-unit at the top level and then let the code run sequentially inside those processes, performing the job of x, then y, then z. Assuming there are a lot of work-units coming through the system, this is eventually going to saturate your processing cores. </div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">In general, there are two patterns I tend to see in concurrent systems. One is where you have relatively few processes, and they then forward messages along "channels" forming a processing network that's relatively static. It is common if creating processes tend to be expensive (like the need for an OS-thread or something such, or if a new thread has considerable memory overhead). The other, you make the message itself into a process and spawn a process per message. If creating a new process is cheap, this is more common. Erlang likes the latter approach[0]. You don't have a single graph in which multiple messages are flowing. You have a million graphs in each of which a single message is flowing. And that graph is usually represented by tail-calling functions. Of course, you have to handle access to limited resources in such a system. But this can often be done by factoring through a manager-process of some kind handing out tokens whenever a resource is available.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">The other reason a process-per-message approach could be alluring is that it often limits message communication. That tends to make for a simpler program where fewer things can fail along the way.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">[0] Any language with cheap process creation tend to be viable. Go could also be used for this approach, even though it has access to a channel primitive.</div><br></div></div></div>