From 5bb7313ae324353bdf2c15959194fd4286527b51 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 6 Nov 2023 11:53:11 -0600 Subject: [PATCH 1/2] GH-1858 Add better error handling --- tests/trx_generator/trx_provider.cpp | 28 ++++++++++++++++++++-------- tests/trx_generator/trx_provider.hpp | 1 + 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/tests/trx_generator/trx_provider.cpp b/tests/trx_generator/trx_provider.cpp index 4ff29007fd..301a817c4c 100644 --- a/tests/trx_generator/trx_provider.cpp +++ b/tests/trx_generator/trx_provider.cpp @@ -109,16 +109,21 @@ namespace eosio::testing { void http_connection::disconnect() { int max = 30; int waited = 0; - while (_sent.load() != _acknowledged.load() && waited < max) { - ilog("http_connection::disconnect waiting on ack - sent ${s} | acked ${a} | waited ${w}", - ("s", _sent.load())("a", _acknowledged.load())("w", waited)); + for (uint64_t sent = _sent.load(), acknowledged = _acknowledged.load(); + sent != acknowledged && waited < max; + sent = _sent.load(), acknowledged = _acknowledged.load()) { + ilog("disconnect waiting on ack - sent ${s} | acked ${a} | waited ${w}", + ("s", sent)("a", acknowledged)("w", waited)); sleep(1); ++waited; } if (waited == max) { - elog("http_connection::disconnect failed to receive all acks in time - sent ${s} | acked ${a} | waited ${w}", + elog("disconnect failed to receive all acks in time - sent ${s} | acked ${a} | waited ${w}", ("s", _sent.load())("a", _acknowledged.load())("w", waited)); } + if (_errors.load()) { + elog("${n} errors reported during http calls, see logs", ("n", _errors.load())); + } } bool http_connection::needs_response_trace_info() { @@ -151,10 +156,17 @@ namespace eosio::testing { trx_acknowledged(trx_id, fc::time_point::now()); if (ec) { elog("http error: ${c}: ${m}", ("c", ec.value())("m", ec.message())); - throw std::runtime_error(ec.message()); + ++_errors; + return; } if (this->needs_response_trace_info() && response.result() == boost::beast::http::status::ok) { + bool exception = false; + auto exception_handler = [this, &response, &exception](const fc::exception_ptr& ex) { + elog("Fail to parse JSON from string: ${string}", ("string", response.body())); + ++_errors; + exception = true; + }; try { fc::variant resp_json = fc::json::from_string(response.body()); if (resp_json.is_object() && resp_json.get_object().contains("processed")) { @@ -186,9 +198,9 @@ namespace eosio::testing { elog("async_http_request Transaction failed, transaction not processed: ${string}", ("string", response.body())); } - } - EOS_RETHROW_EXCEPTIONS(chain::json_parse_exception, "Fail to parse JSON from string: ${string}", - ("string", response.body())); + } CATCH_AND_CALL(exception_handler) + if (exception) + return; } if (!(response.result() == boost::beast::http::status::accepted || diff --git a/tests/trx_generator/trx_provider.hpp b/tests/trx_generator/trx_provider.hpp index f5685fe06b..df8fa3049a 100644 --- a/tests/trx_generator/trx_provider.hpp +++ b/tests/trx_generator/trx_provider.hpp @@ -88,6 +88,7 @@ namespace eosio::testing { std::atomic _acknowledged{0}; std::atomic _sent{0}; + std::atomic _errors{0}; explicit http_connection(const provider_base_config& provider_config) : provider_connection(provider_config) {} From eecd4c5dfb819dfa3af65147024b1f09abe92562 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 6 Nov 2023 11:53:37 -0600 Subject: [PATCH 2/2] GH-1858 Use one strand --- tests/trx_generator/http_client_async.hpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/trx_generator/http_client_async.hpp b/tests/trx_generator/http_client_async.hpp index 7aad239e5c..4fc754c922 100644 --- a/tests/trx_generator/http_client_async.hpp +++ b/tests/trx_generator/http_client_async.hpp @@ -4,6 +4,9 @@ // libs/beast/example/http/client/async/http_client_async.cpp // with minimum modification and yet reusable. // +// Updated to use strand like in the boost example +// libs/beast/example/http/client/crawl/http_crawl.cpp +// // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // @@ -48,6 +51,7 @@ inline void fail(beast::error_code ec, char const* what) { std::cerr << what << // Performs an HTTP GET and prints the response class session : public std::enable_shared_from_this { + net::strand ex_; tcp::resolver resolver_; beast::tcp_stream stream_; beast::flat_buffer buffer_; // (Must persist between reads) @@ -59,8 +63,9 @@ class session : public std::enable_shared_from_this { // Objects are constructed with a strand to // ensure that handlers do not execute concurrently. explicit session(net::io_context& ioc, const response_callback_t& response_callback) - : resolver_(net::make_strand(ioc)) - , stream_(net::make_strand(ioc)) + : ex_(net::make_strand(ioc.get_executor())) + , resolver_(ex_) + , stream_(ex_) , response_callback_(response_callback) {} // Start the asynchronous operation