Skip to content

Commit

Permalink
GH-1062 Remove deadline since we no longer want to interrupt json cre…
Browse files Browse the repository at this point in the history
…ation on the http thread
  • Loading branch information
heifner committed May 5, 2023
1 parent 0e8739e commit cb1b52d
Show file tree
Hide file tree
Showing 12 changed files with 41 additions and 58 deletions.
10 changes: 5 additions & 5 deletions plugins/chain_api_plugin/chain_api_plugin.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <eosio/chain_api_plugin/chain_api_plugin.hpp>
#include <eosio/chain/exceptions.hpp>
#include <eosio/http_plugin/macros.hpp>
#include <fc/time.hpp>
#include <fc/io/json.hpp>

namespace eosio {
Expand All @@ -11,15 +12,15 @@ using namespace eosio;

class chain_api_plugin_impl {
public:
chain_api_plugin_impl(controller& db)
explicit chain_api_plugin_impl(controller& db)
: db(db) {}

controller& db;
};


chain_api_plugin::chain_api_plugin(){}
chain_api_plugin::~chain_api_plugin(){}
chain_api_plugin::chain_api_plugin() = default;
chain_api_plugin::~chain_api_plugin() = default;

void chain_api_plugin::set_program_options(options_description&, options_description&) {}
void chain_api_plugin::plugin_initialize(const variables_map&) {}
Expand Down Expand Up @@ -47,9 +48,8 @@ parse_params<chain_apis::read_only::get_transaction_status_params, http_params_t
auto deadline = api_handle.start(); \
try { \
auto params = parse_params<api_namespace::call_name ## _params, params_type>(body);\
FC_CHECK_DEADLINE(deadline);\
fc::variant result( api_handle.call_name( std::move(params), deadline ) ); \
cb(http_response_code, deadline, std::move(result)); \
cb(http_response_code, std::move(result)); \
} catch (...) { \
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
} \
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::time_point::maximum(), fc::variant(result)); \
cb(http_response_code, fc::variant(result)); \
} catch (...) { \
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
} \
Expand Down
27 changes: 11 additions & 16 deletions plugins/http_plugin/include/eosio/http_plugin/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,11 @@

#include <eosio/chain/thread_utils.hpp>// for thread pool
#include <eosio/http_plugin/http_plugin.hpp>
#include <fc/utility.hpp>

#include <atomic>
#include <map>
#include <optional>
#include <regex>
#include <set>
#include <string>

#include <fc/io/raw.hpp>
#include <fc/log/logger_config.hpp>
#include <fc/time.hpp>
#include <fc/utility.hpp>

#include <boost/asio.hpp>
#include <boost/asio/bind_executor.hpp>
Expand All @@ -33,6 +26,13 @@
#include <boost/asio/basic_stream_socket.hpp>
#include <boost/asio/detail/config.hpp>

#include <atomic>
#include <map>
#include <optional>
#include <regex>
#include <set>
#include <string>

