1+ #include < exception>
12#include < viam/sdk/robot/client.hpp>
23
34#include < chrono>
@@ -144,11 +145,16 @@ RobotClient::~RobotClient() {
144145
145146void RobotClient::close () {
146147 should_refresh_.store (false );
148+ should_check_connection_.store (false );
147149
148150 if (refresh_thread_.joinable ()) {
149151 refresh_thread_.join ();
150152 }
151153
154+ if (check_connection_thread_.joinable ()) {
155+ check_connection_thread_.join ();
156+ }
157+
152158 stop_all ();
153159
154160 viam_channel_.close ();
@@ -231,6 +237,62 @@ void RobotClient::refresh_every() {
231237 }
232238};
233239
240+ void RobotClient::check_connection () {
241+ auto check_every = check_every_interval_;
242+ auto reconnect_every = reconnect_every_interval_;
243+ if (check_every == std::chrono::seconds{0 }) {
244+ check_every = reconnect_every;
245+ }
246+ if (check_every == std::chrono::seconds{0 } && reconnect_every == std::chrono::seconds{0 }) {
247+ should_check_connection_.store (false );
248+ }
249+ bool connected (true );
250+ while (should_check_connection_) {
251+ std::exception_ptr connection_error;
252+ std::string what;
253+ for (int i = 0 ; i < 3 ; ++i) {
254+ try {
255+ std::this_thread::sleep_for (check_every);
256+ impl::client_helper (impl_, &RobotService::Stub::ResourceNames).invoke ([](auto &) {
257+ return ;
258+ });
259+ connected = true ;
260+ break ;
261+ } catch (const std::exception& e) {
262+ connected = false ;
263+ connection_error = std::current_exception ();
264+ what = e.what ();
265+ std::this_thread::sleep_for (std::chrono::milliseconds{100 });
266+ }
267+ }
268+ if (connected) {
269+ continue ;
270+ }
271+ const auto * uri = viam_channel_.get_channel_addr ();
272+ VIAM_SDK_LOG (error) << " Lost connection to machine at address " << uri << " with error "
273+ << what << " . Attempting to reconnect every " << reconnect_every.count ()
274+ << " second(s)" ;
275+
276+ viam_channel_.close ();
277+
278+ for (int i = 0 ; i < 3 ; ++i) {
279+ try {
280+ auto channel = ViamChannel::dial (uri, {});
281+ impl_ =
282+ std::make_unique<RobotClient::impl>(RobotService::NewStub (channel.channel ()));
283+ refresh ();
284+ connected = true ;
285+ } catch (const std::exception& e) {
286+ viam_channel_.close ();
287+ std::this_thread::sleep_for (reconnect_every);
288+ }
289+ }
290+ if (!connected) {
291+ close ();
292+ }
293+ }
294+ }
295+
234296RobotClient::RobotClient (ViamChannel channel)
235297 : viam_channel_(std::move(channel)),
236298 impl_ (std::make_unique<impl>(RobotService::NewStub(viam_channel_.channel()))) {}
@@ -262,8 +324,8 @@ void RobotClient::log(const std::string& name,
262324 ClientContext ctx;
263325 const auto response = impl_->stub ->Log (ctx, req, &resp);
264326 if (is_error_response (response)) {
265- // Manually override to force this to get logged to console so we don't set off an infinite
266- // loop
327+ // Manually override to force this to get logged to console so we don't set off an
328+ // infinite loop
267329 VIAM_SDK_LOG (error) << boost::log::add_value (sdk::impl::attr_console_force_type{}, true )
268330 << " Error sending log message over grpc: " << response.error_message ()
269331 << response.error_details ();
@@ -279,6 +341,13 @@ std::shared_ptr<RobotClient> RobotClient::with_channel(ViamChannel channel,
279341 robot->refresh_thread_ = std::thread{&RobotClient::refresh_every, robot.get ()};
280342 }
281343
344+ robot->should_check_connection_ = true ;
345+
346+ robot->check_every_interval_ = options.check_every_interval ();
347+ robot->reconnect_every_interval_ = options.reconnect_every_interval ();
348+
349+ robot->check_connection_thread_ = std::thread{&RobotClient::check_connection, robot.get ()};
350+
282351 robot->refresh ();
283352 return robot;
284353};
0 commit comments