On 4/28/2015 10:31 AM, Steve Litt wrote:
Good! I was about to ask the definitions of parent and child, but the
preceding makes it clear.

I'm taking it from the viewpoint that says "the service that the user wishes to start is the parent of all other service dependencies that must start".

So what you're doing here is minimizing polling, right? Instead of
saying "whoops, child not running yet, continue the runit loop", you
actually start the child, the hope being that no service will ever be
skipped and have to wait for the next iteration. Do I have that right?
Kinda. A failure of a single child still causes a run loop, but the next time around, some of the children are already started, and a start of the child will quickly return a success, allowing the script to skip over it quickly until it is looking at the same problem child from the last time. The time lost is only on failed starts, and child starts typically don't take that long. If they are, well, it's not the parent's fault...

Here's the current version of run.sh, with dependency support baked
in:
https://bitbucket.org/avery_payne/supervision-scripts/src/b8383ed5aaa1f6d848c1a85e6216e59ba98c3440/sv/.run/run.sh?at=default

That's a gnarley run script.

Yup.  For the moment.

If I'm not mistaken, everything inside the "if test
$( cat ../.env/NEEDS_ENABLED ) -gt 0; then" block is boilerplate that
could be put inside a shellscript callable from any ./run.

True, and that idea has merit.

  That would
hack off 45 lines right there. I think you could do something similar
with everything between lines 83 and 110. The person who is truly
interested in the low level details could look at the called
shellscripts (perhaps called with the dot operator). I'm thinking you
could knock this ./run down to less than 35 lines of shellscript by
putting boilerplate in shellscripts.
I've seen this done in other projects, and for the sake of simplicity (and reducing subshell spawns) I've tried to avoid it. But that doesn't mean I'm against the idea. Certainly, all of these are improvements with merit, provided that they don't interfere with some of the other project goals. If I can get the time to look at all of it, I'll re-write it by segmenting out the various components.

In fact, you may have given me an idea to solve an existing problem I'm having with certain daemons...


You're doing more of a recursive start. No doubt, when there are two or
three levels of dependency and services take a non-trivial amount of
time to start (seconds), yours results in the quicker boot. But for
typical stuff, I'd imagine the old "wait til next time if your ducks
aren't in line" will be almost as fast, will be conceptually
simpler, and more codeable by the end user. Not because your method is
any harder, but because you're applying it against a program whose
native behavior is "wait til next cycle".

Actually, I was looking for the lowest-cost solution to "how do I keep track of dependency trees between multiple services". The result was a self-organizing set of data and scripts. I don't manage *anything* beyond "service A must have service B". It doesn't matter how deep that dependency tree goes, or even if there are common "leaf nodes" at the end of the tree, because it self-organizes. This reduces my cognitive workload; as the project grows to hundreds of scripts, the number of possible combinations reaches a point where it would be unmanageable otherwise. Using this approach means I don't care how many there are, I only care about what is needed for a specific service.

And, as you said in a past email, having a run-once capability without
insane kludges would be nice, and as you said in another past email,
it's not enough to test for the child service to be "up" according to
runit, but it must pass a test to indicate the process itself is
functional. I've been doing that ever since you mentioned it.

At some point I have to go back and start writing ./check scripts. :(

Reply via email to