namespace eosio {
static uint16_t const uri_default_port = 80;
/// Default port for wss://
Expand Down Expand Up @@ -153,27 +153,22 @@ struct http_plugin_state {
*/
auto make_http_response_handler(std::shared_ptr<http_plugin_state> plugin_state, detail::abstract_conn_ptr session_ptr, http_content_type content_type) {
return [plugin_state{std::move(plugin_state)},
session_ptr{std::move(session_ptr)}, content_type](int code, fc::time_point deadline, std::optional<fc::variant> response) {
session_ptr{std::move(session_ptr)}, content_type](int code, std::optional<fc::variant> response) {
auto payload_size = detail::in_flight_sizeof(response);
if(auto error_str = session_ptr->verify_max_bytes_in_flight(payload_size); !error_str.empty()) {
session_ptr->send_busy_response(std::move(error_str));
return;
}

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;
}

plugin_state->bytes_in_flight += payload_size;

// 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, deadline, start, payload_size, response = std::move(response), content_type]() {
[plugin_state, session_ptr, code, payload_size, response = std::move(response), content_type]() {
try {
plugin_state->bytes_in_flight -= payload_size;
if (response.has_value()) {
std::string json = (content_type == http_content_type::plaintext) ? response->as_string() : fc::json::to_string(*response, deadline + (fc::time_point::now() - start));
std::string json = (content_type == http_content_type::plaintext) ? response->as_string() : fc::json::to_string(*response, fc::time_point::maximum());
if (auto error_str = session_ptr->verify_max_bytes_in_flight(json.size()); error_str.empty())
session_ptr->send_response(std::move(json), code);
else
Expand Down
24 changes: 6 additions & 18 deletions plugins/http_plugin/include/eosio/http_plugin/macros.hpp
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
#pragma once

struct async_result_visitor : public fc::visitor<fc::variant> {
template<typename T>
fc::variant operator()(const T& v) const {
return fc::variant(v);
}
};

#define CALL_ASYNC_WITH_400(api_name, api_handle, api_namespace, call_name, call_result, http_resp_code, params_type) \
{ std::string("/v1/" #api_name "/" #call_name), \
[api_handle, &_http_plugin](string&&, string&& body, url_response_callback&& cb) mutable { \
auto deadline = api_handle.start(); \
api_handle.start(); \
try { \
auto params = parse_params<api_namespace::call_name ## _params, params_type>(body); \
FC_CHECK_DEADLINE(deadline); \
using http_fwd_t = std::function<chain::t_or_exception<call_result>()>; \
api_handle.call_name( std::move(params), \
api_handle.call_name( std::move(params), /* called on main application thread */ \
[&_http_plugin, cb=std::move(cb), body=std::move(body)] \
(const chain::next_function_variant<call_result>& result) mutable { \
if (std::holds_alternative<fc::exception_ptr>(result)) { \
Expand All @@ -25,8 +17,7 @@ struct async_result_visitor : public fc::visitor<fc::variant> {
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
} \
} else if (std::holds_alternative<call_result>(result)) { \
cb(http_resp_code, fc::time_point::maximum(), \
fc::variant(std::get<call_result>(std::move(result)))); \
cb(http_resp_code, fc::variant(std::get<call_result>(std::move(result)))); \
} else { \
/* api returned a function to be processed on the http_plugin thread pool */ \
assert(std::holds_alternative<http_fwd_t>(result)); \
Expand All @@ -41,8 +32,7 @@ struct async_result_visitor : public fc::visitor<fc::variant> {
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
} \
} else { \
cb(resp_code, fc::time_point::maximum(), \
fc::variant(std::get<call_result>(std::move(result)))) ; \
cb(resp_code, fc::variant(std::get<call_result>(std::move(result)))); \
} \
}); \
} \
Expand All @@ -63,10 +53,9 @@ struct async_result_visitor : public fc::visitor<fc::variant> {
auto deadline = api_handle.start(); \
try { \
auto params = parse_params<api_namespace::call_name ## _params, params_type>(body); \
FC_CHECK_DEADLINE(deadline); \
using http_fwd_t = std::function<chain::t_or_exception<call_result>()>; \
/* called on main application thread */ \
http_fwd_t http_fwd(api_handle.call_name(std::move(params), deadline)); \
FC_CHECK_DEADLINE(deadline); \
_http_plugin.post_http_thread_pool([resp_code=http_resp_code, cb=std::move(cb), \
body=std::move(body), \
http_fwd = std::move(http_fwd)]() { \
Expand All @@ -78,8 +67,7 @@ struct async_result_visitor : public fc::visitor<fc::variant> {
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
} \
} else { \
cb(resp_code, fc::time_point::maximum(), \
fc::variant(std::get<call_result>(std::move(result)))) ; \
cb(resp_code, fc::variant(std::get<call_result>(std::move(result)))); \
} \
}); \
} catch (...) { \
Expand Down
6 changes: 3 additions & 3 deletions plugins/http_plugin/tests/unit_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,18 @@ class Db
p.add_api({
{ std::string("/hello"),
[&](string&&, string&& body, url_response_callback&& cb) {
cb(200, fc::time_point::maximum(), fc::variant("world!"));
cb(200, fc::variant("world!"));
}
},
{ std::string("/echo"),
[&](string&&, string&& body, url_response_callback&& cb) {
cb(200, fc::time_point::maximum(), fc::variant(body));
cb(200, fc::variant(body));
}
},
{ std::string("/check_ones"), // returns "yes" if body only has only '1' chars, "no" otherwise
[&](string&&, string&& body, url_response_callback&& cb) {
bool ok = std::all_of(body.begin(), body.end(), [](char c) { return c == '1'; });
cb(200, fc::time_point::maximum(), fc::variant(ok ? string("yes") : string("no")));
cb(200, fc::variant(ok ? string("yes") : string("no")));
}
},
}, appbase::exec_queue::read_write);
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::time_point::maximum(), fc::variant(result)); \
cb(http_response_code, 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 @@ -25,7 +25,7 @@ using namespace eosio;
[&](string&&, string&& body, url_response_callback&& cb) mutable { \
try { \
INVOKE \
cb(http_response_code, fc::time_point::maximum(), fc::variant(result)); \
cb(http_response_code, fc::variant(result)); \
} catch (...) { \
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
} \
Expand All @@ -43,7 +43,7 @@ using namespace eosio;
http_plugin::handle_exception(#api_name, #call_name, body, cb);\
}\
} else if (std::holds_alternative<call_result>(result)) { \
cb(http_response_code, fc::time_point::maximum(), fc::variant(std::get<call_result>(result)));\
cb(http_response_code, fc::variant(std::get<call_result>(result)));\
} else { \
assert(0); \
} \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void test_control_api_plugin::plugin_initialize(const variables_map&) {}
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, fc::time_point::maximum(), std::move(result)); \
cb(http_response_code, std::move(result)); \
} catch (...) { \
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
} \
Expand Down
14 changes: 7 additions & 7 deletions plugins/trace_api_plugin/trace_api_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ 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::time_point::maximum(), fc::variant( results ));
cb( 400, fc::variant( results ));
return;
}

Expand All @@ -272,9 +272,9 @@ struct trace_api_rpc_plugin_impl : public std::enable_shared_from_this<trace_api
auto resp = that->req_handler->get_block_trace(*block_number);
if (resp.is_null()) {
error_results results{404, "Trace API: block trace missing"};
cb( 404, fc::time_point::maximum(), fc::variant( results ));
cb( 404, fc::variant( results ));
} else {
cb( 200, fc::time_point::maximum(), std::move(resp) );
cb( 200, std::move(resp) );
}
} catch (...) {
http_plugin::handle_exception("trace_api", "get_block", body, cb);
Expand Down Expand Up @@ -308,7 +308,7 @@ 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::time_point::maximum(), fc::variant( results ));
cb( 400, fc::variant( results ));
return;
}

Expand All @@ -317,14 +317,14 @@ struct trace_api_rpc_plugin_impl : public std::enable_shared_from_this<trace_api
get_block_n blk_num = common->store->get_trx_block_number(*trx_id, common->minimum_irreversible_history_blocks);
if (!blk_num.has_value()){
error_results results{404, "Trace API: transaction id missing in the transaction id log files"};
cb( 404, fc::time_point::maximum(), fc::variant( results ));
cb( 404, fc::variant( results ));
} else {
auto resp = that->req_handler->get_transaction_trace(*trx_id, *blk_num);
if (resp.is_null()) {
error_results results{404, "Trace API: transaction trace missing"};
cb( 404, fc::time_point::maximum(), fc::variant( results ));
cb( 404, fc::variant( results ));
} else {
cb( 200, fc::time_point::maximum(), std::move(resp) );
cb( 200, std::move(resp) );
}
}
} catch (...) {
Expand Down
2 changes: 1 addition & 1 deletion plugins/wallet_api_plugin/wallet_api_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ using namespace eosio;
[&api_handle](string&&, string&& body, url_response_callback&& cb) mutable { \
try { \
INVOKE \
cb(http_response_code, fc::time_point::now() + fc::days(365), fc::variant(result)); \
cb(http_response_code, fc::variant(result)); \
} catch (...) { \
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
} \
Expand Down
2 changes: 1 addition & 1 deletion programs/keosd/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ int main(int argc, char** argv)
auto& http = app->get_plugin<http_plugin>();
http.add_handler("/v1/" + keosd::config::key_store_executable_name + "/stop",
[&a=app](string, string, url_response_callback cb) {
cb(200, fc::time_point::maximum(), fc::variant(fc::variant_object()));
cb(200, fc::variant(fc::variant_object()));
a->quit();
}, appbase::exec_queue::read_write );
app->startup();
Expand Down
4 changes: 2 additions & 2 deletions tests/chain_plugin_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ BOOST_FIXTURE_TEST_CASE( get_block_with_invalid_abi, validating_tester ) try {
// block should be decoded successfully
auto block = plugin.get_raw_block(param, fc::time_point::maximum());
auto abi_cache = plugin.get_block_serializers(block, fc::microseconds::maximum());
std::string block_str = json::to_pretty_string(plugin.convert_block(block, abi_cache, fc::microseconds::maximum()));
std::string block_str = json::to_pretty_string(plugin.convert_block(block, abi_cache));
BOOST_TEST(block_str.find("procassert") != std::string::npos);
BOOST_TEST(block_str.find("condition") != std::string::npos);
BOOST_TEST(block_str.find("Should Not Assert!") != std::string::npos);
Expand All @@ -114,7 +114,7 @@ BOOST_FIXTURE_TEST_CASE( get_block_with_invalid_abi, validating_tester ) try {
// get the same block as string, results in decode failed(invalid abi) but not exception
auto block2 = plugin.get_raw_block(param, fc::time_point::maximum());
auto abi_cache2 = plugin.get_block_serializers(block2, fc::microseconds::maximum());
std::string block_str2 = json::to_pretty_string(plugin.convert_block(block2, abi_cache2, fc::microseconds::maximum()));
std::string block_str2 = json::to_pretty_string(plugin.convert_block(block2, abi_cache2));
BOOST_TEST(block_str2.find("procassert") != std::string::npos);
BOOST_TEST(block_str2.find("condition") == std::string::npos); // decode failed
BOOST_TEST(block_str2.find("Should Not Assert!") == std::string::npos); // decode failed
Expand Down

0 comments on commit cb1b52d

Please sign in to comment.