Saša Jurić writes about Erlang and Elixir, covering concurrency, processes, macros, and the Phoenix framework.
HN commenters recommend it as a source of very good articles on Elixir and Erlang, including pieces on spawning processes and macros.
RabbitMQ is IMHO probably the best open source example tackling a large, complicated real world problem with graceful degradation (e.g. if a queue keeps crashing).
Elixir has a lot of smaller but very high quality libraries to learn from. You may be interested in how Ecto & Postgrex manage DB connections, in particular how connection sockets are “borrowed” so data doesn’t get repeatedly messaged (read: copied) between processes. Bandit / Thousand Island also make interesting decisions for process structure in HTTP1.1 vs HTTP2.
I think a common mistake is to create processes mimicking classic OOP structure, like an OrderProcessor, ShippingManager, etc. Processes in Erlang are a unit of fault tolerance, not code organization. This means more usually you’ll have one process per request, potentially calling code from many different modules; since requests are the things you want to fail separately from each other.
In RabbitMQ’s case for instance connections and queues are processes, but exchanges are not. It would feel natural to model the problem as three processes with messages going Connection -> Exchange -> Queue, but in reality an exchange is a set of routing rules that can be applied by a connection directly, which avoids a lot of complexity and overhead.
Last thing I’d note is supervision trees etc. are really about handling _unexpected_ errors (Joe uses the terms faults and errors with different meanings iirc). If you want a web request to be retried a few times with…
"Erlang based systems obtain many of the aforementioned properties from the Erlang concurrency model. Erlang handles the concurrency itself instead of relying on the OS. A concurrent entity in Erlang, called Erlang process, is much lighter than a standard OS process or thread, initially using about 3 KB of memory on a 64bit system. In a typical Erlang systems, you can easily create hundreds of thousands or maybe even millions of Erlang processes. The Erlang virtual machine uses its own scheduler which ensures that each process gets a fair share of execution time. The scheduler also distributes processes over available CPU cores, using as few OS threads as possible (by default only as much as the number of available CPU cores)."
http://www.theerlangelist.com/2012/12/yet-another-introduction-to-erlang.html
It is kind of like Node in that it is very easy to do concurrent stuff, except instead of nested callbacks and all that jazz, you write 'processes' which are designed to share nothing. They run akin to OS threads in that one process crashing won't bring down the whole system (unlike Node). As no state is shared it also means that they can easily (i.e. it is built into the VM, and switched on by default) be scaled up to run over many cores. If you are interested, you might want to look at Elixir (a language built on top of the Erlang VM) which has a more Ruby-esque syntax: http://elixir-lang.org/
EDIT: Should also point out that I think "Jessica's" comment was just…
Programming languages, being technologies, are subject to the Lindy effect (https://en.wikipedia.org/wiki/Lindy_effect).
This means that the younger a language is, the lower its life expectancy. This is why the neomania in JavaScript framework
land is so chaotic. Even if a better framework emerges and takes off in popularity over a few months, it's unlikely to last in
the mainstream for another year. When I'm choosing something to study programming-wise, I use
this heuristic as part of the decision-making process. For example, studying algorithms and data structures is more robust
than studying Vue.js or GraphQL, which are not likely to be around in a few years.
Elixir was just released 5 years ago, and despite some success, has not taken off as much as the absolute top programming languages released around that
time. For example, Go, released just 2 years earlier, is by far the most successful of new languages from the last 10 years.
Given my skeptical mindset towards neomania, it might surprise you to hear that I'm a huge proponent of Elixir!
Here are my reasons for studying Elixir and using it exclusively for my non-work projects, despite there being
countless other recent, appealing languages:
- Although the language is young, it's built on Erlang, which is 30 years old. Even if Elixir fails, there is a lot
of knowledge transfer between the two languages (probably 90% of what I learn from using Elixir transfers directly over
even if I switch to exclusively…
I don't actually agree that the ecosystem is weaker than Rails. There may be fewer hex packages than Ruby gems, but after 10 years worth of doing my own Rails work and cleaning up other people's messes, I can safely say that most of the gems in the ecosystem are antithetical to well-designed modular software.
Bottom line, learning to write software well is hard, no matter what language you're in. What is probably weaker in the Elixir sphere is the amount of blog posts that go deeper than "Yay elixir", but there are some really high-quality books that are a good subsitute. Here's the order I usually recommend for new Elixirians:
1) Dave Thomas' Programming Elixir
2) Sasa Juric (http://theerlangelist.com/) Elixir in Action (blog is also great)
3) Programming Phoenix (Jose Valim, Chris McCord, Bruce Tate)
4) Lance Halvorsen's Functional Web Development with Elixir, OTP, and Phoenix should probably be in there somewhere but I'm not sure where, as I haven't had a chance to read it yet.
5) Designing for Scalability with Erlang and OTP is a good followup when you're comfortable with the syntax and concepts from OTP
[1] https://pragprog.com/book/elixir13/programming-elixir-1-3
[2] https://www.manning.com/books/elixir-in-action?a_aid=sjuric
[3] https://pragprog.com/book/phoenix/programming-phoenix
[4] https://pragprog.com/book/lhelph/functional-web-development-with-elixir-otp-and-phoenix
[5] http://shop.oreilly.com/product/0636920024149.do
I have more than 10 years of professional experience using C++, C# and Ruby to develop "classical" business web and desktop apps.
I started using Erlang two years ago to implement a push server, and fell in love with it immediately. The language has its quirks, but the virtual machine is fantastic, and it really makes it easier to manage massive concurrency, which is almost always the case on the server side.
If you find the language too strange, you should also check Elixir, a Ruby flavored language which compiles to the Erlang bytecode and can normally cooperate with other Erlang code. Starting this year, I am adding new feature for my Erlang based system using Elixir as much as possible.
At the moment, you should really be familiar with Erlang to be able to fully understand and utilise Elixir.
Other alternatives to Erlang would be Go, Scala/Akka, or reactor based platforms such as node.js or EventMachine. Also, probably Haskell and Clojure, but I'm not really familiar with those. Personally, I find them all to be inferior to Erlang VM, although Go and especially Scala/Akka are really close. I wouldn't recommend reactors despite my great affection for both Ruby and Javascript.
Some detailed ramblings on what I really love about Erlang can be found on my blog:
http://www.theerlangelist.com/2012/12/yet-another-introduction-to-erlang.html
http://www.theerlangelist.com/2013/01/erlang-based-server-systems.html
While I don't disagree entirely, I find that Elixir is actually quite functional. Using processes for state as if they're objects is generally considered bad practice.
I can highly recommend this article (also just in general for people curious about Elixir): http://theerlangelist.com/article/spawn_or_not
A quote:
> But before starting, since this is going to be a long article, I want to immediately share my main points:
> Use functions and modules to separate thought concerns.
> Use processes to separate runtime concerns.
> Do not use processes (not even agents) to separate thought concerns.
> The construct “thought concern” here refers to ideas which exist in our mind, such as order, order item, and product for example. If those concepts are more complex, it’s worth implementing them in separate modules and functions to separate different concerns and keep each part of our code focused and concise.
> Using processes (e.g. agents) for this is a mistake I see people make frequently. Such approach essentially sidesteps the functional part of Elixir, and instead attempts to simulate objects with processes.