Mads
Multi-Agent Distributed System
Loading...
Searching...
No Matches
up_supervisor.hpp
Go to the documentation of this file.
1/*
2 _ _ ____ _
3 | | | |_ __ / ___| _ _ _ __ ___ _ ____ __(_)___ ___ _ __
4 | | | | '_ \ \___ \| | | | '_ \ / _ \ '__\ \ / /| / __|/ _ \| '__|
5 | |_| | |_) | ___) | |_| | |_) | __/| \ V / | \__ \ (_) | |
6 \___/| .__/ |____/ \__,_| .__/ \___|_| \_/ |_|___/\___/|_|
7 |_| |_|
8
9Process supervisor backing `mads up` (src/main/up.cpp): starts a
10Mads::DirectorConfig's processes in dependency order, gates each start on its
11`ready` probe, restarts `relaunch` processes with exponential backoff, and
12tears everything down (SIGTERM -> grace -> SIGKILL) on request.
13
14Spawns via vendored reproc (see src/up_supervisor.cpp for why the plain C API
15is used instead of reproc++, and how process groups are handled on POSIX,
16where reproc itself does not set one up).
17
18Author(s): Paolo Bosetti
19*/
20#ifndef MADS_UP_SUPERVISOR_HPP
21#define MADS_UP_SUPERVISOR_HPP
22
23#include "broker_probe.hpp"
24#include "director_config.hpp"
25
26#include <atomic>
27#include <chrono>
28#include <memory>
29#include <optional>
30#include <string>
31#include <vector>
32
33namespace Mads {
34
35// Defined in up_supervisor.cpp. Deliberately a free (non-nested) type, not a
36// private nested class of UpSupervisor: the reader threads that drain a
37// child's stdout/stderr are free functions (std::thread needs a plain
38// callable), and a private nested type would not be nameable from them.
39struct UpManagedProcess;
40
41struct UpOptions {
42 std::optional<std::string> until_exit; // process name to wait for
43 std::optional<std::chrono::milliseconds> timeout; // hard cap for the whole run
44 std::chrono::milliseconds grace{5000}; // SIGTERM -> SIGKILL grace period
45 int max_restarts = -1; // -1 = unlimited
46 bool no_shell = false; // tokenize `command` instead of shelling out
47 // Per-process readiness wait; not exposed on the schema/CLI (director.toml
48 // has no per-key timeout), applies uniformly to every `ready = "..."`.
49 std::chrono::milliseconds ready_timeout{10000};
50 bool quiet = false; // suppress multiplexed [name] stdout/stderr passthrough
51 // CURVE credentials for `ready = "broker"` probes, from mads-up's own
52 // --crypto/--keys_dir/--key_client/--key_broker flags. Unset means "probe
53 // in the clear", which reaches only an unencrypted broker: a CURVE-secured
54 // one drops a plain peer during the ZMTP handshake, so the probe would
55 // never come back and the gate would wait out its full ready_timeout with
56 // a perfectly healthy broker running. Not a director.toml key: the plan
57 // format is shared with Director's GUI, and every process already names
58 // its own --crypto flags inside `command`.
59 std::optional<ProbeCurveKeys> curve;
60};
61
62enum class RunOutcome {
63 Ok, // clean teardown (stop requested, or --until-exit target exited)
64 Timeout, // --timeout elapsed
65 ReadyTimeout, // a process's `ready` probe never succeeded
66 StartFailed, // a process failed to spawn
67 ProcessFailed // a non-relaunch process exited non-zero unexpectedly
68};
69
70struct RunResult {
72 int exit_code = 0; // meaningful for RunOutcome::Ok when --until-exit is set,
73 // and for the failing process otherwise
74 std::string message;
75};
76
84public:
85 UpSupervisor(std::vector<ProcessConfig> processes, UpOptions options);
87
88 UpSupervisor(const UpSupervisor &) = delete;
90
100
105
107 bool stop_requested() const;
108
109 // --- test hooks (tests/test_up_supervisor.cpp) ---------------------------
110
113 int start_count(const std::string &name) const;
114
117 bool any_running() const;
118
119private:
120 std::vector<ProcessConfig> _processes;
121 UpOptions _options;
122 std::vector<std::unique_ptr<UpManagedProcess>> _managed;
123 std::atomic<bool> _stop_requested{false};
124
125 bool start_one(UpManagedProcess &mp);
126 bool wait_ready(UpManagedProcess &mp, std::chrono::milliseconds timeout);
127 void stop_one(UpManagedProcess &mp, std::chrono::milliseconds grace);
128 void teardown();
129 UpManagedProcess *find(const std::string &name);
130};
131
132} // namespace Mads
133
134#endif // MADS_UP_SUPERVISOR_HPP
Starts, supervises and tears down the processes described by an expanded Mads::DirectorConfig....
UpSupervisor & operator=(const UpSupervisor &)=delete
bool any_running() const
RunResult run()
Starts every enabled process in order (waiting on each one's ready probe before moving on to whatever...
UpSupervisor(const UpSupervisor &)=delete
bool stop_requested() const
True once request_stop() was called or run() decided to stop on its own.
UpSupervisor(std::vector< ProcessConfig > processes, UpOptions options)
int start_count(const std::string &name) const
Definition agent.hpp:67
std::string message
std::optional< std::chrono::milliseconds > timeout
std::optional< std::string > until_exit
std::chrono::milliseconds ready_timeout
std::optional< ProbeCurveKeys > curve
std::chrono::milliseconds grace