TL;DR: Try to keep your start up encoded as much as possible with the standard facilities of sub-supervisors, children (the order of them) as well as the restart strategy and you’ll guarantee that your system looks like any other. If ConCache
is actually doing logic, don’t make it a supervisor. Catastrophic failure should be encoded in the init
to prevent the system/supervisor and the rest of the children from starting.
A bit of meditation on the things in this post, written by the great Fred Hebert: It’s About the Guarantees
I think maybe more information about everything is in order.
Ordinarily, a supervisor wouldn’t be a process that actually does logic, so I’m weary of this being started and called :cache
in your supervision tree.
What is it that can fail when starting the supervisor and why do we need to start all our children before post_start
? Usually when we require a specific ordering of started processes we can simply put them before/after other processes in the children list. A good model is to have processes that are tied to each other in functionality start under the same supervisor with their relationship encoded in the restart strategy
. This might not be needed here, but it’s worth looking at in the future when your supervision tree grows.
Encoding catastrophic failure into your startup is best done by setting up whatever requirements you have in a process’ init
(that would be the ConCache.init
call here). If there is something that simply will not allow for your application to start without, put it there and the BEAM will make sure your app just doesn’t start if this condition isn’t met.
If a process is needed for ConCache
to be running, put its startup before ConCache
and that will have to start up properly for ConCache
to be started. Conversely, if ConCache
needs to be running for something else to function, putting it before it in the children list will ensure that it needs to start properly for the other thing to start. This requires you to bail out if things aren’t actually working as they should, so detection of that property is needed in the init
of the process.
This applies to all processes, so it’s good to think of your startup process as potentially containing information about what’s important. If something is pivotal to the whole system and it simply can’t run without it, put that first in your children list, though you’ll have to have the dependencies it has start before it, obviously.
With regards to general cache behavior, I favor the idea of checking a cache for data and if it doesn’t have it, populate the cache with that data.
Edit: If you need to pre-populate the cache you have to make the choice whether or not to make that hold up your startup (if the cache is important enough) or delay that by, for example, sending yourself a message in the init
callback in order to load the cache data in a handle_info
. Both behaviors will likely die on error, so if the cache is important enough you very likely want it to die on init
instead of later.