Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I'm curious, and I know this is a random thread to post this question, but how do you handle the fact that the Elixir process might be shut down with regards to necessary persistence of any message queues? Put differently: I consider both message queues and databases in my system to be part of the stateful workloads and the web app part of the stateless workloads (can-be-killed-at-any-time). How do you handle the case where your stateful workload (queueing) now lives within your Elixir process which might be killed at any instance?


The terminology is a bit ambiguous here with the word 'process' so I'm not 100% sure precisely what you're asking. The BEAM (Elixir VM) uses the the term 'process' to describe its green threads/fibres. The BEAM runs as one OS process, with a thread per core of your machine and schedules each of the application green threads onto one of those threads. BEAM processes are cheap and quick to create and come and go regularly. The BEAM itself is very stable and will stay up permanently (potentially even through SW upgrade if you want). Whenever I say process below I mean a BEAM process.

When you use Phoenix, the Web framework creates a process to handle the specific request. By default everything you do happens in that process (give or take some database stuff). If you make a programming error that process will 'crash' (again a BEAM term that is more like an exception) and the user will get an error. No other processes will be affected, regardless of whether they are to do with other requests or anything else.

If you want a work queue, you would create a separate set of BEAM processes (or maybe just one), probably at startup. In your request handling you would send a message to that work queue process asking it to do things. Your request can block (not affecting any other requests) waiting for it if necessary, or it can return so you can get the result later. If the Web request times out or crashes or whatever, that will kill the handler process, but will leave the work queue process alone.

One other note - under the hood it's all message passing between processes, but to the programmer each process is probably just a Gen Server (an abstraction) and the message send and reply is just a function call. But normal Phoenix stuff doesn't even have that because the Web server does the 'process machinery' for handling requests.


If you want a persistent task queue in Elixir then I would use a library like oban [1] that uses postgres to manage the jobs, a nice benefit of it is that you can enqueue your jobs as part of a database transaction (and Ecto.Multi gives you a nice interface to transactions). And just because you can have a message queue directly inside your application server doesn't mean you need to or that it's a good fit for every project.

1. https://github.com/sorentwo/oban


Kill at any time is dangerous for stateful Erlang / Elixir workloads. But there are several patterns:

1. Some process group libraries can handle graceful shutdown, which migrates the processes to other nodes. When you kill one of the nodes, it's process goes to other nodes in like tens of seconds.

2. Invent some virtual actor pattern like Microsoft Orleans.

3. Just backup processes states to external storage. Even not for shutting down nodes scenarios, people still tend to backup process state to ETS or stateful processes so that stateless processes can crash-then-revive without troubles.


You can add a kill/shutdown message handler and move your state somewhere else before the process dies.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: