Skip to content

Commit

Permalink
feat: allow configurign top-level supervisor restart limits
Browse files Browse the repository at this point in the history
This lets you start a runtime that will terminate if the top-level
application terminates, which is useful for CLIs that may crash and need
to stay crashed.

For long-running applications this helps configure how many times you
want the application to retry before fully shutting down.

Also add a small pretty printer to print out the config as debug
information when the runtime starts.
  • Loading branch information
leostera committed Oct 28, 2024
1 parent 58458b6 commit 310a486
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 10 deletions.
28 changes: 25 additions & 3 deletions packages/riot-runtime/Config.ml
Original file line number Diff line number Diff line change
@@ -1,11 +1,33 @@
type t = { rnd : Random.State.t; max_workers : int; workers : int }
type t = {
rnd : Random.State.t;
max_workers : int;
workers : int;
supervisor_restart_limit : int;
supervisor_restart_period : int;
}

let make ?workers () =
let pp fmt t =
Format.fprintf fmt "== RIOT CONFIG ==\n";
Format.fprintf fmt "* max_wokers=%d\n" t.max_workers;
Format.fprintf fmt "* workers=%d\n" t.workers;
Format.fprintf fmt "* supervisor_restart_limit=%d\n" t.supervisor_restart_limit;
Format.fprintf fmt "* supervisor_restart_period=%d\n" t.supervisor_restart_period;
Format.fprintf fmt "\n%!"
;;

let make ?(supervisor_restart_limit = 1) ?(supervisor_restart_period = 0)
?workers () =
let max_workers = Int.max 0 (Stdlib.Domain.recommended_domain_count () - 2) in
let workers =
match workers with Some w -> Int.min w max_workers | None -> max_workers
in
let rnd = Random.State.make_self_init () in
{ rnd; max_workers; workers }
{
rnd;
max_workers;
workers;
supervisor_restart_limit;
supervisor_restart_period;
}

let default () = make ()
13 changes: 8 additions & 5 deletions packages/riot/riot.ml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ let run ?(config = Config.default ()) main =

let Config.{ workers; rnd; _ } = config in

Log.debug (fun f -> f "Initializing Riot runtime...");
Log.debug (fun f -> f "Initializing Riot runtime...\n%a" Config.pp config);

Printexc.record_backtrace true;
Core.Pid.reset ();
Scheduler.Uid.reset ();
Expand Down Expand Up @@ -63,20 +64,22 @@ let run_with_status ?config ~on_error main =
in
shutdown ~status ()

let start ?config ~apps () =
run ?config @@ fun () ->
let start ?(config = Config.default ()) ~apps () =
run ~config @@ fun () ->
let child_specs =
List.map
(fun (module App : Application.Intf) ->
Supervisor.child_spec App.start ())
apps
in
let restart_limit = config.supervisor_restart_limit in
let restart_period = config.supervisor_restart_period in
Supervisor.(
start_supervisor
{
strategy = One_for_one;
restart_limit = 1;
restart_period = 0;
restart_limit;
restart_period;
child_specs;
children = [];
restarts = [];
Expand Down
17 changes: 15 additions & 2 deletions packages/riot/riot.mli
Original file line number Diff line number Diff line change
Expand Up @@ -305,10 +305,23 @@ val shutdown : ?status:int -> unit -> unit
(** Gracefully shuts down the runtime. Any non-yielding process will block this. *)

module Config : sig
type t = { rnd : Random.State.t; max_workers : int; workers : int }
type t = {
rnd : Random.State.t;
max_workers : int;
workers : int;
supervisor_restart_limit : int;
supervisor_restart_period : int;
}

val pp : Format.formatter -> t -> unit
val default : unit -> t
val make : ?workers:int -> unit -> t

val make :
?supervisor_restart_limit:int ->
?supervisor_restart_period:int ->
?workers:int ->
unit ->
t
end

val run : ?config:Config.t -> (unit -> unit) -> unit
Expand Down

0 comments on commit 310a486

Please sign in to comment.