sschuldenzucker
Supervision design for static but interdependent processes, startup order
Hey all, I’m pulling my hair out over how to properly design my supervision structure. It works right now but only because processes are restarted often enough to eventually fall in the right order.
I’m sure there’s an obvious right solution here that I just don’t see (pretty new to elixir). Anyone got an idea? ![]()
I’m building a single-user interactive app. There are four GenServers:
- The
ModelManagerserves as a central point to store the underlying data. (makes it easier to implement sync later) Processes can subscribe to the ModelManager and be notified in the event of changes. - The
Frontend(a TUI using the Ratatouille library) presents the UI and pushes changes to the ModelManager. It also listens to change events emitted from the ModelManager (e.g., because of sync). - The frontend actually needs a little
MsgTransformerprocess between itself and the ModelManager to transform the messages into a shape that Ratatouille can deal with. - The
FileSaverimplements autosave by listening to change events from the ModelManager and writing them to disk.
I even made a little diagram:
The problem I’m facing is startup: in principle it’s clear what should happen:
- The
ModelManagershould start first. - Then we can start
FileServerandMsgTransformer(the MsgTransformer actually belonging to the Frontend; nobody else has to know about this) - Finally we can start the
Frontend.
This order is necessary so everyone can subscribe / reference the other processes when they need to. But I have no idea how to make this happen.
Right now I’m just putting all four processes as directly supervised children under my main app tree. Some process (the frontend specifically) crash upon init because the ModelManager isn’t live yet, so it can’t subscribe. But the supervisor restarts it, so it’ll eventually be fine. — But this is definitely not a clean design right?
Most Liked
axelson
It sounds like you’re pretty well sorted on the questions you had, but reading your post I think that I’d recommend not having a separate process for the MsgTransformer, and instead convert that into a plain module that is used by the frontend process. My reasoning is that it sounds like the MsgTransformer process is being used for code organization rather than isolation/resilience (plus adding a process always adds performance overhead). If you haven’t already, I highly recommend reading Saša Jurić excellent blog post on this topic: The Erlangelist - To spawn, or not to spawn?
cmo
Children are started in the order you list them. Once one returns from init, the next one starts.
w0rd-driven
If Frontend depends on it then it should start first. Your second point kind of illustrates that. You could try to detect if the named process is started but you might as well use supervisors to guarantee it.
You are basically pulling the childspec calls from your app into each supervisor with a bit more boilerplate. A supervisor is a behavior of a GenServer, which I map to something like traits in PHP. Since you want to manage dependent processes, it makes sense to group them as a supervisor tree and when your dependency crashes you likely want to re-initialize some state for it.
I think you understand quite a bit but it helps to put theory to practice. You could spike on a throwaway branch and try different strategies or groupings until it “feels right”. You could also look at all the other children your app handles. The docs for supervisors Supervisor — Elixir v1.17.2 has examples and is pretty comprehensive. The DockYard Academy section on supervisors and the drills are a great as well curriculum/reading/supervisors.livemd at main · DockYard-Academy/curriculum · GitHub.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









