4 ms·
One of the great things about the Elixir ecosystem is that, in so many cases, the libraries you’re using make the appropriate use of supervision trees so you do
by thruflo 3y ago
One of the great things about the Elixir ecosystem is that, in so many cases, the libraries you’re using make the appropriate use of supervision trees so you don’t have to.
Obviously it depends on what you’re building and you can craft your own supervision structures if you want to. But most of the time you can get the benefits of BEAM resiliency without having to drop down into the details.
- jlouis 3y agoThis sort-of stems from the underlying OTP principles from Erlang. Each application has their own isolated supervision tree, and your system contains a number of applications. Hence, a library which contains a service is likely to have their own internal supervision tree. Your code can then sort-of latch onto this tree and piggyback on its existence. This is very common in web applications because when a new connection is opened, you spawn a process to handle the connection. If connections are (de-)multiplexed into channels like in HTTP/2 and HTTP/3, you'd just move up one layer and spawn a process per channel. Likewise, if you have a limited resource such as Postgres connections, they are usually maintained in a pool, and access is queued until a connection from the pool is ready for use. This can circumvent the need for something like pg_bouncer in some use-cases.
- pests 3y agoThe one thing I dislike about Elixir is the confusion caused by how some libraries execute their functionality in-process and others spawn a supervision tree and message pass - putting your work in a possible queue that can get overloaded. Its a common pitfall for more inexperienced devs and I think its just a symptom of the language conventions. Everyone is taught genservers with a client-side API existing inside the same module as handle_ functions and it blurs the distiction some. I think if the convention was to create a separate module to implement the client-side convenience functions then the client-server split would be more obvious.
- lawik 3y agoYeah, there are a few common mistakes that can get really troublesome when library authors make them. Assuming how you want to structure execution (by using GenServers in the library usually). Another one is only one instance of config. Meaning if you have a plan to use the library for multiple distinct activities or with multiple accounts, you have trouble. Both simple config and GenServers have their place in libraries. But if a library doesn't expose the fundamentals it gets gnarly quickly.
- anonymousDan 3y agoWhen you say 'execute their functionality in-process', what exactly do you mean? In the context of the current process? Are there any good resources explaining when it is more appropriate to do one over the other?
- thibaut_barrere 3y agoOne example is HTTP libraries. For instance, take Mint (https://github.com/elixir-mint/mint https://github.com/elixir-mint/mint): > Mint is different from most Erlang and Elixir HTTP clients because it provides a process-less architecture. Mint is a low-level library which doesn't make attempt to manage processes (including HTTP pooling). In contrast, Finch (which builds on top of Mint) includes pool management: https://github.com/elixir-mint/mint#connection-management-and-pooling https://github.com/elixir-mint/mint#connection-management-an... It can take someone a bit off guard when they realise that the library they use provide a "default pool" they were not aware of, and that it can become a bottleneck etc.
- anonymousDan 3y agoGreat, thanks for that I'll take a look.
- iudqnolq 3y agoThere's a library for embedding inline svg icons. You call it with a string name in your html template and get back a string svg. It was originally implemented as a single GenServer. When you app started up it'd read the filesystem and create a map of svg name => svg contents in a process. Then each lookup call would send a message to that process and get back the contents. This has had the flaw of making template rendering single threaded. It's far worse than a file read per lookup
- cgio 3y agoThis is an allowed practice, just not idiomatic, mostly following on Erlang convention I think. If you do the coding gnome elixir course, he quite explicitly has a section on this and proceeds with separating API from server. At the end of the day, it is equivalent and all it takes is getting used to one or the other. I would argue spending the time to get used to the idiomatic way a community establishes is to your benefit in the end.
- jlouis 3y agoIt's an Erlang convention. Erlang suffers from having a very rudimentary module system, so a clean separation between the public API and the gen_server API isn't that easy to make. If you have access to a better module system, you should definitely induce a cleaner separation and adapt that as a convention. It helps people in general, but the in particular the less experienced.
- pests 3y agoI agree and love Elixir and use it daily. I think my downvotes above is really strange lmao. This is just a common footgun I see new developers struggle with.
- jongjong 3y agoI feel like Elixir get pushed too hard on people. Makes me skeptical. Same way I feel about TypeScript community. Calm down, it's just a programming language. I don't believe the programming language matters much. What matters is one's familiarity with it. There are good tools and frameworks available for just about any moderately popular language. Every language has caveats. Every language has lots of pros and cons and when you average them out, they're essentially all the same. Just a matter of personal preferences and habits.
- weatherlight 3y agoIt's not just a programming language—it's an entire philosophy centered around fault tolerance and concurrency, thanks to its foundation on the Erlang VM. While Elixir's syntax and features are certainly appealing, the real power lies in its integration with the Erlang VM. When people praise Elixir, a significant portion of that praise is directed at the capabilities you get with OTP/BEAM right out of the box. These include robustness, distribution, and real-time processing, which are not as readily available or as mature in other ecosystems. the Erlang VM is 38+ years old.
- sodapopcan 3y ago> The one thing I dislike about Elixir is the confusion caused by how some libraries execute their functionality in-process and others spawn a supervision tree and message pass. It's my assumption that needless process-starting is from classic OO developers trying to get something closer to the objects they're used to. I'm not sure separating the client and API logic in tutorials would necessarily stop them from doing this. People who are hellbent on shoehorning familiar idioms into an unfamiliar language are going to do so regardless. But I see what you're saying. I think it's more important to drill home that modules and processes have nothing to do with each other. I still catch myself conflating them once in a while three years in and it's caused the most confusion while trying to teach friends (although I'm not a particularly good teacher).