Live data from Hacker News

Elixir GenServer Explained

papercups.io

11–20 of 91 posts

Re: Elixir GenServer Explained

#11

Maybe a dumb complaint, but I hate the name. I have a really hard time not reading it as the active name "Generate Server". Like, I'd expect it to be a function that generates servers (whatever that means, since what it's dealing with isn't something I'd normally call "a server" either). It bugs the hell out of me every time I read Elixir code. One of those things I have to keep reminding myself: "OK, it's not what i…

When I first came to Elixir & Erlang, their naming convention gave me no trouble at all. Now of course, I haven't done much for decades with languages that would have given me the mental model that would bias me to automatically be thinking of the things you name. I do know that there are certain well-worn development environments where you might gain such a bias.

Remember that Erlang, too, and some of these technologies, names, and conventions, are pretty old and that they may not have been as evocative then as they might be today with some of their conventions. "Process" almost certainly would have been confusing to the neophyte, but appropriately descriptive nonetheless, but "Gen" for Generic.... eh.

Anyway I guess the point is that I have to look inward to see if something like this rubbing me the wrong way is the substandard choice of the project I'm diving into, or if it's me bringing unwarranted biases and assumptions to the table.

Re: Elixir GenServer Explained

#13
post #10

Earlier quoted context omitted.

It's "generic" server: http://erlang.org/doc/man/gen_server.html

The sooner you start smacking people with tribal knowledge, the sooner many people start to back away slowly. I used to interview ex-coworkers. I don't do it as much anymore because it gets old/depressing and the answers tend not to change that much. If, for the purposes of thinking about turnover, you look at a former colleague as an 'aggrieved party', we are generally somewhere in the neighborhood of mediocre at ag…

What? GP's response is terse but not impolite, and explaining what an abbreviation means is a far cry from "smacking people with tribal knowledge", it's just table stakes explanation in a field which requires precision.

The only reason modern computing got where it is today is by standing on the shoulders of giants. If we go back and re-litigate every naming decision of the past several decades just to make newcomers feel welcome, all progress will slow as we collectively devolve into continuous bikeshedding.

Re: Elixir GenServer Explained

#14

Maybe a dumb complaint, but I hate the name. I have a really hard time not reading it as the active name "Generate Server". Like, I'd expect it to be a function that generates servers (whatever that means, since what it's dealing with isn't something I'd normally call "a server" either). It bugs the hell out of me every time I read Elixir code. One of those things I have to keep reminding myself: "OK, it's not what i…

You got downvoted, but I agree. "Gen" is very typically used as a shorthand for "generate", whereas I've _only_ seen it used as a shorthand for "generic" in the Erlang/Elixir world.

Re: Elixir GenServer Explained

#15

Maybe a dumb complaint, but I hate the name. I have a really hard time not reading it as the active name "Generate Server". Like, I'd expect it to be a function that generates servers (whatever that means, since what it's dealing with isn't something I'd normally call "a server" either). It bugs the hell out of me every time I read Elixir code. One of those things I have to keep reminding myself: "OK, it's not what i…

Is "general" or "generic" more misleading than "generate"?

[deleted]

Re: Elixir GenServer Explained

#16
post #5

Since these insert events are being buffered, what happens if the process dies? Are all of those inserts lost? I feel like Erlang/Elixir is designed to handle cases like this robustly, but it's not clear to me how this code avoids losing data when a process crashes, potentially up to 5s worth of updates!

Furthermore I have heard it is actually possible for casts to be dropped under load. I am having a hard time confirming this, and had a hard time confirming it back then too. And even worse, I realize most of the time we code as if the casts will be reliably delivered.

Can someone chime in on this?

Re: Elixir GenServer Explained

#17

Maybe a dumb complaint, but I hate the name. I have a really hard time not reading it as the active name "Generate Server". Like, I'd expect it to be a function that generates servers (whatever that means, since what it's dealing with isn't something I'd normally call "a server" either). It bugs the hell out of me every time I read Elixir code. One of those things I have to keep reminding myself: "OK, it's not what i…

You got downvoted, but I agree. "Gen" is very typically used as a shorthand for "generate", whereas I've _only_ seen it used as a shorthand for "generic" in the Erlang/Elixir world.

I have sympathy for gp. But also, naming things is hard. Wait till you dig deeper into the erlang rabbit hole and discover the undocumented gen module.

Re: Elixir GenServer Explained

#18
post #16
post #5

Since these insert events are being buffered, what happens if the process dies? Are all of those inserts lost? I feel like Erlang/Elixir is designed to handle cases like this robustly, but it's not clear to me how this code avoids losing data when a process crashes, potentially up to 5s worth of updates!

Furthermore I have heard it is actually possible for casts to be dropped under load. I am having a hard time confirming this, and had a hard time confirming it back then too. And even worse, I realize most of the time we code as if the casts will be reliably delivered. Can someone chime in on this?

I think that casts are guaranteed delivery if the process exists. Problem is, the caster can't know that with certainty (there could be a race between checking, process death and sending). Or the recipient could just ignore the cast altogether. Out if the box it's impossible to know which happened.

Calls by contrast check out a monitor on the counterparty and crash with a timeout so you have guaranteed delivery and acknowledgement, or crash the calling process.

A lot of times people from other plarforms rush to use casts when they "don't need a response" but the actual meanings have more to do with failure domains and rate limiting back pressure; my personal feeling is you should default to call and only use cast when you need failure isolation.

Re: Elixir GenServer Explained

#19
post #5

Since these insert events are being buffered, what happens if the process dies? Are all of those inserts lost? I feel like Erlang/Elixir is designed to handle cases like this robustly, but it's not clear to me how this code avoids losing data when a process crashes, potentially up to 5s worth of updates!

In this case, that's correct—you could lose up to 5s worth of state, plus any buffered messages. That's by design here. The business impact of that is going to depend on use-case, but I personally would find it difficult to believe that there would be any real impact in that event, in this case, under high load.

Obviously, different tolerances to that are going to necessitate different designs. You can configure the size of the message buffer when a GenServer starts, and if you have very low tolerance for lost data, you'd want to use a synchronous message (using call instead of cast, which blocks the sender until it returns) and appropriate error handling.

BEAM has a plethora of features for reliable applications, you just have to apply them appropriately.

Re: Elixir GenServer Explained

#20
post #5

Since these insert events are being buffered, what happens if the process dies? Are all of those inserts lost? I feel like Erlang/Elixir is designed to handle cases like this robustly, but it's not clear to me how this code avoids losing data when a process crashes, potentially up to 5s worth of updates!

Yea, they're just in memory, so they're lost. Erlang/Elixir doesn't solve this. There's no getting around the fact that you need an ack that your event was processed and saved to some durable store. A supervisor won't save you from lack of acknowledgment at the app level. Any restart or retry logic within beam itself is useless if a beaver chews through a power cord and the machine halts. And what is an ack, anyway? Is an ack from mongo as good as an ack from postgres? This is all stuff the language can't know. These are all business questions, all the language can do is give you tools handle these cases, which Erlang/Elixir does.
Post reply on HN