zachallaun / protean

Finite State Machines and Statecharts for Elixir
MIT License
14 stars 0 forks source link

Correct supervision / process dependency strategy #2

Closed zachallaun closed 1 year ago

zachallaun commented 1 year ago

Protean's supervision strategy at the moment: The library asks that the user add Protean to their application supervision tree. That starts a DynamicSupervisor that is then used for any invoked processes (regardless of "depth"). While it's possible to pass a different supervisor when starting a machine, any processes resulting from :invoke are started using that same supervisor.

Whether this is the correct implementation depends on how we want to handle restarts & process dependencies. The problem is that the dependencies are cyclical -- invoked children can send messages to their parents. For instance: Let's say we have a parent and child process communicating with each other. While this is probably a bad design choice, these machines may be coordinating with each other such that one's in a state where it is expecting a certain event. Then, let's say the child dies -- if it's restarted, it may now be in a state that it will never send the event the parent expects.

I believe SCXML semantics account for this. An invoked process shouldn't ever be restarted -- the crash should be visible to the parent machine through the error transition, which the parent could use to e.g. self-transition and restart the invoked process itself.

So: restarts bad, child processes should be started with restart: :temporary.

But what if that crashed child process had invoked processes itself? They need to be shut down. but all of those processes were started under the same top-level dynamic supervisor. Machine servers are given their parent's pid when they start. It could monitor that pid so that we receive a :DOWN message. If the parent crashes, the child can terminate.

I'm not yet sure what to do about misc processes we don't control. I'd like any OTP process to be invokable from within a machine, but I'd like to basically one-way-link children to their parents, so that the children are always terminated if the parent crashes.

zachallaun commented 1 year ago

Ok, duh... Parents know their invoked children. When the interpreter stops, they need to clean up by sending an exit signal to each. There are still cases (I think with :brutal_kill?) where children can be "left behind", but I think this is sufficient for the moment.

311e880a4f543e7de4ece347ada77903eee85907