From 3abe789f76384c46d95a3c8c9c3a2416b96846d1 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Mon, 3 Apr 2023 13:50:29 -0400 Subject: [PATCH 1/8] Add generic `make_api_entry` function which splits processing between main thread and http thread pool --- plugins/chain_api_plugin/chain_api_plugin.cpp | 85 +++++++++++-------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/plugins/chain_api_plugin/chain_api_plugin.cpp b/plugins/chain_api_plugin/chain_api_plugin.cpp index ba5c92272b..1b71810c7f 100644 --- a/plugins/chain_api_plugin/chain_api_plugin.cpp +++ b/plugins/chain_api_plugin/chain_api_plugin.cpp @@ -62,6 +62,32 @@ parse_params +static api_entry make_api_entry(http_plugin &_http_plugin, API& api, const char* api_name, + const char* call_name, PARAMS_PARSER params_parser, HANDLER handler) { + return api_entry( + std::string("/v1/") + api_name + "/" + call_name, + [&_http_plugin, api, api_name, call_name, + params_parser = std::move(params_parser), handler = std::move(handler)](string&&, string&& body, url_response_callback&& cb) { + auto deadline = api.start(); + try { + auto start = fc::time_point::now(); + auto params = params_parser(body); + FC_CHECK_DEADLINE(deadline); + + // call first handler on main thread (likely because it accesses non thread-safe data) + // returns a thread-safe lambda that can be enqueued on the http thread pool to complete the request + auto completion_handler = handler(api, start, deadline, params, cb); + FC_CHECK_DEADLINE(deadline); // make sure remaining time is > 0 + + // execute thread-safe http_handler on _http_plugin's thread pool + _http_plugin.post_http_thread_pool(std::move(completion_handler)); + } catch (...) { + http_plugin::handle_exception(api_name, call_name, body, cb); + } + }); +} + void chain_api_plugin::plugin_startup() { ilog( "starting chain_api_plugin" ); my.reset(new chain_api_plugin_impl(app().get_plugin().chain())); @@ -128,41 +154,32 @@ void chain_api_plugin::plugin_startup() { } _http_plugin.add_api({ - { std::string("/v1/chain/get_block"), - [ro_api, &_http_plugin, max_time=std::min(chain.get_abi_serializer_max_time(),max_response_time)] - ( string&&, string&& body, url_response_callback&& cb ) mutable { - auto deadline = ro_api.start(); - try { - auto start = fc::time_point::now(); - auto params = parse_params(body); - FC_CHECK_DEADLINE( deadline ); - chain::signed_block_ptr block = ro_api.get_raw_block( params, deadline ); - - auto abi_cache = ro_api.get_block_serializers( block, max_time ); - FC_CHECK_DEADLINE( deadline ); - - auto post_time = fc::time_point::now(); - auto remaining_time = max_time - (post_time - start); - _http_plugin.post_http_thread_pool( - [ro_api, cb, deadline, post_time, remaining_time, abi_cache{std::move(abi_cache)}, block{std::move( block )}]() mutable { - try { - auto new_deadline = deadline + (fc::time_point::now() - post_time); - - fc::variant result = ro_api.convert_block( block, std::move(abi_cache), remaining_time ); - - cb( 200, new_deadline, std::move( result ) ); - } catch( ... ) { - http_plugin::handle_exception( "chain", "get_block", "", cb ); - } - } ); - } catch( ... ) { - http_plugin::handle_exception("chain", "get_block", body, cb); - } - } - } - }, appbase::exec_queue::read_only); + make_api_entry( + _http_plugin, ro_api, "chain", "get_block", + [](const string& body) { + return parse_params(body); + }, + [max_response_time, &chain](auto& api, fc::time_point start, fc::time_point deadline, auto ¶ms, const url_response_callback &cb) { + + chain::signed_block_ptr block = api.get_raw_block(params, deadline); + auto max_time = std::min(chain.get_abi_serializer_max_time(), max_response_time); + auto abi_cache = api.get_block_serializers(block, max_time); + auto post_time = fc::time_point::now(); + auto remaining_time = max_time - (post_time - start); + + return [api, cb, deadline, post_time, remaining_time, abi_cache=std::move(abi_cache), block=std::move(block)]() mutable { + try { + auto new_deadline = deadline + (fc::time_point::now() - post_time); + fc::variant result = api.convert_block(block, std::move(abi_cache), remaining_time); + cb(200, new_deadline, std::move(result)); + } catch( ... ) { + http_plugin::handle_exception("chain", "get_block", "", cb); + } + }; + })}, + appbase::exec_queue::read_only); } - + void chain_api_plugin::plugin_shutdown() {} } From be8217f31ac4d5cb91a7cbf96bc9d9ccf9cf50e6 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Wed, 5 Apr 2023 11:35:31 -0400 Subject: [PATCH 2/8] unify definitions of `next_function` and its parameter So that it is defined in a single location (DRY) and can be easily updated. --- .../eosio/chain/transaction_metadata.hpp | 6 +++++ .../chain/unapplied_transaction_queue.hpp | 2 +- .../include/eosio/chain/plugin_interface.hpp | 8 ++----- plugins/chain_plugin/chain_plugin.cpp | 17 +++++++------- .../eosio/chain_plugin/chain_plugin.hpp | 2 +- .../eosio/chain_plugin/trx_retry_db.hpp | 6 ++--- .../chain_plugin/test/test_trx_retry_db.cpp | 23 +++++++++---------- plugins/chain_plugin/trx_retry_db.cpp | 2 +- plugins/net_plugin/net_plugin.cpp | 2 +- .../producer_api_plugin.cpp | 10 ++++---- .../eosio/producer_plugin/producer_plugin.hpp | 2 +- .../producer_plugin/snapshot_scheduler.hpp | 2 +- plugins/producer_plugin/producer_plugin.cpp | 4 ++-- .../test/test_read_only_trx.cpp | 2 +- .../producer_plugin/test/test_trx_full.cpp | 2 +- 15 files changed, 46 insertions(+), 44 deletions(-) diff --git a/libraries/chain/include/eosio/chain/transaction_metadata.hpp b/libraries/chain/include/eosio/chain/transaction_metadata.hpp index 5e585df6e7..bdb612bb78 100644 --- a/libraries/chain/include/eosio/chain/transaction_metadata.hpp +++ b/libraries/chain/include/eosio/chain/transaction_metadata.hpp @@ -10,6 +10,12 @@ namespace boost { namespace asio { namespace eosio { namespace chain { +template +using next_function_variant = std::variant>; + +template +using next_function = std::function&)>; + class transaction_metadata; using transaction_metadata_ptr = std::shared_ptr; using recover_keys_future = std::future; diff --git a/libraries/chain/include/eosio/chain/unapplied_transaction_queue.hpp b/libraries/chain/include/eosio/chain/unapplied_transaction_queue.hpp index e8b3ad26c4..7677caa5b5 100644 --- a/libraries/chain/include/eosio/chain/unapplied_transaction_queue.hpp +++ b/libraries/chain/include/eosio/chain/unapplied_transaction_queue.hpp @@ -27,7 +27,7 @@ enum class trx_enum_type { incoming_p2p = 4 // incoming_end() needs to be updated if this changes }; -using next_func_t = std::function&)>; +using next_func_t = next_function; struct unapplied_transaction { const transaction_metadata_ptr trx_meta; diff --git a/plugins/chain_interface/include/eosio/chain/plugin_interface.hpp b/plugins/chain_interface/include/eosio/chain/plugin_interface.hpp index d9b458184a..845314a558 100644 --- a/plugins/chain_interface/include/eosio/chain/plugin_interface.hpp +++ b/plugins/chain_interface/include/eosio/chain/plugin_interface.hpp @@ -8,13 +8,9 @@ #include #include -namespace eosio { namespace chain { namespace plugin_interface { +namespace eosio::chain::plugin_interface { using namespace eosio::chain; using namespace appbase; - - template - using next_function = std::function&)>; - struct chain_plugin_interface; namespace channels { @@ -50,4 +46,4 @@ namespace eosio { namespace chain { namespace plugin_interface { } } -} } } +} // namespace eosio::chain::plugin_interface diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index 86d877b413..3baa801ea4 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -2095,7 +2095,7 @@ void read_write::push_transaction(const read_write::push_transaction_params& par } EOS_RETHROW_EXCEPTIONS(chain::packed_transaction_type_exception, "Invalid packed transaction") app().get_method()(pretty_input, true, transaction_metadata::trx_type::input, false, - [this, next](const std::variant& result) -> void { + [this, next](const next_function_variant& result) -> void { if (std::holds_alternative(result)) { next(std::get(result)); } else { @@ -2169,13 +2169,15 @@ void read_write::push_transaction(const read_write::push_transaction_params& par } static void push_recurse(read_write* rw, int index, const std::shared_ptr& params, const std::shared_ptr& results, const next_function& next) { - auto wrapped_next = [=](const std::variant& result) { + auto wrapped_next = [=](const next_function_variant& result) { if (std::holds_alternative(result)) { const auto& e = std::get(result); results->emplace_back( read_write::push_transaction_results{ transaction_id_type(), fc::mutable_variant_object( "error", e->to_detail_string() ) } ); - } else { + } else if (std::holds_alternative(result)) { const auto& r = std::get(result); results->emplace_back( r ); + } else { + assert(0); } size_t next_index = index + 1; @@ -2214,12 +2216,11 @@ void read_write::send_transaction(const read_write::send_transaction_params& par } EOS_RETHROW_EXCEPTIONS(chain::packed_transaction_type_exception, "Invalid packed transaction") app().get_method()(pretty_input, true, transaction_metadata::trx_type::input, false, - [this, next](const std::variant& result) -> void { + [this, next](const next_function_variant& result) -> void { if (std::holds_alternative(result)) { next(std::get(result)); } else { auto trx_trace_ptr = std::get(result); - try { fc::variant output; try { @@ -2257,7 +2258,7 @@ void read_write::send_transaction2(const read_write::send_transaction2_params& p ("e", ptrx->expiration())("m", trx_retry->get_max_expiration_time()) ); app().get_method()(ptrx, true, transaction_metadata::trx_type::input, static_cast(params.return_failure_trace), - [this, ptrx, next, retry, retry_num_blocks](const std::variant& result) -> void { + [this, ptrx, next, retry, retry_num_blocks](const next_function_variant& result) -> void { if( std::holds_alternative( result ) ) { next( std::get( result ) ); } else { @@ -2266,7 +2267,7 @@ void read_write::send_transaction2(const read_write::send_transaction2_params& p if( retry && trx_retry.has_value() && !trx_trace_ptr->except) { // will be ack'ed via next later trx_retry->track_transaction( ptrx, retry_num_blocks, - [ptrx, next](const std::variant>& result ) { + [ptrx, next](const next_function_variant>& result ) { if( std::holds_alternative( result ) ) { next( std::get( result ) ); } else { @@ -2566,7 +2567,7 @@ void read_only::send_transient_transaction(const Params& params, next_function()(pretty_input, true /* api_trx */, trx_type, true /* return_failure_trace */, - [this, next](const std::variant& result) -> void { + [this, next](const next_function_variant& result) -> void { if (std::holds_alternative(result)) { next(std::get(result)); } else { diff --git a/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp b/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp index 8868fd3eaa..b09fe05496 100644 --- a/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp +++ b/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp @@ -718,7 +718,7 @@ class read_only { private: template - void send_transient_transaction(const Params& params, next_function next, chain::transaction_metadata::trx_type trx_type) const; + void send_transient_transaction(const Params& params, eosio::chain::next_function next, chain::transaction_metadata::trx_type trx_type) const; }; class read_write { diff --git a/plugins/chain_plugin/include/eosio/chain_plugin/trx_retry_db.hpp b/plugins/chain_plugin/include/eosio/chain_plugin/trx_retry_db.hpp index 866cd14549..7569d899a1 100644 --- a/plugins/chain_plugin/include/eosio/chain_plugin/trx_retry_db.hpp +++ b/plugins/chain_plugin/include/eosio/chain_plugin/trx_retry_db.hpp @@ -2,12 +2,10 @@ #include #include #include +#include namespace eosio::chain_apis { -template -using next_function = std::function&)>; - /** * This class manages the ephemeral indices and data that provide the transaction retry feature. * It is designed to be run on an API node, as it only tracks incoming API transactions. @@ -51,7 +49,7 @@ class trx_retry_db { * @param next report result to user by calling next * @throws throw tx_resource_exhaustion if trx would exceeds max_mem_usage_size */ - void track_transaction( chain::packed_transaction_ptr ptrx, std::optional num_blocks, next_function> next ); + void track_transaction( chain::packed_transaction_ptr ptrx, std::optional num_blocks, eosio::chain::next_function> next ); /** * Attach to chain applied_transaction signal diff --git a/plugins/chain_plugin/test/test_trx_retry_db.cpp b/plugins/chain_plugin/test/test_trx_retry_db.cpp index ba211c4fef..a58d399b73 100644 --- a/plugins/chain_plugin/test/test_trx_retry_db.cpp +++ b/plugins/chain_plugin/test/test_trx_retry_db.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include @@ -259,14 +258,14 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { auto lib = std::optional{}; auto trx_1 = make_unique_trx(chain->get_chain_id(), fc::seconds(2), 1); bool trx_1_expired = false; - trx_retry.track_transaction( trx_1, lib, [&trx_1_expired](const std::variant>& result){ + trx_retry.track_transaction( trx_1, lib, [&trx_1_expired](const next_function_variant>& result){ BOOST_REQUIRE( std::holds_alternative(result) ); BOOST_CHECK_EQUAL( std::get(result)->code(), expired_tx_exception::code_value ); trx_1_expired = true; } ); auto trx_2 = make_unique_trx(chain->get_chain_id(), fc::seconds(4), 2); bool trx_2_expired = false; - trx_retry.track_transaction( trx_2, lib, [&trx_2_expired](const std::variant>& result){ + trx_retry.track_transaction( trx_2, lib, [&trx_2_expired](const next_function_variant>& result){ BOOST_REQUIRE( std::holds_alternative(result) ); BOOST_CHECK_EQUAL( std::get(result)->code(), expired_tx_exception::code_value ); trx_2_expired = true; @@ -305,7 +304,7 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { // auto trx_3 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 3); bool trx_3_expired = false; - trx_retry.track_transaction( trx_3, lib, [&trx_3_expired](const std::variant>& result){ + trx_retry.track_transaction( trx_3, lib, [&trx_3_expired](const next_function_variant>& result){ BOOST_REQUIRE( std::holds_alternative(result) ); BOOST_CHECK_EQUAL( std::get(result)->code(), expired_tx_exception::code_value ); trx_3_expired = true; @@ -315,7 +314,7 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { fc::mock_time_traits::set_now(pnow); auto trx_4 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 4); bool trx_4_expired = false; - trx_retry.track_transaction( trx_4, lib, [&trx_4_expired](const std::variant>& result){ + trx_retry.track_transaction( trx_4, lib, [&trx_4_expired](const next_function_variant>& result){ BOOST_REQUIRE( std::holds_alternative(result) ); BOOST_CHECK_EQUAL( std::get(result)->code(), expired_tx_exception::code_value ); trx_4_expired = true; @@ -358,7 +357,7 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { // auto trx_5 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 5); bool trx_5_variant = false; - trx_retry.track_transaction( trx_5, lib, [&trx_5_variant](const std::variant>& result){ + trx_retry.track_transaction( trx_5, lib, [&trx_5_variant](const next_function_variant>& result){ BOOST_REQUIRE( std::holds_alternative>(result) ); BOOST_CHECK( !!std::get>(result) ); trx_5_variant = true; @@ -368,7 +367,7 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { fc::mock_time_traits::set_now(pnow); auto trx_6 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 6); bool trx_6_variant = false; - trx_retry.track_transaction( trx_6, std::optional(2), [&trx_6_variant](const std::variant>& result){ + trx_retry.track_transaction( trx_6, std::optional(2), [&trx_6_variant](const next_function_variant>& result){ BOOST_REQUIRE( std::holds_alternative>(result) ); BOOST_CHECK( !!std::get>(result) ); trx_6_variant = true; @@ -427,7 +426,7 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { // auto trx_7 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 7); bool trx_7_variant = false; - trx_retry.track_transaction( trx_7, lib, [&trx_7_variant](const std::variant>& result){ + trx_retry.track_transaction( trx_7, lib, [&trx_7_variant](const next_function_variant>& result){ BOOST_REQUIRE( std::holds_alternative>(result) ); BOOST_CHECK( !!std::get>(result) ); trx_7_variant = true; @@ -437,7 +436,7 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { fc::mock_time_traits::set_now(pnow); auto trx_8 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 8); bool trx_8_variant = false; - trx_retry.track_transaction( trx_8, std::optional(3), [&trx_8_variant](const std::variant>& result){ + trx_retry.track_transaction( trx_8, std::optional(3), [&trx_8_variant](const next_function_variant>& result){ BOOST_REQUIRE( std::holds_alternative>(result) ); BOOST_CHECK( !!std::get>(result) ); trx_8_variant = true; @@ -445,7 +444,7 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { // one to expire, will be forked out never to return auto trx_9 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 9); bool trx_9_expired = false; - trx_retry.track_transaction( trx_9, lib, [&trx_9_expired](const std::variant>& result){ + trx_retry.track_transaction( trx_9, lib, [&trx_9_expired](const next_function_variant>& result){ BOOST_REQUIRE( std::holds_alternative(result) ); BOOST_CHECK_EQUAL( std::get(result)->code(), expired_tx_exception::code_value ); trx_9_expired = true; @@ -586,14 +585,14 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { // auto trx_10 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 10); bool trx_10_variant = false; - trx_retry.track_transaction( trx_10, std::optional(0), [&trx_10_variant](const std::variant>& result){ + trx_retry.track_transaction( trx_10, std::optional(0), [&trx_10_variant](const next_function_variant>& result){ BOOST_REQUIRE( std::holds_alternative>(result) ); BOOST_CHECK( !!std::get>(result) ); trx_10_variant = true; } ); auto trx_11 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 11); bool trx_11_variant = false; - trx_retry.track_transaction( trx_11, std::optional(1), [&trx_11_variant](const std::variant>& result){ + trx_retry.track_transaction( trx_11, std::optional(1), [&trx_11_variant](const next_function_variant>& result){ BOOST_REQUIRE( std::holds_alternative>(result) ); BOOST_CHECK( !!std::get>(result) ); trx_11_variant = true; diff --git a/plugins/chain_plugin/trx_retry_db.cpp b/plugins/chain_plugin/trx_retry_db.cpp index 622c635e34..dd617279f0 100644 --- a/plugins/chain_plugin/trx_retry_db.cpp +++ b/plugins/chain_plugin/trx_retry_db.cpp @@ -31,7 +31,7 @@ struct tracked_transaction { uint32_t block_num = 0; fc::variant trx_trace_v; fc::time_point last_try; - chain_apis::next_function> next; + next_function> next; const transaction_id_type& id()const { return ptrx->id(); } fc::time_point_sec expiry()const { return ptrx->expiration(); } diff --git a/plugins/net_plugin/net_plugin.cpp b/plugins/net_plugin/net_plugin.cpp index 79c97668d8..7f1a90d551 100644 --- a/plugins/net_plugin/net_plugin.cpp +++ b/plugins/net_plugin/net_plugin.cpp @@ -3166,7 +3166,7 @@ namespace eosio { trx_in_progress_size += calc_trx_size( trx ); my_impl->chain_plug->accept_transaction( trx, - [weak = weak_from_this(), trx](const std::variant& result) mutable { + [weak = weak_from_this(), trx](const next_function_variant& result) mutable { // next (this lambda) called from application thread if (std::holds_alternative(result)) { fc_dlog( logger, "bad packed_transaction : ${m}", ("m", std::get(result)->what()) ); diff --git a/plugins/producer_api_plugin/producer_api_plugin.cpp b/plugins/producer_api_plugin/producer_api_plugin.cpp index cd18009b2f..a8f84a0fa8 100644 --- a/plugins/producer_api_plugin/producer_api_plugin.cpp +++ b/plugins/producer_api_plugin/producer_api_plugin.cpp @@ -43,16 +43,18 @@ struct async_result_visitor : public fc::visitor { {std::string("/v1/" #api_name "/" #call_name), \ [&api_handle](string&&, string&& body, url_response_callback&& cb) mutable { \ if (body.empty()) body = "{}"; \ - auto next = [cb=std::move(cb), body=std::move(body)](const std::variant& result){ \ + auto next = [cb=std::move(cb), body=std::move(body)](const chain::next_function_variant& result){ \ if (std::holds_alternative(result)) {\ try {\ std::get(result)->dynamic_rethrow_exception();\ } catch (...) {\ http_plugin::handle_exception(#api_name, #call_name, body, cb);\ }\ - } else {\ - cb(http_response_code, fc::time_point::maximum(), std::visit(async_result_visitor(), result));\ - }\ + } else if (std::holds_alternative(result)) { \ + cb(http_response_code, fc::time_point::maximum(), fc::variant(std::get(result)));\ + } else { \ + assert(0); \ + } \ };\ INVOKE\ }\ diff --git a/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp b/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp index 37f0ec45be..01702ea9aa 100644 --- a/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp +++ b/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp @@ -124,7 +124,7 @@ class producer_plugin : public appbase::plugin { }; template - using next_function = std::function&)>; + using next_function = eosio::chain::next_function; producer_plugin(); virtual ~producer_plugin(); diff --git a/plugins/producer_plugin/include/eosio/producer_plugin/snapshot_scheduler.hpp b/plugins/producer_plugin/include/eosio/producer_plugin/snapshot_scheduler.hpp index 4515659aa8..ad6e005f63 100644 --- a/plugins/producer_plugin/include/eosio/producer_plugin/snapshot_scheduler.hpp +++ b/plugins/producer_plugin/include/eosio/producer_plugin/snapshot_scheduler.hpp @@ -176,7 +176,7 @@ class snapshot_scheduler { void execute_snapshot(uint32_t srid) { _inflight_sid = srid; - auto next = [srid, this](const std::variant& result) { + auto next = [srid, this](const chain::next_function_variant& result) { if(std::holds_alternative(result)) { try { std::get(result)->dynamic_rethrow_exception(); diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index e79aac762a..b026ecc321 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -694,7 +694,7 @@ class producer_plugin_impl : public std::enable_shared_from_this& response ) { + next = [this, trx, next{std::move(next)}]( const next_function_variant& response ) { next( response ); fc::exception_ptr except_ptr; // rejected @@ -1530,7 +1530,7 @@ void producer_plugin::create_snapshot(producer_plugin::next_function& res){ + entry.next = [prev = entry.next, next](const next_function_variant& res){ prev(res); next(res); }; diff --git a/plugins/producer_plugin/test/test_read_only_trx.cpp b/plugins/producer_plugin/test/test_read_only_trx.cpp index d55291d2c9..3184501686 100644 --- a/plugins/producer_plugin/test/test_read_only_trx.cpp +++ b/plugins/producer_plugin/test/test_read_only_trx.cpp @@ -117,7 +117,7 @@ void test_trxs_common(std::vector& specific_args) { transaction_metadata::trx_type::read_only, // trx_type return_failure_traces, [ptrx, &next_calls, &trace_with_except, &trx_match, return_failure_traces] - (const std::variant& result) { + (const next_function_variant& result) { if( !std::holds_alternative( result ) && !std::get( result )->except ) { if( std::get( result )->id != ptrx->id() ) { elog( "trace not for trx ${id}: ${t}", diff --git a/plugins/producer_plugin/test/test_trx_full.cpp b/plugins/producer_plugin/test/test_trx_full.cpp index 4473b06d26..4304cccb5e 100644 --- a/plugins/producer_plugin/test/test_trx_full.cpp +++ b/plugins/producer_plugin/test/test_trx_full.cpp @@ -163,7 +163,7 @@ BOOST_AUTO_TEST_CASE(producer) { transaction_metadata::trx_type::input, // trx_type return_failure_traces, // return_failure_traces [ptrx, &next_calls, &trace_with_except, &trx_match, &trxs, return_failure_traces] - (const std::variant& result) { + (const next_function_variant& result) { if( !std::holds_alternative( result ) && !std::get( result )->except ) { if( std::get( result )->id == ptrx->id() ) { trxs.push_back( ptrx ); From a2d676e517182f566989b696017065731a10477f Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Wed, 5 Apr 2023 13:04:32 -0400 Subject: [PATCH 3/8] Missed needed change in macros.hpp --- plugins/http_plugin/include/eosio/http_plugin/macros.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/http_plugin/include/eosio/http_plugin/macros.hpp b/plugins/http_plugin/include/eosio/http_plugin/macros.hpp index f217b94962..014b17eb28 100644 --- a/plugins/http_plugin/include/eosio/http_plugin/macros.hpp +++ b/plugins/http_plugin/include/eosio/http_plugin/macros.hpp @@ -15,7 +15,7 @@ struct async_result_visitor : public fc::visitor { auto params = parse_params(body);\ FC_CHECK_DEADLINE(deadline);\ api_handle.call_name( std::move(params), \ - [cb=std::move(cb), body=std::move(body)](const std::variant& result){ \ + [cb=std::move(cb), body=std::move(body)](const eosio::chain::next_function_variant& result){ \ if (std::holds_alternative(result)) {\ try {\ std::get(result)->dynamic_rethrow_exception();\ From 3f9f7045879dcac367e482b596330f1c2c799616 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Wed, 5 Apr 2023 13:14:46 -0400 Subject: [PATCH 4/8] Missed another needed change --- .../include/eosio/http_plugin/macros.hpp | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/plugins/http_plugin/include/eosio/http_plugin/macros.hpp b/plugins/http_plugin/include/eosio/http_plugin/macros.hpp index 014b17eb28..0e8fb7d694 100644 --- a/plugins/http_plugin/include/eosio/http_plugin/macros.hpp +++ b/plugins/http_plugin/include/eosio/http_plugin/macros.hpp @@ -8,26 +8,28 @@ struct async_result_visitor : public fc::visitor { }; #define CALL_ASYNC_WITH_400(api_name, api_handle, api_namespace, call_name, call_result, http_response_code, params_type) \ -{std::string("/v1/" #api_name "/" #call_name), \ - [api_handle](string&&, string&& body, url_response_callback&& cb) mutable { \ - auto deadline = api_handle.start(); \ - try { \ - auto params = parse_params(body);\ - FC_CHECK_DEADLINE(deadline);\ - api_handle.call_name( std::move(params), \ +{std::string("/v1/" #api_name "/" #call_name), \ + [api_handle](string&&, string&& body, url_response_callback&& cb) mutable { \ + auto deadline = api_handle.start(); \ + try { \ + auto params = parse_params(body); \ + FC_CHECK_DEADLINE(deadline); \ + api_handle.call_name( std::move(params), \ [cb=std::move(cb), body=std::move(body)](const eosio::chain::next_function_variant& result){ \ - if (std::holds_alternative(result)) {\ - try {\ - std::get(result)->dynamic_rethrow_exception();\ - } catch (...) {\ - http_plugin::handle_exception(#api_name, #call_name, body, cb);\ - }\ - } else {\ - cb(http_response_code, fc::time_point::maximum(), std::visit(async_result_visitor(), result));\ - }\ - });\ - } catch (...) { \ - http_plugin::handle_exception(#api_name, #call_name, body, cb); \ - } \ - }\ + if (std::holds_alternative(result)) { \ + try { \ + std::get(result)->dynamic_rethrow_exception(); \ + } catch (...) { \ + http_plugin::handle_exception(#api_name, #call_name, body, cb); \ + } \ + } else if (std::holds_alternative(result)) { \ + cb(http_response_code, fc::time_point::maximum(), fc::variant(std::get(result))); \ + } else { \ + assert(0); \ + } \ + }); \ + } catch (...) { \ + http_plugin::handle_exception(#api_name, #call_name, body, cb); \ + } \ + } \ } From 01b992ce05c449b90389ebe8f46594fc28717534 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Wed, 5 Apr 2023 22:03:26 -0400 Subject: [PATCH 5/8] Address some PR comments (define types in `types.hpp` and add comments) --- .../eosio/chain/transaction_metadata.hpp | 6 ------ libraries/chain/include/eosio/chain/types.hpp | 18 ++++++++++++++++-- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/libraries/chain/include/eosio/chain/transaction_metadata.hpp b/libraries/chain/include/eosio/chain/transaction_metadata.hpp index bdb612bb78..5e585df6e7 100644 --- a/libraries/chain/include/eosio/chain/transaction_metadata.hpp +++ b/libraries/chain/include/eosio/chain/transaction_metadata.hpp @@ -10,12 +10,6 @@ namespace boost { namespace asio { namespace eosio { namespace chain { -template -using next_function_variant = std::variant>; - -template -using next_function = std::function&)>; - class transaction_metadata; using transaction_metadata_ptr = std::shared_ptr; using recover_keys_future = std::future; diff --git a/libraries/chain/include/eosio/chain/types.hpp b/libraries/chain/include/eosio/chain/types.hpp index 97b64ed70a..a29b4e5f31 100644 --- a/libraries/chain/include/eosio/chain/types.hpp +++ b/libraries/chain/include/eosio/chain/types.hpp @@ -43,7 +43,7 @@ #define _V(n, v) fc::mutable_variant_object(n, v) -namespace eosio { namespace chain { +namespace eosio::chain { using std::map; using std::vector; using std::unordered_map; @@ -396,7 +396,21 @@ namespace eosio { namespace chain { template struct overloaded : Ts... { using Ts::operator()...; }; template overloaded(Ts...) -> overloaded; -} } // eosio::chain + // next_function is a function passed to an API (like send_transaction) and which is called at the end of + // the API processing on the main thread. The type T is a description for the API result. + // The function accepts a variant which can contain an exception_ptr (if an exception occured while + // processing the API) of the result T. + // The last option is a function which can be executed in a multithreaded context (likely on the + // http_plugin thread pool) and which completes the API processing and returns the result T. + // ------------------------------------------------------------------------------------------------------- + template + using next_function_variant = std::variant>; + + template + using next_function = std::function&)>; + + +} // eosio::chain namespace chainbase { // chainbase::shared_cow_string From 1d039b67492f43e69aa237a7964d7855501a9b94 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Wed, 5 Apr 2023 22:06:56 -0400 Subject: [PATCH 6/8] Update whitespace as per PR comments. --- plugins/chain_api_plugin/chain_api_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/chain_api_plugin/chain_api_plugin.cpp b/plugins/chain_api_plugin/chain_api_plugin.cpp index 1b71810c7f..7f011804f1 100644 --- a/plugins/chain_api_plugin/chain_api_plugin.cpp +++ b/plugins/chain_api_plugin/chain_api_plugin.cpp @@ -63,7 +63,7 @@ parse_params -static api_entry make_api_entry(http_plugin &_http_plugin, API& api, const char* api_name, +static api_entry make_api_entry(http_plugin& _http_plugin, API& api, const char* api_name, const char* call_name, PARAMS_PARSER params_parser, HANDLER handler) { return api_entry( std::string("/v1/") + api_name + "/" + call_name, From 74575d34048e9b2ca30fdfd59264a55328f0621b Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Wed, 5 Apr 2023 22:13:46 -0400 Subject: [PATCH 7/8] Fix a couple typos. --- libraries/chain/include/eosio/chain/types.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/chain/include/eosio/chain/types.hpp b/libraries/chain/include/eosio/chain/types.hpp index a29b4e5f31..65d6080099 100644 --- a/libraries/chain/include/eosio/chain/types.hpp +++ b/libraries/chain/include/eosio/chain/types.hpp @@ -397,10 +397,11 @@ namespace eosio::chain { template overloaded(Ts...) -> overloaded; // next_function is a function passed to an API (like send_transaction) and which is called at the end of - // the API processing on the main thread. The type T is a description for the API result. + // the API processing on the main thread. The type T is a description of the API result that can be + // serialized as output. // The function accepts a variant which can contain an exception_ptr (if an exception occured while - // processing the API) of the result T. - // The last option is a function which can be executed in a multithreaded context (likely on the + // processing the API) or the result T. + // The third option is a function which can be executed in a multithreaded context (likely on the // http_plugin thread pool) and which completes the API processing and returns the result T. // ------------------------------------------------------------------------------------------------------- template @@ -409,7 +410,6 @@ namespace eosio::chain { template using next_function = std::function&)>; - } // eosio::chain namespace chainbase { From 8f90505d3e3a05c239976b411a329d9eba6d1e46 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Fri, 7 Apr 2023 08:31:54 -0400 Subject: [PATCH 8/8] remove unnecessary header addition --- plugins/chain_plugin/include/eosio/chain_plugin/trx_retry_db.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/chain_plugin/include/eosio/chain_plugin/trx_retry_db.hpp b/plugins/chain_plugin/include/eosio/chain_plugin/trx_retry_db.hpp index 7569d899a1..ebad51a18a 100644 --- a/plugins/chain_plugin/include/eosio/chain_plugin/trx_retry_db.hpp +++ b/plugins/chain_plugin/include/eosio/chain_plugin/trx_retry_db.hpp @@ -2,7 +2,6 @@ #include #include #include -#include namespace eosio::chain_apis {