commit 534a49e827727529cc2c9e32048ee2cf0a20badf
parent 07a6eb73cd716037ec79e29eec343b7da5504bc1
Author: Daniel Barlow <dan@telent.net>
Date: Mon, 8 Jul 2024 21:53:51 +0100
s6-rc-round-robin
runs services in order, starting the next one when the previous one
dies or fails to start
Diffstat:
3 files changed, 81 insertions(+), 0 deletions(-)
diff --git 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
@@ -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
@@ -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 }