s6-rc-round-robin

runs services in order, starting the next one when the previous one
dies or fails to start
This commit is contained in:
Daniel Barlow 2024-07-08 21:53:51 +01:00
parent 07a6eb73cd
commit 534a49e827
3 changed files with 81 additions and 0 deletions

View File

@ -95,6 +95,7 @@ in {
run-liminix-vm = callPackage ./run-liminix-vm { };
s6-init-bin = callPackage ./s6-init-bin { };
s6-rc-database = callPackage ./s6-rc-database { };
s6-rc-round-robin = callPackage ./s6-rc-round-robin { };
s6-rc-up-tree = callPackage ./s6-rc-up-tree { };
# schnapps is written by Turris and provides a high-level interface

View File

@ -0,0 +1,21 @@
{
lualinux,
writeFennel,
anoia,
linotify,
fennel,
stdenv,
s6-rc-up-tree,
}:
stdenv.mkDerivation {
name = "s6-rc-round-robin";
src = ./.;
propagatedBuildInputs = [ s6-rc-up-tree ];
installPhase = ''
mkdir -p $out/bin
cp -p ${writeFennel "uevent-watch" {
packages = [fennel anoia linotify lualinux s6-rc-up-tree] ;
mainFunction = "run";
} ./robin.fnl} $out/bin/s6-rc-round-robin
'';
}

View File

@ -0,0 +1,59 @@
(local { : directory? : symlink } (require :anoia.fs))
(local { : assoc : system } (require :anoia))
(local inotify (require :inotify))
(fn parse-args [args]
(match args
["-p" proxy & rest] (assoc (parse-args rest) :proxy proxy)
backends { : backends }
_ nil))
(fn %% [fmt ...] (string.format fmt ...))
(fn start-service [service]
(let [(ok msg) (pcall system (%% "s6-rc-up-tree %q" service))]
(when (not ok) (print msg))
ok))
(fn stop-service [service]
(let [(ok msg) (pcall system (%% "s6-rc -b -d change %q" service))]
(when (not ok) (print msg))
ok))
(fn watch-fsevents [directory-name]
(doto (inotify.init)
(: :addwatch directory-name
inotify.IN_CREATE
inotify.IN_MOVE
inotify.IN_DELETE
inotify.IN_DELETE_SELF
inotify.IN_MOVED_FROM
inotify.IN_MOVED_TO
inotify.IN_CLOSE_WRITE)))
(fn round-robin [els]
(var i -1)
(fn []
(set i (% (+ 1 i) (# els)))
(. els (+ 1 i))))
(fn run []
(let [{ : proxy : backends } (parse-args arg)]
(each [s (round-robin backends)]
(print "ROBIN starting " s)
(when (start-service s)
(let [outputs-dir (.. "/run/services/outputs/" s)]
(print "ROBIN started " s "expecting outputs in " outputs-dir)
(with-open [watcher (watch-fsevents outputs-dir)]
(symlink outputs-dir "active")
(start-service proxy)
(while (directory? outputs-dir)
(print :ROBIN (watcher:read))))))
;; service failed to start, or started and finished
(print "ROBIN finished " s "stopping proxy")
(stop-service proxy)
(stop-service s)
(os.remove "active")
)))
{ : run }