Skip to content

Instantly share code, notes, and snippets.

@knewter
Last active August 20, 2016 15:27
Show Gist options
  • Save knewter/ba7d6476389b2ad24b77e7e4e9056507 to your computer and use it in GitHub Desktop.
Save knewter/ba7d6476389b2ad24b77e7e4e9056507 to your computer and use it in GitHub Desktop.
A discussion to try to help explain processes and GenServer to early elixir users

me: have you ever done the ‘make a process that runs a function that does a receive and calls that function again after receiving every message’ thing yet?

person1: that was a sentence that I have no idea what it means

me: I had already done erlang for like 3 months when I got into elixir, and kind of dug in hard on erlang, so I had these concepts in the brain already

me: ok, let me show you real quick

me: this is like the thing about elixir

me: in elixir, processes are what you should use for a ton of stuff. Like everything nearly. And when you do, life is amazing.

me: one sec, I’ll make a repo for you

person1: I’m pretty much a pure web dev, we do stateless things

person1: none of this ‘wait for messages and do things’ stuff

me: http://github.com/knewter/process_actor_example

person1: looking

me: if either of you spent any decent time (more than a couple of weeks) learning elixir and weren’t introduced to that, it’s a sad state of affairs 😞

me: this is my 12th episode of elixirsips, so I guess that wasn’t within 2 weeks

me: but still

person1: yeah that kind of stuff was covered in Programming Elixir

me: this is like….the fundamental thing in elixir/erlang

me: ok

me: so some issues with that. If the process dies (however) it’s gone for good. So you can’t rely on it being there. So you can’t build things that rely on it. So you won’t get a super reliable system using that as your primitive without some extra bits on top of it

me: the first is spawn_link

me: if you use that instead of spawn, then you both create a new process and link it to the current process (the shell, in the case of using iex)

me: you could do that without spawn_link, too

me: http://elixir-lang.org/docs/stable/elixir/Process.html#link/1

me: and if you just wanted to receive a message when that process died, but not have it kill you too, that can be done with monitors

me: ok, so if you use those things you can actually build reliable systems - if you want that ping service running all the time, you could spawn a simple process early on that started it, monitored it, and started a new one if/when it died

me: that’s how early erlang systems were built, and it was Good

me: and then they realized they did this all the freaking time, both of those patterns

me: and that there was no good way to get debugging information on those running processes so it was problematic in production to make the system better or understand what was happening

me: so they introduced GenServer to provide a common way to do things with the first pattern

me: it has GenServer.call(pid, msg) and GenServer.cast(pid, msg). The first is synchronous, so you can use it like a ruby method call or w/e. The second is async, so you can send a message to another process and get on with life no matter what else happens.

me: everything in the messaging layer in erlang is asynchronous - it’s built on this concept of each process having a mailbox that you put messages in. receive looks in the mailbox to try to pattern match some case. If there is a message that isn’t matched in the case, it crashes. If there is, it will handle that message and then return (done forever, with one receive). If there isn’t, it will block the process until it receives a message, handle it, and be done forever.

me: if you want to always receive messages, you can tail-call the function that receives them. typically you’d call this loop but that’s just kind of a random convention no one cares about.

me: you can use this pattern to build up state which is how you get ‘changing data’ in an immutable language

me: you take the previous state, do something based on the message, and call back into the loop with the ‘updated’ state (which is just a new immutable value based on the previous one)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment