Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify definitions of next_function and its variant parameter #973

Merged
merged 10 commits into from
Apr 7, 2023
6 changes: 6 additions & 0 deletions libraries/chain/include/eosio/chain/transaction_metadata.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ namespace boost { namespace asio {

namespace eosio { namespace chain {

template<typename T>
using next_function_variant = std::variant<fc::exception_ptr, T, std::function<void()>>;
heifner marked this conversation as resolved.
Show resolved Hide resolved

template<typename T>
using next_function = std::function<void(const next_function_variant<T>&)>;
heifner marked this conversation as resolved.
Show resolved Hide resolved

class transaction_metadata;
using transaction_metadata_ptr = std::shared_ptr<transaction_metadata>;
using recover_keys_future = std::future<transaction_metadata_ptr>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<void(const std::variant<fc::exception_ptr, transaction_trace_ptr>&)>;
using next_func_t = next_function<transaction_trace_ptr>;

struct unapplied_transaction {
const transaction_metadata_ptr trx_meta;
Expand Down
85 changes: 51 additions & 34 deletions plugins/chain_api_plugin/chain_api_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,32 @@ parse_params<chain_apis::read_only::get_transaction_status_params, http_params_t

#define CHAIN_RO_CALL_WITH_400(call_name, http_response_code, params_type) CALL_WITH_400(chain, ro_api, chain_apis::read_only, call_name, http_response_code, params_type)

template<class API, class PARAMS_PARSER, class HANDLER>
static api_entry make_api_entry(http_plugin &_http_plugin, API& api, const char* api_name,
heifner marked this conversation as resolved.
Show resolved Hide resolved
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_plugin>().chain()));
Expand Down Expand Up @@ -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<chain_apis::read_only::get_raw_block_params, http_params_types::params_required>(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<chain_apis::read_only::get_raw_block_params, http_params_types::params_required>(body);
},
[max_response_time, &chain](auto& api, fc::time_point start, fc::time_point deadline, auto &params, 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() {}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,9 @@
#include <eosio/chain/transaction_metadata.hpp>
#include <eosio/chain/trace.hpp>

namespace eosio { namespace chain { namespace plugin_interface {
namespace eosio::chain::plugin_interface {
using namespace eosio::chain;
using namespace appbase;

template<typename T>
using next_function = std::function<void(const std::variant<fc::exception_ptr, T>&)>;

struct chain_plugin_interface;

namespace channels {
Expand Down Expand Up @@ -50,4 +46,4 @@ namespace eosio { namespace chain { namespace plugin_interface {
}
}

} } }
} // namespace eosio::chain::plugin_interface
17 changes: 9 additions & 8 deletions plugins/chain_plugin/chain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<incoming::methods::transaction_async>()(pretty_input, true, transaction_metadata::trx_type::input, false,
[this, next](const std::variant<fc::exception_ptr, transaction_trace_ptr>& result) -> void {
[this, next](const next_function_variant<transaction_trace_ptr>& result) -> void {
if (std::holds_alternative<fc::exception_ptr>(result)) {
next(std::get<fc::exception_ptr>(result));
} else {
Expand Down Expand Up @@ -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<read_write::push_transactions_params>& params, const std::shared_ptr<read_write::push_transactions_results>& results, const next_function<read_write::push_transactions_results>& next) {
auto wrapped_next = [=](const std::variant<fc::exception_ptr, read_write::push_transaction_results>& result) {
auto wrapped_next = [=](const next_function_variant<read_write::push_transaction_results>& result) {
if (std::holds_alternative<fc::exception_ptr>(result)) {
const auto& e = std::get<fc::exception_ptr>(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<read_write::push_transaction_results>(result)) {
const auto& r = std::get<read_write::push_transaction_results>(result);
results->emplace_back( r );
} else {
assert(0);
heifner marked this conversation as resolved.
Show resolved Hide resolved
}

size_t next_index = index + 1;
Expand Down Expand Up @@ -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<incoming::methods::transaction_async>()(pretty_input, true, transaction_metadata::trx_type::input, false,
[this, next](const std::variant<fc::exception_ptr, transaction_trace_ptr>& result) -> void {
[this, next](const next_function_variant<transaction_trace_ptr>& result) -> void {
if (std::holds_alternative<fc::exception_ptr>(result)) {
next(std::get<fc::exception_ptr>(result));
} else {
auto trx_trace_ptr = std::get<transaction_trace_ptr>(result);

try {
fc::variant output;
try {
Expand Down Expand Up @@ -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<incoming::methods::transaction_async>()(ptrx, true, transaction_metadata::trx_type::input, static_cast<bool>(params.return_failure_trace),
[this, ptrx, next, retry, retry_num_blocks](const std::variant<fc::exception_ptr, transaction_trace_ptr>& result) -> void {
[this, ptrx, next, retry, retry_num_blocks](const next_function_variant<transaction_trace_ptr>& result) -> void {
if( std::holds_alternative<fc::exception_ptr>( result ) ) {
next( std::get<fc::exception_ptr>( result ) );
} else {
Expand All @@ -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<fc::exception_ptr, std::unique_ptr<fc::variant>>& result ) {
[ptrx, next](const next_function_variant<std::unique_ptr<fc::variant>>& result ) {
if( std::holds_alternative<fc::exception_ptr>( result ) ) {
next( std::get<fc::exception_ptr>( result ) );
} else {
Expand Down Expand Up @@ -2566,7 +2567,7 @@ void read_only::send_transient_transaction(const Params& params, next_function<R
} EOS_RETHROW_EXCEPTIONS(chain::packed_transaction_type_exception, "Invalid packed transaction")

app().get_method<incoming::methods::transaction_async>()(pretty_input, true /* api_trx */, trx_type, true /* return_failure_trace */,
[this, next](const std::variant<fc::exception_ptr, transaction_trace_ptr>& result) -> void {
[this, next](const next_function_variant<transaction_trace_ptr>& result) -> void {
if (std::holds_alternative<fc::exception_ptr>(result)) {
next(std::get<fc::exception_ptr>(result));
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,7 @@ class read_only {

private:
template<typename Params, typename Results>
void send_transient_transaction(const Params& params, next_function<Results> next, chain::transaction_metadata::trx_type trx_type) const;
void send_transient_transaction(const Params& params, eosio::chain::next_function<Results> next, chain::transaction_metadata::trx_type trx_type) const;
};

class read_write {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@
#include <eosio/chain/types.hpp>
#include <eosio/chain/block_state.hpp>
#include <eosio/chain/trace.hpp>
#include <eosio/chain/transaction_metadata.hpp>
greg7mdp marked this conversation as resolved.
Show resolved Hide resolved

namespace eosio::chain_apis {

template<typename T>
using next_function = std::function<void(const std::variant<fc::exception_ptr, T>&)>;

/**
* 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.
Expand Down Expand Up @@ -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<uint16_t> num_blocks, next_function<std::unique_ptr<fc::variant>> next );
void track_transaction( chain::packed_transaction_ptr ptrx, std::optional<uint16_t> num_blocks, eosio::chain::next_function<std::unique_ptr<fc::variant>> next );

/**
* Attach to chain applied_transaction signal
Expand Down
Loading