diff --git a/pkgs/default.nix b/pkgs/default.nix index cbbc211..0f505a4 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -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 diff --git a/pkgs/s6-rc-round-robin/default.nix b/pkgs/s6-rc-round-robin/default.nix new file mode 100644 index 0000000..c614496 --- /dev/null +++ b/pkgs/s6-rc-round-robin/default.nix @@ -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 + ''; +} diff --git a/pkgs/s6-rc-round-robin/robin.fnl b/pkgs/s6-rc-round-robin/robin.fnl new file mode 100644 index 0000000..f04d648 --- /dev/null +++ b/pkgs/s6-rc-round-robin/robin.fnl @@ -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 }