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

[3.2] Remove hardcoded 10ms limit for chain_api_plugin calls #96

Merged
merged 5 commits into from
Sep 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions plugins/chain_api_plugin/chain_api_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,12 @@ parse_params<chain_apis::read_only::get_transaction_status_params, http_params_t
#define CALL_WITH_400(api_name, api_handle, api_namespace, call_name, http_response_code, params_type) \
{std::string("/v1/" #api_name "/" #call_name), \
[api_handle](string, string body, url_response_callback cb) mutable { \
api_handle.validate(); \
auto deadline = api_handle.start(); \
try { \
auto params = parse_params<api_namespace::call_name ## _params, params_type>(body);\
fc::variant result( api_handle.call_name( std::move(params) ) ); \
cb(http_response_code, std::move(result)); \
FC_CHECK_DEADLINE(deadline);\
fc::variant result( api_handle.call_name( std::move(params), deadline ) ); \
cb(http_response_code, deadline, std::move(result)); \
} catch (...) { \
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
} \
Expand All @@ -64,10 +65,11 @@ parse_params<chain_apis::read_only::get_transaction_status_params, http_params_t
#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 { \
api_handle.validate(); \
auto deadline = api_handle.start(); \
try { \
auto params = parse_params<api_namespace::call_name ## _params, params_type>(body);\
api_handle.call_name( std::move(params),\
FC_CHECK_DEADLINE(deadline);\
api_handle.call_name( std::move(params), \
[cb, body](const std::variant<fc::exception_ptr, call_result>& result){\
if (std::holds_alternative<fc::exception_ptr>(result)) {\
try {\
Expand All @@ -76,7 +78,7 @@ parse_params<chain_apis::read_only::get_transaction_status_params, http_params_t
http_plugin::handle_exception(#api_name, #call_name, body, cb);\
}\
} else {\
cb(http_response_code, std::visit(async_result_visitor(), result));\
cb(http_response_code, fc::time_point::maximum(), std::visit(async_result_visitor(), result));\
}\
});\
} catch (...) { \
Expand All @@ -96,8 +98,11 @@ void chain_api_plugin::plugin_startup() {
ilog( "starting chain_api_plugin" );
my.reset(new chain_api_plugin_impl(app().get_plugin<chain_plugin>().chain()));
auto& chain = app().get_plugin<chain_plugin>();
auto ro_api = chain.get_read_only_api();
auto rw_api = chain.get_read_write_api();
auto& http = app().get_plugin<http_plugin>();
fc::microseconds max_response_time = http.get_max_response_time();

auto ro_api = chain.get_read_only_api(max_response_time);
auto rw_api = chain.get_read_write_api(max_response_time);

auto& _http_plugin = app().get_plugin<http_plugin>();
ro_api.set_shorten_abi_errors( !_http_plugin.verbose_errors() );
Expand Down
132 changes: 78 additions & 54 deletions plugins/chain_plugin/chain_plugin.cpp

Large diffs are not rendered by default.

127 changes: 85 additions & 42 deletions plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions plugins/chain_plugin/test/test_chain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,8 @@ class chain_plugin_tester : public TESTER {
read_only::get_account_results get_account_info(const account_name acct){
auto account_object = control->get_account(acct);
read_only::get_account_params params = { account_object.name };
chain_apis::read_only plugin(*(control.get()), {}, fc::microseconds::maximum(), {}, {});
return plugin.get_account(params);
chain_apis::read_only plugin(*(control.get()), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {});
return plugin.get_account(params, fc::time_point::maximum());
}

transaction_trace_ptr setup_producer_accounts( const std::vector<account_name>& accounts ) {
Expand Down
2 changes: 1 addition & 1 deletion plugins/db_size_api_plugin/db_size_api_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ using namespace eosio;
try { \
body = parse_params<std::string, http_params_types::no_params>(body); \
INVOKE \
cb(http_response_code, fc::variant(result)); \
cb(http_response_code, fc::time_point::maximum(), fc::variant(result)); \
} catch (...) { \
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
} \
Expand Down
35 changes: 20 additions & 15 deletions plugins/http_plugin/http_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
return;
}

url_response_callback wrapped_then = [tracked_b, then=std::move(then)](int code, std::optional<fc::variant> resp) {
then(code, std::move(resp));
url_response_callback wrapped_then = [tracked_b, then=std::move(then)](int code, const fc::time_point& deadline, std::optional<fc::variant> resp) {
then(code, deadline, std::move(resp));
};

// post to the app thread taking shared ownership of next (via std::shared_ptr),
Expand Down Expand Up @@ -253,8 +253,8 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
"Maximum size in megabytes http_plugin should use for processing http requests. -1 for unlimited. 429 error response when exceeded." )
("http-max-in-flight-requests", bpo::value<int32_t>()->default_value(-1),
"Maximum number of requests http_plugin should use for processing http requests. 429 error response when exceeded." )
("http-max-response-time-ms", bpo::value<uint32_t>()->default_value(30),
"Maximum time for processing a request.")
("http-max-response-time-ms", bpo::value<int64_t>()->default_value(30),
"Maximum time for processing a request, -1 for unlimited")
("verbose-http-errors", bpo::bool_switch()->default_value(false),
"Append the error log to HTTP responses")
("http-validate-host", boost::program_options::value<bool>()->default_value(true),
Expand Down Expand Up @@ -286,8 +286,13 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
my->plugin_state->max_bytes_in_flight = max_bytes_mb * 1024 * 1024;
}
my->plugin_state->max_requests_in_flight = options.at( "http-max-in-flight-requests" ).as<int32_t>();
my->plugin_state->max_response_time = fc::microseconds( options.at("http-max-response-time-ms").as<uint32_t>() * 1000 );

int64_t max_reponse_time_ms = options.at("http-max-response-time-ms").as<int64_t>();
EOS_ASSERT( max_reponse_time_ms == -1 || max_reponse_time_ms >= 0, chain::plugin_config_exception,
"http-max-response-time-ms must be -1, or non-negative: ${m}", ("m", max_reponse_time_ms) );
// set to one year for -1, unlimited, since this is added to fc::time_point::now() for a deadline
my->plugin_state->max_response_time = max_reponse_time_ms == -1 ?
fc::days(365) : fc::microseconds( max_reponse_time_ms * 1000 );

my->plugin_state->validate_host = options.at("http-validate-host").as<bool>();
if( options.count( "http-alias" )) {
const auto& aliases = options["http-alias"].as<vector<string>>();
Expand Down Expand Up @@ -430,7 +435,7 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
try {
if (body.empty()) body = "{}";
auto result = (*this).get_supported_apis();
cb(200, fc::variant(result));
cb(200, fc::time_point::maximum(), fc::variant(result));
} catch (...) {
handle_exception("node", "get_supported_apis", body, cb);
}
Expand Down Expand Up @@ -487,36 +492,36 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
throw;
} catch (chain::unknown_block_exception& e) {
error_results results{400, "Unknown Block", error_results::error_info(e, verbose_http_errors)};
cb( 400, fc::variant( results ));
cb( 400, fc::time_point::maximum(), fc::variant( results ));
} catch (chain::invalid_http_request& e) {
error_results results{400, "Invalid Request", error_results::error_info(e, verbose_http_errors)};
cb( 400, fc::variant( results ));
cb( 400, fc::time_point::maximum(), fc::variant( results ));
} catch (chain::unsatisfied_authorization& e) {
error_results results{401, "UnAuthorized", error_results::error_info(e, verbose_http_errors)};
cb( 401, fc::variant( results ));
cb( 401, fc::time_point::maximum(), fc::variant( results ));
} catch (chain::tx_duplicate& e) {
error_results results{409, "Conflict", error_results::error_info(e, verbose_http_errors)};
cb( 409, fc::variant( results ));
cb( 409, fc::time_point::maximum(), fc::variant( results ));
} catch (fc::eof_exception& e) {
error_results results{422, "Unprocessable Entity", error_results::error_info(e, verbose_http_errors)};
cb( 422, fc::variant( results ));
cb( 422, fc::time_point::maximum(), fc::variant( results ));
fc_elog( logger(), "Unable to parse arguments to ${api}.${call}", ("api", api_name)( "call", call_name ) );
fc_dlog( logger(), "Bad arguments: ${args}", ("args", body) );
} catch (fc::exception& e) {
error_results results{500, "Internal Service Error", error_results::error_info(e, verbose_http_errors)};
cb( 500, fc::variant( results ));
cb( 500, fc::time_point::maximum(), fc::variant( results ));
fc_dlog( logger(), "Exception while processing ${api}.${call}: ${e}",
("api", api_name)( "call", call_name )("e", e.to_detail_string()) );
} catch (std::exception& e) {
error_results results{500, "Internal Service Error", error_results::error_info(fc::exception( FC_LOG_MESSAGE( error, e.what())), verbose_http_errors)};
cb( 500, fc::variant( results ));
cb( 500, fc::time_point::maximum(), fc::variant( results ));
fc_elog( logger(), "STD Exception encountered while processing ${api}.${call}",
("api", api_name)( "call", call_name ) );
fc_dlog( logger(), "Exception Details: ${e}", ("e", e.what()) );
} catch (...) {
error_results results{500, "Internal Service Error",
error_results::error_info(fc::exception( FC_LOG_MESSAGE( error, "Unknown Exception" )), verbose_http_errors)};
cb( 500, fc::variant( results ));
cb( 500, fc::time_point::maximum(), fc::variant( results ));
fc_elog( logger(), "Unknown Exception encountered while processing ${api}.${call}",
("api", api_name)( "call", call_name ) );
}
Expand Down
14 changes: 10 additions & 4 deletions plugins/http_plugin/include/eosio/http_plugin/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,18 +212,24 @@ auto make_in_flight(T&& object, std::shared_ptr<http_plugin_state> plugin_state)
*/
auto make_http_response_handler(std::shared_ptr<http_plugin_state> plugin_state, detail::abstract_conn_ptr session_ptr) {
return [plugin_state{std::move(plugin_state)},
session_ptr{std::move(session_ptr)}](int code, std::optional<fc::variant> response) {
session_ptr{std::move(session_ptr)}](int code, fc::time_point deadline, std::optional<fc::variant> response) {
auto tracked_response = make_in_flight(std::move(response), plugin_state);
if(!session_ptr->verify_max_bytes_in_flight()) {
return;
}

// post back to an HTTP thread to to allow the response handler to be called from any thread
auto start = fc::time_point::now();
if( deadline == fc::time_point::maximum() ) { // no caller supplied deadline so use http configured deadline
deadline = start + plugin_state->max_response_time;
}

// post back to an HTTP thread to allow the response handler to be called from any thread
boost::asio::post(plugin_state->thread_pool->get_executor(),
[plugin_state, session_ptr, code, tracked_response = std::move(tracked_response)]() {
[plugin_state, session_ptr, code, deadline, start,
tracked_response = std::move(tracked_response)]() {
try {
if(tracked_response->obj().has_value()) {
std::string json = fc::json::to_string(*tracked_response->obj(), fc::time_point::now() + plugin_state->max_response_time);
std::string json = fc::json::to_string(*tracked_response->obj(), deadline + (fc::time_point::now() - start));
auto tracked_json = make_in_flight(std::move(json), plugin_state);
session_ptr->send_response(std::move(tracked_json->obj()), code);
} else {
Expand Down
4 changes: 2 additions & 2 deletions plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ namespace eosio {
* @brief A callback function provided to a URL handler to
* allow it to specify the HTTP response code and body
*
* Arguments: response_code, response_body
* Arguments: response_code, deadline, response_body
*/
using url_response_callback = std::function<void(int,std::optional<fc::variant>)>;
using url_response_callback = std::function<void(int,fc::time_point,std::optional<fc::variant>)>;

/**
* @brief Callback type for a URL handler
Expand Down
2 changes: 1 addition & 1 deletion plugins/login_plugin/login_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ void login_plugin::plugin_initialize(const variables_map& options) {
if (body.empty()) \
body = "{}"; \
fc::variant result( call_name(fc::json::from_string(body).as<login_plugin::call_name##_params>()) ); \
cb(http_response_code, std::move(result)); \
cb(http_response_code, fc::time_point::maximum(), std::move(result)); \
} catch (...) { \
http_plugin::handle_exception("login", #call_name, body, cb); \
} \
Expand Down
2 changes: 1 addition & 1 deletion plugins/net_api_plugin/net_api_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ using namespace eosio;
[&api_handle](string, string body, url_response_callback cb) mutable { \
try { \
INVOKE \
cb(http_response_code, fc::variant(result)); \
cb(http_response_code, fc::time_point::maximum(), fc::variant(result)); \
} catch (...) { \
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
} \
Expand Down
4 changes: 2 additions & 2 deletions plugins/producer_api_plugin/producer_api_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ struct async_result_visitor : public fc::visitor<fc::variant> {
[&api_handle](string, string body, url_response_callback cb) mutable { \
try { \
INVOKE \
cb(http_response_code, fc::variant(result)); \
cb(http_response_code, fc::time_point::maximum(), fc::variant(result)); \
} catch (...) { \
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
} \
Expand All @@ -50,7 +50,7 @@ struct async_result_visitor : public fc::visitor<fc::variant> {
http_plugin::handle_exception(#api_name, #call_name, body, cb);\
}\
} else {\
cb(http_response_code, std::visit(async_result_visitor(), result));\
cb(http_response_code, fc::time_point::maximum(), std::visit(async_result_visitor(), result));\
}\
};\
INVOKE\
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ struct async_result_visitor : public fc::visitor<std::string> {
try { \
auto params = parse_params<api_namespace::call_name ## _params, params_type>(body);\
fc::variant result( api_handle.call_name( std::move(params) ) ); \
cb(http_response_code, std::move(result)); \
cb(http_response_code, fc::time_point::maximum(), std::move(result)); \
} catch (...) { \
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
} \
Expand Down
20 changes: 11 additions & 9 deletions plugins/trace_api_plugin/trace_api_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ struct trace_api_rpc_plugin_impl : public std::enable_shared_from_this<trace_api
return;
}

const auto deadline = that->calc_deadline( max_response_time );

auto block_number = ([&body]() -> std::optional<uint32_t> {
if (body.empty()) {
return {};
Expand All @@ -274,19 +276,18 @@ struct trace_api_rpc_plugin_impl : public std::enable_shared_from_this<trace_api

if (!block_number) {
error_results results{400, "Bad or missing block_num"};
cb( 400, fc::variant( results ));
cb( 400, deadline, fc::variant( results ));
return;
}

try {

const auto deadline = that->calc_deadline( max_response_time );
auto resp = that->req_handler->get_block_trace(*block_number, [deadline]() { FC_CHECK_DEADLINE(deadline); });
if (resp.is_null()) {
error_results results{404, "Trace API: block trace missing"};
cb( 404, fc::variant( results ));
cb( 404, deadline, fc::variant( results ));
} else {
cb( 200, std::move(resp) );
cb( 200, deadline, std::move(resp) );
}
} catch (...) {
http_plugin::handle_exception("trace_api", "get_block", body, cb);
Expand All @@ -302,6 +303,8 @@ struct trace_api_rpc_plugin_impl : public std::enable_shared_from_this<trace_api
return;
}

const auto deadline = that->calc_deadline( max_response_time );

auto trx_id = ([&body]() -> std::optional<transaction_id_type> {
if (body.empty()) {
return {};
Expand All @@ -320,24 +323,23 @@ struct trace_api_rpc_plugin_impl : public std::enable_shared_from_this<trace_api

if (!trx_id) {
error_results results{400, "Bad or missing transaction ID"};
cb( 400, fc::variant( results ));
cb( 400, deadline, fc::variant( results ));
return;
}

try {
const auto deadline = that->calc_deadline( max_response_time );
// search for the block that contains the transaction
get_block_n blk_num = common->store->get_trx_block_number(*trx_id, common->minimum_irreversible_history_blocks, [deadline]() { FC_CHECK_DEADLINE(deadline); });
if (!blk_num.has_value()){
error_results results{404, "Trace API: transaction id missing in the transaction id log files"};
cb( 404, fc::variant( results ));
cb( 404, deadline, fc::variant( results ));
} else {
auto resp = that->req_handler->get_transaction_trace(*trx_id, *blk_num, [deadline]() { FC_CHECK_DEADLINE(deadline); });
if (resp.is_null()) {
error_results results{404, "Trace API: transaction trace missing"};
cb( 404, fc::variant( results ));
cb( 404, deadline, fc::variant( results ));
} else {
cb( 200, std::move(resp) );
cb( 200, deadline, std::move(resp) );
}
}
} catch (...) {
Expand Down
Loading