Add Erlang style supervisor
Depends on #649
Motivation
One of the visions for Effection was to recreate part of the brilliant OTP system for Erlang, by enabling the easy creation of supervision trees. Supervision trees enable fault tolerance through the "just let it crash" philosophy. While Effection code is very good at surfacing errors, actually dealing with those errors has been tricky. With supervision trees, parts of the system or the whole system can be kept running and restarted easily.
Approach
Why reinvent the wheel? OTPs supervisors are good and battle tested. This basically copies most of the functionality of OTP supervisors.
For more information, see the README
Alternate Designs
There are millions of other ways of doing the same thing.
Possible Drawbacks or Risks
The code is complicated, and there are probably a ton of nasty edge cases.
TODOs and Open Questions
- [ ] This interacts somewhat poorly with resources. Is there something we can do about that?
- [ ] Missing
simple_one_for_onestrategy. IMO this should probably be a completely separate thing, since the external interface forsimple_one_for_oneshould be quite different. It feels like Erlang sort of shoehorned this into one module, but it really shouldn't be. - [ ] The
periodandintensityoptions are not yet implemented. I think this is a very necessary part of the supervision system, but it's tricky to implement. Also, I think having some kind of backoff would be nice. - [ ] Type safety for the
argsoption could be improved. I think the only nice way of doing this is by using the multiple-overloads trick.
Learning
https://www.erlang.org/doc/man/supervisor.html
This looks amazing! Sorry I've taken so long to get to reviewing it, but I didn't have much time last week.
I am curious about the dynamic nature of the
addChild,haltChildandhandAndRemoveChild. What is the modern use case for being able dynamically configure the supervisor like this as opposed to say, passing in the child specifications to the constructor?Actually, in stating the question, I think I may have answered it. It would be awesome in Backstage to be able to enable and disable plugins via a UI, and this would be perfect for that sort of thing.
A thing like
addChildwould even allow you to add a new plugin without even restarting the server!
I think, by far the most common use case is adding children in the constructor. I think for most usecases involving dynamically adding and removing children, you really want the simple_one_for_one type supervisor. But IMO in TypeScript, this supervisor should have a totally different interface. In Erlang some methods just change signature when this strategy is passed in, which makes (some) sense in a dynamic language, but becomes pretty cumbersome in a statically typed language. I do think there are some usecases for dynamically adding children, like you pointed out.
@cowboyd I've added some minor improvements, including rendering error messages nicely, and fixing the dependency to use a caret. Held off on removing args awaiting a decision on what you think is best there.
@cowboyd coming up to a point where I'd actually like to try and use this. I've made a few changes and improvements. I can obviously use this from my own project, but any chance this could get merged?
Hey @jnicklas! that's great to hear! I'm still OOO this week, but will have a look first thing next year!
@jnicklas I've approved, but it looks like there is a ESLint check that is failing...
I'd still love to see a supervisor package, but with the advent of v3 this code would have to be re-worked significantly. I'm going to go ahead and close, but nothing would give me greater joy than to have you working on Effection code again!