blob: f94e61727494e63d57687762505ac6f9de93da4c [file] [log] [blame]
Tyler Chatowa79419d2020-08-12 20:12:11 -07001#ifndef AOS_STARTER_STARTER_RPC_LIB_H_
2#define AOS_STARTER_STARTER_RPC_LIB_H_
3
Stephan Pleinesf581a072024-05-23 20:59:27 -07004#include <stdint.h>
5
Tyler Chatowa79419d2020-08-12 20:12:11 -07006#include <chrono>
Stephan Pleinesf581a072024-05-23 20:59:27 -07007#include <functional>
James Kuszmaul293b2172021-11-10 16:20:48 -08008#include <map>
milind upadhyaya87957a2021-03-06 20:46:30 -08009#include <optional>
Stephan Pleinesf581a072024-05-23 20:59:27 -070010#include <string>
11#include <string_view>
12#include <utility>
James Kuszmaul293b2172021-11-10 16:20:48 -080013#include <vector>
Tyler Chatowa79419d2020-08-12 20:12:11 -070014
15#include "aos/configuration.h"
James Kuszmaul293b2172021-11-10 16:20:48 -080016#include "aos/events/event_loop.h"
Stephan Pleinesf581a072024-05-23 20:59:27 -070017#include "aos/flatbuffers.h"
Tyler Chatowa79419d2020-08-12 20:12:11 -070018#include "aos/starter/starter_generated.h"
19#include "aos/starter/starter_rpc_generated.h"
Stephan Pleinesf581a072024-05-23 20:59:27 -070020#include "aos/time/time.h"
Tyler Chatowa79419d2020-08-12 20:12:11 -070021
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080022namespace aos::starter {
Tyler Chatowa79419d2020-08-12 20:12:11 -070023
James Kuszmaul293b2172021-11-10 16:20:48 -080024// Data required to command that starter start/stop/restart a given application.
25struct ApplicationCommand {
26 Command command;
27 std::string_view application;
28 std::vector<const aos::Node *> nodes;
29};
30
31// This class manages interacting with starterd so that you can conveniently
32// start/stop applications programmatically.
33// Note that the StarterClient only maintains internal state for a single set of
34// commands at once, so once the user calls SendCommands() they must wait for
35// the timeout or success handler to be called before calling SendCommands
36// again.
37class StarterClient {
38 public:
39 StarterClient(EventLoop *event_loop);
40
41 void SendCommands(const std::vector<ApplicationCommand> &commands,
42 monotonic_clock::duration timeout);
43
44 void SetTimeoutHandler(std::function<void()> handler) {
45 timeout_handler_ = handler;
46 }
47
Austin Schuh0dcdf1d2024-03-27 12:55:41 -070048 // Sets the callback to be called on success. Note: this isn't safe to call
49 // while the previous success handler is running unless you use std::ref to
50 // manage its lifetime some other way.
James Kuszmaul293b2172021-11-10 16:20:48 -080051 void SetSuccessHandler(std::function<void()> handler) {
Austin Schuh0dcdf1d2024-03-27 12:55:41 -070052 success_handler_ = std::move(handler);
James Kuszmaul293b2172021-11-10 16:20:48 -080053 }
54
55 private:
56 struct CommandStatus {
57 State expected_state;
58 std::string application;
59 std::optional<uint64_t> old_id;
60 };
61
62 bool CheckCommandsSucceeded();
63
64 void Timeout();
65
66 void Succeed();
67
68 EventLoop *event_loop_;
69 TimerHandler *timeout_timer_;
70 Sender<StarterRpc> cmd_sender_;
71 // Map of fetchers by node name.
72 std::map<std::string, Fetcher<Status>> status_fetchers_;
73
74 // Mapping of node name to a list of applications with pending commands.
75 std::map<std::string, std::vector<CommandStatus>> current_commands_;
76
77 std::function<void()> timeout_handler_;
78 std::function<void()> success_handler_;
79};
80
Tyler Chatowa79419d2020-08-12 20:12:11 -070081// Finds the status of an individual application within a starter status message
82// Returns nullptr if no application found by the given name.
83const aos::starter::ApplicationStatus *FindApplicationStatus(
84 const aos::starter::Status &status, std::string_view name);
85
milind upadhyay4272f382021-04-07 18:03:08 -070086// Checks if the name is an executable name and if it is, it returns that
87// application's name, otherwise returns name as given
Austin Schuhdae1e8d2022-03-26 15:09:31 -070088std::string_view FindApplication(const std::string_view name,
milind upadhyay4272f382021-04-07 18:03:08 -070089 const aos::Configuration *config);
90
Tyler Chatowa79419d2020-08-12 20:12:11 -070091// Sends the given command to the application with the name name. Creates a
92// temporary event loop from the provided config for sending the command and
93// receiving back status messages. Returns true if the command executed
94// successfully, or false otherwise. Returns false if the desired state was not
95// achieved within timeout.
96bool SendCommandBlocking(aos::starter::Command, std::string_view name,
97 const aos::Configuration *config,
James Kuszmaul293b2172021-11-10 16:20:48 -080098 std::chrono::milliseconds timeout,
99 std::vector<const aos::Node *> nodes = {});
Tyler Chatowa79419d2020-08-12 20:12:11 -0700100
Austin Schuhe4b748a2021-10-16 14:19:58 -0700101// Sends lots of commands and waits for them all to succeed. There must not be
102// more than 1 conflicting command in here which modifies the state of a single
103// application otherwise it will never succeed. An example is having both a
104// start and stop command for a single application.
James Kuszmaul293b2172021-11-10 16:20:48 -0800105bool SendCommandBlocking(const std::vector<ApplicationCommand> &commands,
106 const aos::Configuration *config,
107 std::chrono::milliseconds timeout);
Austin Schuhe4b748a2021-10-16 14:19:58 -0700108
Tyler Chatowa79419d2020-08-12 20:12:11 -0700109// Fetches the status of the application with the given name. Creates a
James Kuszmaule4bb0a22022-01-07 18:14:43 -0800110// temporary event loop from the provided config for fetching. Returns nullopt
111// if the application is not found.
James Kuszmaul2ca441b2022-01-07 18:16:23 -0800112// The returned pair is the time at which the ApplicationStatus was sent on the
113// node it was sent from, to allow calculating uptimes on remote nodes.
James Kuszmaule4bb0a22022-01-07 18:14:43 -0800114const std::optional<
James Kuszmaul2ca441b2022-01-07 18:16:23 -0800115 std::pair<aos::monotonic_clock::time_point,
116 aos::FlatbufferDetachedBuffer<aos::starter::ApplicationStatus>>>
James Kuszmaule4bb0a22022-01-07 18:14:43 -0800117GetStatus(std::string_view name, const aos::Configuration *config,
118 const aos::Node *node);
Tyler Chatowa79419d2020-08-12 20:12:11 -0700119
Philipp Schrader08537492021-01-23 16:17:55 -0800120// Fetches the entire status message of starter. Creates a temporary event loop
121// from the provided config for fetching.
James Kuszmaul293b2172021-11-10 16:20:48 -0800122// The returned pair is the time at which the Status was sent on the node it was
123// sent from, to allow calculating uptimes on remote nodes.
124// TODO(james): Use the ServerStatistics message and return the monotonic offset
125// instead, so that we can correctly handle high message latencies. Because
126// people don't generally care about ultra-high-precision uptime calculations,
127// this hasn't been prioritized.
128std::optional<std::pair<aos::monotonic_clock::time_point,
129 const aos::FlatbufferVector<aos::starter::Status>>>
130GetStarterStatus(const aos::Configuration *config, const aos::Node *node);
Philipp Schrader08537492021-01-23 16:17:55 -0800131
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -0800132} // namespace aos::starter
Tyler Chatowa79419d2020-08-12 20:12:11 -0700133
134#endif // AOS_STARTER_STARTER_RPC_LIB_H_