From 269daef498608174d0576f640f7efa1ffc300e3a Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Tue, 26 Mar 2024 18:45:50 +0800 Subject: [PATCH 01/19] [coro_rpc] simply response mode --- include/ylt/coro_rpc/impl/context.hpp | 32 ++--- include/ylt/coro_rpc/impl/coro_connection.hpp | 114 ++++++++---------- src/coro_rpc/tests/rpc_api.cpp | 1 - 3 files changed, 61 insertions(+), 86 deletions(-) diff --git a/include/ylt/coro_rpc/impl/context.hpp b/include/ylt/coro_rpc/impl/context.hpp index 37a688fb8..85988e085 100644 --- a/include/ylt/coro_rpc/impl/context.hpp +++ b/include/ylt/coro_rpc/impl/context.hpp @@ -43,8 +43,8 @@ class context_base { typename rpc_protocol::req_header &get_req_head() { return self_->req_head_; } bool check_status() { - auto old_flag = self_->has_response_.exchange(true); - if (old_flag != false) + auto old_flag = self_->status_.exchange(context_status::start_response); + if (old_flag != context_status::init) AS_UNLIKELY { ELOGV(ERROR, "response message more than one time"); return false; @@ -67,8 +67,7 @@ class context_base { context_base(std::shared_ptr> context_info) : self_(std::move(context_info)) { if (self_->conn_) { - self_->conn_->set_rpc_call_type( - coro_connection::rpc_call_type::callback_started); + self_->conn_->set_rpc_return_by_callback(); } }; context_base() = default; @@ -79,8 +78,8 @@ class context_base { std::string_view error_msg) { if (!check_status()) AS_UNLIKELY { return; }; - self_->conn_->template response_error( - error_code, error_msg, self_->req_head_, self_->is_delay_); + self_->conn_->template response_error(error_code, error_msg, + self_->req_head_); } void response_error(coro_rpc::err_code error_code) { response_error(error_code, error_code.message()); @@ -98,16 +97,15 @@ class context_base { */ template void response_msg(Args &&...args) { + if (!check_status()) + AS_UNLIKELY { return; }; if constexpr (std::is_same_v) { static_assert(sizeof...(args) == 0, "illegal args"); - if (!check_status()) - AS_UNLIKELY { return; }; std::visit( [&](const serialize_proto &) { self_->conn_->template response_msg( serialize_proto::serialize(), - std::move(self_->resp_attachment_), self_->req_head_, - self_->is_delay_); + std::move(self_->resp_attachment_), self_->req_head_); }, *rpc_protocol::get_serialize_protocol(self_->req_head_)); } @@ -115,22 +113,19 @@ class context_base { static_assert( requires { return_msg_type{std::forward(args)...}; }, "constructed return_msg_type failed by illegal args"); - - if (!check_status()) - AS_UNLIKELY { return; }; - return_msg_type ret{std::forward(args)...}; std::visit( [&](const serialize_proto &) { self_->conn_->template response_msg( serialize_proto::serialize(ret), - std::move(self_->resp_attachment_), self_->req_head_, - self_->is_delay_); + std::move(self_->resp_attachment_), self_->req_head_); }, *rpc_protocol::get_serialize_protocol(self_->req_head_)); // response_handler_(std::move(conn_), std::move(ret)); } + /*finish here*/ + self_->status_ = context_status::start_response; } /*! @@ -187,11 +182,6 @@ class context_base { return std::move(self_->req_attachment_); } - void set_delay() { - self_->is_delay_ = true; - self_->conn_->set_rpc_call_type( - coro_connection::rpc_call_type::callback_with_delay); - } std::any &tag() { return self_->conn_->tag(); } const std::any &tag() const { return self_->conn_->tag(); } }; diff --git a/include/ylt/coro_rpc/impl/coro_connection.hpp b/include/ylt/coro_rpc/impl/coro_connection.hpp index 5aeb52532..6fc9eb26e 100644 --- a/include/ylt/coro_rpc/impl/coro_connection.hpp +++ b/include/ylt/coro_rpc/impl/coro_connection.hpp @@ -39,6 +39,7 @@ namespace coro_rpc { class coro_connection; using rpc_conn = std::shared_ptr; +enum class context_status : int { init, start_response, finish_response }; template struct context_info_t { std::shared_ptr conn_; @@ -48,10 +49,14 @@ struct context_info_t { std::function resp_attachment_ = [] { return std::string_view{}; }; - std::atomic has_response_ = false; - bool is_delay_ = false; + std::atomic status_ = context_status::init; context_info_t(std::shared_ptr &&conn) : conn_(std::move(conn)) {} + context_info_t(std::shared_ptr &&conn, + std::string &&req_body_buf, std::string &&req_attachment_buf) + : conn_(std::move(conn)), + req_body_(std::move(req_body_buf)), + req_attachment_(std::move(req_attachment_buf)) {} }; /*! * TODO: add doc @@ -70,12 +75,6 @@ struct context_info_t { class coro_connection : public std::enable_shared_from_this { public: - enum rpc_call_type { - non_callback, - callback_with_delay, - callback_finished, - callback_started - }; /*! * @@ -152,11 +151,9 @@ class coro_connection : public std::enable_shared_from_this { std::make_shared>(shared_from_this()); std::string resp_error_msg; while (true) { - auto &req_head = context_info->req_head_; - auto &body = context_info->req_body_; - auto &req_attachment = context_info->req_attachment_; reset_timer(); - auto ec = co_await rpc_protocol::read_head(socket, req_head); + typename rpc_protocol::req_header req_head_tmp; + auto ec = co_await rpc_protocol::read_head(socket, req_head_tmp); cancel_timer(); // `co_await async_read` uses asio::async_read underlying. // If eof occurred, the bytes_transferred of `co_await async_read` must @@ -169,7 +166,7 @@ class coro_connection : public std::enable_shared_from_this { } #ifdef UNIT_TEST_INJECT - client_id_ = req_head.seq_num; + client_id_ = req_head_tmp.seq_num; ELOGV(INFO, "conn_id %d, client_id %d", conn_id_, client_id_); #endif @@ -183,6 +180,27 @@ class coro_connection : public std::enable_shared_from_this { break; } #endif + + // try to reuse context + if (is_rpc_return_by_callback) { + // cant reuse context,make shared new one + is_rpc_return_by_callback = false; + if (context_info->status_ != context_status::finish_response) { + // cant reuse buffer + context_info = std::make_shared>( + shared_from_this()); + } + else { + // reuse string buffer + context_info = std::make_shared>( + shared_from_this(), std::move(context_info->req_body_), + std::move(context_info->req_attachment_)); + } + } + auto &req_head = context_info->req_head_; + auto &body = context_info->req_body_; + auto &req_attachment = context_info->req_attachment_; + req_head = std::move(req_head_tmp); auto serialize_proto = rpc_protocol::get_serialize_protocol(req_head); if (!serialize_proto.has_value()) @@ -215,36 +233,22 @@ class coro_connection : public std::enable_shared_from_this { auto coro_handler = router.get_coro_handler(key); pair = co_await router.route_coro(coro_handler, payload, context_info, serialize_proto.value(), key); + // TODO: if coroutine resume in another thread, it's thread-unsafe. we + // need post it back to the same io exeuctor. } else { pair = router.route(handler, payload, context_info, serialize_proto.value(), key); } - auto &[resp_err, resp_buf] = pair; - switch (rpc_call_type_) { - default: - unreachable(); - case rpc_call_type::non_callback: - break; - case rpc_call_type::callback_with_delay: + if (is_rpc_return_by_callback) { + if (!resp_err) { ++delay_resp_cnt; - rpc_call_type_ = rpc_call_type::non_callback; - continue; - case rpc_call_type::callback_finished: - continue; - case rpc_call_type::callback_started: - coro_io::callback_awaitor awaitor; - rpc_call_type_ = rpc_call_type::callback_finished; - co_await awaitor.await_resume([this](auto handler) { - this->callback_awaitor_handler_ = std::move(handler); - }); - context_info->has_response_ = false; - context_info->resp_attachment_ = []() -> std::string_view { - return {}; - }; - rpc_call_type_ = rpc_call_type::non_callback; continue; + } + else { + is_rpc_return_by_callback = false; + } } resp_error_msg.clear(); if (!!resp_err) @@ -297,20 +301,18 @@ class coro_connection : public std::enable_shared_from_this { template void response_msg(std::string &&body_buf, std::function &&resp_attachment, - const typename rpc_protocol::req_header &req_head, - bool is_delay) { + const typename rpc_protocol::req_header &req_head) { std::string header_buf = rpc_protocol::prepare_response( body_buf, req_head, resp_attachment().size()); response(std::move(header_buf), std::move(body_buf), - std::move(resp_attachment), shared_from_this(), is_delay) + std::move(resp_attachment), shared_from_this()) .via(executor_) .detach(); } template void response_error(coro_rpc::errc ec, std::string_view error_msg, - const typename rpc_protocol::req_header &req_head, - bool is_delay) { + const typename rpc_protocol::req_header &req_head) { std::function attach_ment = []() -> std::string_view { return {}; }; @@ -318,12 +320,12 @@ class coro_connection : public std::enable_shared_from_this { std::string header_buf = rpc_protocol::prepare_response( body_buf, req_head, 0, ec, error_msg, true); response(std::move(header_buf), std::move(body_buf), std::move(attach_ment), - shared_from_this(), is_delay) + shared_from_this()) .via(executor_) .detach(); } - void set_rpc_call_type(enum rpc_call_type r) { rpc_call_type_ = r; } + void set_rpc_return_by_callback() { is_rpc_return_by_callback = true; } /*! * Check the connection has closed or not @@ -364,8 +366,8 @@ class coro_connection : public std::enable_shared_from_this { private: async_simple::coro::Lazy response( std::string header_buf, std::string body_buf, - std::function resp_attachment, rpc_conn self, - bool is_delay) noexcept { + std::function resp_attachment, + rpc_conn self) noexcept { if (has_closed()) AS_UNLIKELY { ELOGV(DEBUG, "response_msg failed: connection has been closed"); @@ -379,25 +381,12 @@ class coro_connection : public std::enable_shared_from_this { #endif write_queue_.emplace_back(std::move(header_buf), std::move(body_buf), std::move(resp_attachment)); - if (is_delay) { - --delay_resp_cnt; - assert(delay_resp_cnt >= 0); - reset_timer(); - } + --delay_resp_cnt; + assert(delay_resp_cnt >= 0); + reset_timer(); if (write_queue_.size() == 1) { co_await send_data(); } - if (!is_delay) { - if (rpc_call_type_ == rpc_call_type::callback_finished) { - // the function start_impl is waiting for resume. - callback_awaitor_handler_.resume(); - } - else { - assert(rpc_call_type_ == rpc_call_type::callback_started); - // the function start_impl is not waiting for resume. - rpc_call_type_ = rpc_call_type::callback_finished; - } - } } async_simple::coro::Lazy send_data() { @@ -518,9 +507,6 @@ class coro_connection : public std::enable_shared_from_this { asio::error_code ec; timer_.cancel(ec); } - - coro_io::callback_awaitor::awaitor_handler callback_awaitor_handler_{ - nullptr}; async_simple::Executor *executor_; asio::ip::tcp::socket socket_; // FIXME: queue's performance can be imporved. @@ -528,7 +514,7 @@ class coro_connection : public std::enable_shared_from_this { std::tuple>> write_queue_; coro_rpc::errc resp_err_; - rpc_call_type rpc_call_type_{non_callback}; + bool is_rpc_return_by_callback{false}; // if don't get any message in keep_alive_timeout_duration_, the connection // will be closed when enable_check_timeout_ is true. diff --git a/src/coro_rpc/tests/rpc_api.cpp b/src/coro_rpc/tests/rpc_api.cpp index d5f09d36b..a980f3189 100644 --- a/src/coro_rpc/tests/rpc_api.cpp +++ b/src/coro_rpc/tests/rpc_api.cpp @@ -91,7 +91,6 @@ void coro_fun_with_delay_return_string_twice( } void fun_with_delay_return_void_cost_long_time(coro_rpc::context conn) { - conn.set_delay(); std::thread([conn = std::move(conn)]() mutable { std::this_thread::sleep_for(700ms); conn.response_msg(); From 15a26a07024ac935c77e79f1bb444a2e4aee1e57 Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Wed, 27 Mar 2024 15:53:10 +0800 Subject: [PATCH 02/19] use asio::dispatch instead of asio::post in executor --- include/ylt/coro_io/io_context_pool.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/ylt/coro_io/io_context_pool.hpp b/include/ylt/coro_io/io_context_pool.hpp index 81bce7d4a..8cef68df9 100644 --- a/include/ylt/coro_io/io_context_pool.hpp +++ b/include/ylt/coro_io/io_context_pool.hpp @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include #include @@ -51,10 +51,10 @@ class ExecutorWrapper : public async_simple::Executor { virtual bool schedule(Func func) override { if constexpr (requires(ExecutorImpl e) { e.post(std::move(func)); }) { - executor_.post(std::move(func)); + executor_.dispatch(std::move(func)); } else { - asio::post(executor_, std::move(func)); + asio::dispatch(executor_, std::move(func)); } return true; @@ -67,7 +67,7 @@ class ExecutorWrapper : public async_simple::Executor { executor.post(std::move(func)); } else { - asio::post(executor, std::move(func)); + asio::dispatch(executor, std::move(func)); } return true; } From 348ee96a09c70f4f945cfb947e7a9fd3a064d727 Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Wed, 27 Mar 2024 17:46:40 +0800 Subject: [PATCH 03/19] coroutine rpc funtion start with delay --- include/ylt/coro_rpc/impl/coro_connection.hpp | 139 ++++++++++-------- src/coro_rpc/tests/rpc_api.hpp | 21 --- src/coro_rpc/tests/test_coro_rpc_server.cpp | 21 +-- 3 files changed, 77 insertions(+), 104 deletions(-) diff --git a/include/ylt/coro_rpc/impl/coro_connection.hpp b/include/ylt/coro_rpc/impl/coro_connection.hpp index 6fc9eb26e..aedf81c50 100644 --- a/include/ylt/coro_rpc/impl/coro_connection.hpp +++ b/include/ylt/coro_rpc/impl/coro_connection.hpp @@ -75,7 +75,6 @@ struct context_info_t { class coro_connection : public std::enable_shared_from_this { public: - /*! * * @param io_context @@ -88,7 +87,6 @@ class coro_connection : public std::enable_shared_from_this { std::chrono::seconds(0)) : executor_(executor), socket_(std::move(socket)), - resp_err_(), timer_(executor->get_asio_executor()) { if (timeout_duration == std::chrono::seconds(0)) { return; @@ -149,12 +147,11 @@ class coro_connection : public std::enable_shared_from_this { typename rpc_protocol::router &router, Socket &socket) noexcept { auto context_info = std::make_shared>(shared_from_this()); - std::string resp_error_msg; + reset_timer(); while (true) { - reset_timer(); typename rpc_protocol::req_header req_head_tmp; + // timer will be reset after rpc call response auto ec = co_await rpc_protocol::read_head(socket, req_head_tmp); - cancel_timer(); // `co_await async_read` uses asio::async_read underlying. // If eof occurred, the bytes_transferred of `co_await async_read` must // less than RPC_HEAD_LEN. Incomplete data will be discarded. @@ -215,6 +212,7 @@ class coro_connection : public std::enable_shared_from_this { ec = co_await rpc_protocol::read_payload(socket, req_head, body, req_attachment); + cancel_timer(); payload = std::string_view{body}; if (ec) @@ -225,71 +223,68 @@ class coro_connection : public std::enable_shared_from_this { break; } - std::pair pair{}; - auto key = rpc_protocol::get_route_key(req_head); auto handler = router.get_handler(key); + ++delay_resp_cnt; if (!handler) { auto coro_handler = router.get_coro_handler(key); - pair = co_await router.route_coro(coro_handler, payload, context_info, - serialize_proto.value(), key); - // TODO: if coroutine resume in another thread, it's thread-unsafe. we - // need post it back to the same io exeuctor. + + set_rpc_return_by_callback(); + router + .route_coro(coro_handler, payload, context_info, + serialize_proto.value(), key) + .via(executor_) + .start([context_info](auto &&result) mutable { + asio::dispatch([context_info=std::move(context_info),result = std::move(result)]() mutable { + coro_rpc::errc resp_err; + std::string resp_buf; + if (result.hasError()) + AS_UNLIKELY { + resp_err = coro_rpc::errc::interrupted; + resp_buf = "unknonw error"; + } + else { + std::tie(resp_err, resp_buf) = result.value(); + } + context_info->conn_->template direct_response_msg( + resp_err, resp_buf, context_info->req_head_); + }); + }); } else { - pair = router.route(handler, payload, context_info, - serialize_proto.value(), key); - } - auto &[resp_err, resp_buf] = pair; - if (is_rpc_return_by_callback) { - if (!resp_err) { - ++delay_resp_cnt; - continue; - } - else { - is_rpc_return_by_callback = false; + auto [resp_err, resp_buf] = router.route(handler, payload, context_info, + serialize_proto.value(), key); + if (is_rpc_return_by_callback) { + if (!resp_err) { + continue; + } + else { + is_rpc_return_by_callback = false; + } } - } - resp_error_msg.clear(); - if (!!resp_err) - AS_UNLIKELY { std::swap(resp_buf, resp_error_msg); } - std::string header_buf = rpc_protocol::prepare_response( - resp_buf, req_head, 0, resp_err, resp_error_msg); - #ifdef UNIT_TEST_INJECT - if (g_action == inject_action::close_socket_after_send_length) { - ELOGV(WARN, - "inject action: close_socket_after_send_length conn_id %d, " - "client_id %d", - conn_id_, client_id_); - co_await coro_io::async_write(socket, asio::buffer(header_buf)); - close(); - break; - } - if (g_action == inject_action::server_send_bad_rpc_result) { - ELOGV(WARN, + if (g_action == inject_action::close_socket_after_send_length) { + ELOGV(WARN, "inject action: close_socket_after_send_length", conn_id_, + client_id_); + std::string header_buf = rpc_protocol::prepare_response( + resp_buf, req_head, 0, resp_err, ""); + co_await coro_io::async_write(socket, asio::buffer(header_buf)); + close(); + break; + } + if (g_action == inject_action::server_send_bad_rpc_result) { + ELOGV( + WARN, "inject action: server_send_bad_rpc_result conn_id %d, client_id " "%d", conn_id_, client_id_); - resp_buf[0] = resp_buf[0] + 1; - } -#endif - if (!resp_err_) - AS_LIKELY { - if (!resp_err) - AS_UNLIKELY { resp_err_ = resp_err; } - write_queue_.emplace_back(std::move(header_buf), std::move(resp_buf), - [] { - return std::string_view{}; - }); - if (write_queue_.size() == 1) { - send_data().start([self = shared_from_this()](auto &&) { - }); - } - if (!!resp_err) - AS_UNLIKELY { break; } + resp_buf[0] = resp_buf[0] + 1; } +#endif + direct_response_msg(resp_err, resp_buf, req_head); + } } + cancel_timer(); } /*! * send `ret` to RPC client @@ -297,6 +292,27 @@ class coro_connection : public std::enable_shared_from_this { * @tparam R message type * @param ret object of message type */ + template + void direct_response_msg(coro_rpc::errc &resp_err, std::string &resp_buf, + const typename rpc_protocol::req_header &req_head) { + std::string resp_error_msg; + if (!!resp_err) { + resp_error_msg = std::move(resp_buf); + resp_buf = {}; + ELOGV(WARNING, "rpc route/execute error, error msg: %s", resp_error_msg.data()); + } + std::string header_buf = rpc_protocol::prepare_response( + resp_buf, req_head, 0, resp_err, resp_error_msg); + + response( + std::move(header_buf), std::move(resp_buf), + [] { + return std::string_view{}; + }, + nullptr) + .start([](auto &&) { + }); + } template void response_msg(std::string &&body_buf, @@ -385,6 +401,8 @@ class coro_connection : public std::enable_shared_from_this { assert(delay_resp_cnt >= 0); reset_timer(); if (write_queue_.size() == 1) { + if (self == nullptr) + self = shared_from_this(); co_await send_data(); } } @@ -445,12 +463,6 @@ class coro_connection : public std::enable_shared_from_this { } write_queue_.pop_front(); } - if (!!resp_err_) - AS_UNLIKELY { - ELOGV(ERROR, "%s, %s", make_error_message(resp_err_), "resp_err_"); - close(); - co_return; - } #ifdef UNIT_TEST_INJECT if (g_action == inject_action::close_socket_after_send_length) { ELOGV(INFO, @@ -513,7 +525,6 @@ class coro_connection : public std::enable_shared_from_this { std::deque< std::tuple>> write_queue_; - coro_rpc::errc resp_err_; bool is_rpc_return_by_callback{false}; // if don't get any message in keep_alive_timeout_duration_, the connection diff --git a/src/coro_rpc/tests/rpc_api.hpp b/src/coro_rpc/tests/rpc_api.hpp index 66fca1981..5f5bb4a3a 100644 --- a/src/coro_rpc/tests/rpc_api.hpp +++ b/src/coro_rpc/tests/rpc_api.hpp @@ -51,16 +51,6 @@ inline async_simple::coro::Lazy coro_func_return_void(int i) { co_return; } inline async_simple::coro::Lazy coro_func(int i) { co_return i; } -inline async_simple::coro::Lazy coro_func_delay_return_int( - coro_rpc::context conn, int i) { - conn.response_msg(i); - co_return; -} -inline async_simple::coro::Lazy coro_func_delay_return_void( - coro_rpc::context conn, int i) { - conn.response_msg(); - co_return; -} class HelloService { public: @@ -68,17 +58,6 @@ class HelloService { static std::string static_hello(); async_simple::coro::Lazy coro_func(int i) { co_return i; } async_simple::coro::Lazy coro_func_return_void(int i) { co_return; } - async_simple::coro::Lazy coro_func_delay_return_int( - coro_rpc::context conn, int i) { - conn.response_msg(i); - co_return; - } - async_simple::coro::Lazy coro_func_delay_return_void( - coro_rpc::context conn, int i) { - conn.response_msg(); - co_return; - } - private: }; namespace ns_login { diff --git a/src/coro_rpc/tests/test_coro_rpc_server.cpp b/src/coro_rpc/tests/test_coro_rpc_server.cpp index f40848aaf..3d9b52824 100644 --- a/src/coro_rpc/tests/test_coro_rpc_server.cpp +++ b/src/coro_rpc/tests/test_coro_rpc_server.cpp @@ -79,6 +79,7 @@ struct CoroServerTester : ServerTester { server.register_handler<&ns_login::LoginService::login>(&login_service_); server.register_handler<&HelloService::hello>(&hello_service_); server.register_handler(); + server.register_handler(); server.register_handler(); server.register_handler(); server.register_handler(); @@ -87,12 +88,8 @@ struct CoroServerTester : ServerTester { server.register_handler(); server.register_handler(); server.register_handler(); - server.register_handler(); - server.register_handler(); server.register_handler<&HelloService::coro_func, - &HelloService::coro_func_return_void, - &HelloService::coro_func_delay_return_void, - &HelloService::coro_func_delay_return_int>( + &HelloService::coro_func_return_void>( &hello_service_); server.register_handler(); server.register_handler<&CoroServerTester::get_value>(this); @@ -175,20 +172,6 @@ struct CoroServerTester : ServerTester { auto ret5 = this->template call<&HelloService::coro_func_return_void>(client, 42); CHECK(ret5.has_value()); - - auto ret6 = this->template call<&HelloService::coro_func_delay_return_void>( - client, 42); - CHECK(ret6.has_value()); - - auto ret7 = this->template call<&HelloService::coro_func_delay_return_int>( - client, 42); - CHECK(ret7.value() == 42); - - auto ret8 = this->template call(client, 42); - CHECK(ret8.has_value()); - - auto ret9 = this->template call(client, 42); - CHECK(ret9.value() == 42); } coro_rpc_server server; std::thread thd; From 6e27c3179d6f0e1735d560962d584aa1b03665dd Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Wed, 27 Mar 2024 18:02:01 +0800 Subject: [PATCH 04/19] [coro_rpc] disable context as lazy rpc function parameter. --- include/ylt/coro_rpc/impl/coro_connection.hpp | 2 +- include/ylt/coro_rpc/impl/router.hpp | 19 ++++------ include/ylt/coro_rpc/impl/rpc_execute.hpp | 38 ++----------------- src/coro_rpc/tests/test_router.cpp | 2 +- 4 files changed, 14 insertions(+), 47 deletions(-) diff --git a/include/ylt/coro_rpc/impl/coro_connection.hpp b/include/ylt/coro_rpc/impl/coro_connection.hpp index aedf81c50..01c81302d 100644 --- a/include/ylt/coro_rpc/impl/coro_connection.hpp +++ b/include/ylt/coro_rpc/impl/coro_connection.hpp @@ -231,7 +231,7 @@ class coro_connection : public std::enable_shared_from_this { set_rpc_return_by_callback(); router - .route_coro(coro_handler, payload, context_info, + .route_coro(coro_handler, payload, serialize_proto.value(), key) .via(executor_) .start([context_info](auto &&result) mutable { diff --git a/include/ylt/coro_rpc/impl/router.hpp b/include/ylt/coro_rpc/impl/router.hpp index c2439997c..ae5cda2d8 100644 --- a/include/ylt/coro_rpc/impl/router.hpp +++ b/include/ylt/coro_rpc/impl/router.hpp @@ -52,7 +52,7 @@ class router { using coro_router_handler_t = std::function>( - std::string_view, rpc_context &context_info, + std::string_view, typename rpc_protocol::supported_serialize_protocols protocols)>; using route_key = typename rpc_protocol::route_key_t; @@ -75,25 +75,23 @@ class router { template struct execute_visitor { std::string_view data; - rpc_context &context_info; Self *self; template async_simple::coro::Lazy> operator()( const serialize_protocol &) { return internal::execute_coro( - data, context_info, self); + data, self); } }; template struct execute_visitor { std::string_view data; - rpc_context &context_info; template async_simple::coro::Lazy> operator()( const serialize_protocol &) { return internal::execute_coro( - data, context_info); + data); } }; @@ -134,9 +132,9 @@ class router { auto it = coro_handlers_.emplace( key, [self]( - std::string_view data, rpc_context &context_info, + std::string_view data, typename rpc_protocol::supported_serialize_protocols protocols) { - execute_visitor visitor{data, context_info, self}; + execute_visitor visitor{data, self}; return std::visit(visitor, protocols); }); if (!it.second) { @@ -188,9 +186,9 @@ class router { async_simple::coro::Lazy>) { auto it = coro_handlers_.emplace( key, - [](std::string_view data, rpc_context &context_info, + [](std::string_view data, typename rpc_protocol::supported_serialize_protocols protocols) { - execute_visitor visitor{data, context_info}; + execute_visitor visitor{data}; return std::visit(visitor, protocols); }); if (!it.second) { @@ -234,7 +232,6 @@ class router { async_simple::coro::Lazy> route_coro( auto handler, std::string_view data, - rpc_context &context_info, typename rpc_protocol::supported_serialize_protocols protocols, const typename rpc_protocol::route_key_t &route_key) { using namespace std::string_literals; @@ -246,7 +243,7 @@ class router { #endif // clang-format off - auto res = co_await (*handler)(data, context_info, protocols); + auto res = co_await (*handler)(data, protocols); // clang-format on if (res.has_value()) AS_LIKELY { diff --git a/include/ylt/coro_rpc/impl/rpc_execute.hpp b/include/ylt/coro_rpc/impl/rpc_execute.hpp index 0a93a2338..f394c1609 100644 --- a/include/ylt/coro_rpc/impl/rpc_execute.hpp +++ b/include/ylt/coro_rpc/impl/rpc_execute.hpp @@ -152,7 +152,7 @@ inline std::optional execute( template inline async_simple::coro::Lazy> execute_coro( - std::string_view data, rpc_context &context_info, + std::string_view data, Self *self = nullptr) { using T = decltype(func); using param_type = util::function_parameters_t; @@ -162,54 +162,24 @@ inline async_simple::coro::Lazy> execute_coro( if constexpr (!std::is_void_v) { using First = std::tuple_element_t<0, param_type>; constexpr bool is_conn = requires { typename First::return_type; }; - if constexpr (is_conn) { - static_assert(std::is_void_v, - "The return_type must be void"); - } - - using conn_return_type = decltype(get_return_type()); - constexpr bool has_coro_conn_v = - std::is_same_v, First>; - auto args = util::get_args(); + static_assert(!is_conn,"context is not allowed as parameter in coroutine function"); bool is_ok = true; - constexpr size_t size = std::tuple_size_v; + constexpr size_t size = std::tuple_size_v; + param_type args; if constexpr (size > 0) { is_ok = serialize_proto::deserialize_to(args, data); } - if constexpr (std::is_void_v) { if constexpr (std::is_void_v) { - if constexpr (has_coro_conn_v) { - // call void func(coro_conn, args...) - co_await std::apply( - func, - std::tuple_cat(std::forward_as_tuple( - context_base( - context_info)), - std::move(args))); - } - else { // call void func(args...) co_await std::apply(func, std::move(args)); - } } else { auto &o = *self; - if constexpr (has_coro_conn_v) { - // call void o.func(coro_conn, args...) - co_await std::apply( - func, std::tuple_cat( - std::forward_as_tuple( - o, context_base( - context_info)), - std::move(args))); - } - else { // call void o.func(args...) co_await std::apply( func, std::tuple_cat(std::forward_as_tuple(o), std::move(args))); - } } } else { diff --git a/src/coro_rpc/tests/test_router.cpp b/src/coro_rpc/tests/test_router.cpp index b2c6a2503..d6aef67a4 100644 --- a/src/coro_rpc/tests/test_router.cpp +++ b/src/coro_rpc/tests/test_router.cpp @@ -223,7 +223,7 @@ TEST_CASE("testing coro_handler") { async_simple::coro::syncAwait(router.route_coro( handler, std::string_view{buf.data() + g_head_offset, buf.size() - g_tail_offset}, - ctx, std::variant{}, id)); + std::variant{}, id)); } TEST_CASE("testing not registered func") { From 121df7e30f84f7175edee5bb075d9d40ee6e5dd8 Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Wed, 27 Mar 2024 21:07:42 +0800 Subject: [PATCH 05/19] add support for context_info --- include/ylt/coro_rpc/impl/context.hpp | 63 +---------- include/ylt/coro_rpc/impl/coro_connection.hpp | 104 +++++++++++++++++- .../impl/protocol/coro_rpc_protocol.hpp | 22 +++- include/ylt/coro_rpc/impl/rpc_execute.hpp | 3 +- src/coro_rpc/tests/rpc_api.cpp | 6 +- src/coro_rpc/tests/rpc_api.hpp | 2 + src/coro_rpc/tests/test_router.cpp | 1 + 7 files changed, 136 insertions(+), 65 deletions(-) diff --git a/include/ylt/coro_rpc/impl/context.hpp b/include/ylt/coro_rpc/impl/context.hpp index 85988e085..76febdf6a 100644 --- a/include/ylt/coro_rpc/impl/context.hpp +++ b/include/ylt/coro_rpc/impl/context.hpp @@ -50,7 +50,7 @@ class context_base { return false; } - if (has_closed()) + if (self_->has_closed()) AS_UNLIKELY { ELOGV(DEBUG, "response_msg failed: connection has been closed"); return false; @@ -125,65 +125,14 @@ class context_base { // response_handler_(std::move(conn_), std::move(ret)); } /*finish here*/ - self_->status_ = context_status::start_response; + self_->status_ = context_status::finish_response; } - - /*! - * Check connection closed or not - * - * @return true if closed, otherwise false - */ - bool has_closed() const { return self_->conn_->has_closed(); } - - /*! - * Close connection - */ - void close() { return self_->conn_->async_close(); } - - /*! - * Get the unique connection ID - * @return connection id - */ - uint64_t get_connection_id() const noexcept { - return self_->conn_->get_connection_id(); - } - - /*! - * Set the response_attachment - * @return a ref of response_attachment - */ - void set_response_attachment(std::string attachment) { - set_response_attachment([attachment = std::move(attachment)] { - return std::string_view{attachment}; - }); + const context_info_t* get_context() const noexcept { + return self_.get(); } - - /*! - * Set the response_attachment - * @return a ref of response_attachment - */ - void set_response_attachment(std::function attachment) { - self_->resp_attachment_ = std::move(attachment); + context_info_t* get_context() noexcept { + return self_.get(); } - - /*! - * Get the request attachment - * @return connection id - */ - std::string_view get_request_attachment() const { - return self_->req_attachment_; - } - - /*! - * Release the attachment - * @return connection id - */ - std::string release_request_attachment() { - return std::move(self_->req_attachment_); - } - - std::any &tag() { return self_->conn_->tag(); } - const std::any &tag() const { return self_->conn_->tag(); } }; template diff --git a/include/ylt/coro_rpc/impl/coro_connection.hpp b/include/ylt/coro_rpc/impl/coro_connection.hpp index 01c81302d..92d35081e 100644 --- a/include/ylt/coro_rpc/impl/coro_connection.hpp +++ b/include/ylt/coro_rpc/impl/coro_connection.hpp @@ -42,6 +42,9 @@ using rpc_conn = std::shared_ptr; enum class context_status : int { init, start_response, finish_response }; template struct context_info_t { +#ifndef CORO_RPC_TEST +private: +#endif std::shared_ptr conn_; typename rpc_protocol::req_header req_head_; std::string req_body_; @@ -50,6 +53,10 @@ struct context_info_t { return std::string_view{}; }; std::atomic status_ = context_status::init; +public: + template + friend class context_base; + friend class coro_connection; context_info_t(std::shared_ptr &&conn) : conn_(std::move(conn)) {} context_info_t(std::shared_ptr &&conn, @@ -57,7 +64,22 @@ struct context_info_t { : conn_(std::move(conn)), req_body_(std::move(req_body_buf)), req_attachment_(std::move(req_attachment_buf)) {} + uint64_t get_connection_id() noexcept; + uint64_t has_closed() const noexcept; + void close(); + uint64_t get_connection_id() const noexcept; + void set_response_attachment(std::string_view attachment); + void set_response_attachment(std::string attachment); + void set_response_attachment(std::function attachment); + std::string_view get_request_attachment() const; + std::string release_request_attachment(); + std::any &tag() noexcept; + const std::any &tag() const noexcept; + asio::ip::tcp::endpoint get_local_endpoint() const noexcept; + asio::ip::tcp::endpoint get_remote_endpoint() const noexcept; + uint64_t get_request_id() const noexcept; }; + /*! * TODO: add doc */ @@ -233,7 +255,7 @@ class coro_connection : public std::enable_shared_from_this { router .route_coro(coro_handler, payload, serialize_proto.value(), key) - .via(executor_) + .via(executor_).setLazyLocal((void*)context_info.get()) .start([context_info](auto &&result) mutable { asio::dispatch([context_info=std::move(context_info),result = std::move(result)]() mutable { coro_rpc::errc resp_err; @@ -379,6 +401,10 @@ class coro_connection : public std::enable_shared_from_this { auto &get_executor() { return *executor_; } + asio::ip::tcp::endpoint get_remote_endpoint() {return socket_.remote_endpoint();} + + asio::ip::tcp::endpoint get_local_endpoint() {return socket_.local_endpoint();} + private: async_simple::coro::Lazy response( std::string header_buf, std::string body_buf, @@ -550,4 +576,80 @@ class coro_connection : public std::enable_shared_from_this { #endif }; +template +uint64_t context_info_t::get_connection_id() noexcept { + return conn_->get_connection_id(); +} + +template +uint64_t context_info_t::has_closed() const noexcept { + return conn_->has_closed(); +} + +template +void context_info_t::close() { + return conn_->async_close(); +} + +template +uint64_t context_info_t::get_connection_id() const noexcept { + +} + +template +void context_info_t::set_response_attachment(std::string attachment) { + set_response_attachment([attachment = std::move(attachment)] { + return std::string_view{attachment}; + }); +} + +template +void context_info_t::set_response_attachment(std::string_view attachment) { + set_response_attachment([attachment] { + return attachment; + }); +} + +template +void context_info_t::set_response_attachment(std::function attachment) { + resp_attachment_ = std::move(attachment); +} + +template +std::string_view context_info_t::get_request_attachment() const { + return req_attachment_; +} + +template +std::string context_info_t::release_request_attachment() { + return std::move(req_attachment_); +} + +template +std::any & context_info_t::tag() noexcept { + return conn_->tag(); +} + +template +const std::any & context_info_t::tag() const noexcept { + return conn_->tag(); +} + +template +asio::ip::tcp::endpoint context_info_t::get_local_endpoint() const noexcept { + return conn_->get_local_endpoint(); +} + +template +asio::ip::tcp::endpoint context_info_t::get_remote_endpoint() const noexcept { + return conn_->get_remote_endpoint(); +} +namespace protocol { + template + uint64_t get_request_id(const typename rpc_protocol::req_header&) noexcept; +} +template +uint64_t context_info_t::get_request_id() const noexcept { + return coro_rpc::protocol::get_request_id(req_head_); +} } // namespace coro_rpc diff --git a/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp b/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp index ee20bd5b2..4c5e79372 100644 --- a/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp +++ b/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -61,7 +62,7 @@ struct coro_rpc_protocol { uint32_t seq_num; //!< sequence number uint32_t function_id; //!< rpc function ID uint32_t length; //!< length of RPC body - uint32_t attach_length; //!< reserved field + uint32_t attach_length; //!< attachment length }; struct resp_header { @@ -71,7 +72,7 @@ struct coro_rpc_protocol { uint8_t msg_type; //!< message type uint32_t seq_num; //!< sequence number uint32_t length; //!< length of RPC body - uint32_t attach_length; //!< reserved field + uint32_t attach_length; //!< attachment length }; using supported_serialize_protocols = std::variant; @@ -204,9 +205,26 @@ struct coro_rpc_protocol { }; STRUCT_PACK_REFL(coro_rpc_protocol::rpc_error, val(), msg); + +template +uint64_t get_request_id(const typename rpc_protocol::req_header& header) noexcept { + if constexpr (std::is_same_v) { + return header.seq_num; + } + else { + return 0; + } +} } // namespace protocol template using context = coro_rpc::context_base; using rpc_error = protocol::coro_rpc_protocol::rpc_error; + +template +async_simple::coro::Lazy*> get_context() { + auto *ctx=co_await async_simple::coro::LazyLocals{}; + assert(ctx!=nullptr); + co_return (context_info_t*)ctx; +} } // namespace coro_rpc \ No newline at end of file diff --git a/include/ylt/coro_rpc/impl/rpc_execute.hpp b/include/ylt/coro_rpc/impl/rpc_execute.hpp index f394c1609..7b21d710a 100644 --- a/include/ylt/coro_rpc/impl/rpc_execute.hpp +++ b/include/ylt/coro_rpc/impl/rpc_execute.hpp @@ -22,8 +22,8 @@ #include #include -#include "context.hpp" #include "coro_connection.hpp" +#include "context.hpp" #include "ylt/util/type_traits.h" namespace coro_rpc::internal { @@ -43,7 +43,6 @@ auto get_return_type() { return First{}; } } - template using rpc_context = std::shared_ptr>; diff --git a/src/coro_rpc/tests/rpc_api.cpp b/src/coro_rpc/tests/rpc_api.cpp index a980f3189..7ad99a6d7 100644 --- a/src/coro_rpc/tests/rpc_api.cpp +++ b/src/coro_rpc/tests/rpc_api.cpp @@ -46,9 +46,9 @@ int long_run_func(int val) { } void echo_with_attachment(coro_rpc::context conn) { - ELOGV(INFO, "conn ID:%d", conn.get_connection_id()); - auto str = conn.release_request_attachment(); - conn.set_response_attachment(std::move(str)); + ELOGV(INFO, "call function echo_with_attachment, conn ID:%d", conn.get_context()->get_connection_id()); + auto str = conn.get_context()->release_request_attachment(); + conn.get_context()->set_response_attachment(std::move(str)); conn.response_msg(); } diff --git a/src/coro_rpc/tests/rpc_api.hpp b/src/coro_rpc/tests/rpc_api.hpp index 5f5bb4a3a..13b327660 100644 --- a/src/coro_rpc/tests/rpc_api.hpp +++ b/src/coro_rpc/tests/rpc_api.hpp @@ -48,6 +48,8 @@ void coro_fun_with_delay_return_string_twice( void coro_fun_with_delay_return_void_cost_long_time( coro_rpc::context conn); inline async_simple::coro::Lazy coro_func_return_void(int i) { + auto ctx = co_await coro_rpc::get_context(); + ELOGV(INFO,"call function coro_func_return_void, connection id:%d,request id:%d",ctx->get_connection_id(),ctx->get_request_id()); co_return; } inline async_simple::coro::Lazy coro_func(int i) { co_return i; } diff --git a/src/coro_rpc/tests/test_router.cpp b/src/coro_rpc/tests/test_router.cpp index d6aef67a4..152f1944d 100644 --- a/src/coro_rpc/tests/test_router.cpp +++ b/src/coro_rpc/tests/test_router.cpp @@ -28,6 +28,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#define CORO_RPC_TEST #include #include #include From e95ddd8e9e027d1186be3d3246be1c056f3ec705 Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Thu, 28 Mar 2024 11:20:22 +0800 Subject: [PATCH 06/19] support throw exception to return error. add test. --- include/ylt/coro_rpc/impl/router.hpp | 36 ++++++++++-- include/ylt/easylog/record.hpp | 4 +- src/coro_rpc/tests/rpc_api.cpp | 64 +++++++++++++++++++++ src/coro_rpc/tests/rpc_api.hpp | 6 ++ src/coro_rpc/tests/test_coro_rpc_server.cpp | 34 +++++++++++ 5 files changed, 138 insertions(+), 6 deletions(-) diff --git a/include/ylt/coro_rpc/impl/router.hpp b/include/ylt/coro_rpc/impl/router.hpp index ae5cda2d8..645a599e3 100644 --- a/include/ylt/coro_rpc/impl/router.hpp +++ b/include/ylt/coro_rpc/impl/router.hpp @@ -52,7 +52,7 @@ class router { using coro_router_handler_t = std::function>( - std::string_view, + std::string_view, typename rpc_protocol::supported_serialize_protocols protocols)>; using route_key = typename rpc_protocol::route_key_t; @@ -256,8 +256,22 @@ class router { co_return std::make_pair(coro_rpc::errc::invalid_argument, "invalid rpc function arguments"s); } + } catch (coro_rpc::errc ec) { + auto msg = coro_rpc::make_error_message(ec); + ELOGV(INFO, + "user return coro_rpc::errc, message: %s, value: %d, rpc " + "function name:%s ", + coro_rpc::make_error_message(ec), static_cast(ec), + get_name(route_key).data()); + co_return std::make_pair(ec, std::string{msg}); + } catch (coro_rpc::err_code ec) { + ELOGV(INFO, + "user return coro_rpc::err_code, message: %s, value: %d, rpc " + "function name:%s ", + ec.message(), ec.val(), get_name(route_key).data()); + co_return std::make_pair(ec.ec, std::string{ec.message()}); } catch (const std::exception &e) { - ELOGV(ERROR, "exception: %s in rpc function: %s", e.what(), + ELOGV(INFO, "exception: %s in rpc function: %s", e.what(), get_name(route_key).data()); co_return std::make_pair(coro_rpc::errc::interrupted, e.what()); } catch (...) { @@ -300,12 +314,26 @@ class router { return std::make_pair(coro_rpc::errc::invalid_argument, "invalid rpc function arguments"s); } + } catch (coro_rpc::errc ec) { + auto msg = coro_rpc::make_error_message(ec); + ELOGV(INFO, + "user return coro_rpc::errc, message: %s, value: %d, rpc " + "function name:%s ", + coro_rpc::make_error_message(ec), static_cast(ec), + get_name(route_key).data()); + return std::make_pair(ec, std::string{msg}); + } catch (coro_rpc::err_code ec) { + ELOGV(INFO, + "user return coro_rpc::err_code, message: %s, value: %d, rpc " + "function name:%s ", + ec.message(), ec.val(), get_name(route_key).data()); + return std::make_pair(ec.ec, std::string{ec.message()}); } catch (const std::exception &e) { - ELOGV(ERROR, "exception: %s in rpc function: %s", e.what(), + ELOGV(INFO, "exception: %s in rpc function: %s", e.what(), get_name(route_key).data()); return std::make_pair(coro_rpc::errc::interrupted, e.what()); } catch (...) { - ELOGV(ERROR, "unknown exception in rpc function: %s", + ELOGV(WARNING, "unknown exception in rpc function: %s", get_name(route_key).data()); return std::make_pair(coro_rpc::errc::interrupted, "unknown rpc function exception"s); diff --git a/include/ylt/easylog/record.hpp b/include/ylt/easylog/record.hpp index f5dacdd42..6a3d4982d 100644 --- a/include/ylt/easylog/record.hpp +++ b/include/ylt/easylog/record.hpp @@ -174,7 +174,7 @@ class record_t { else if constexpr (detail::c_array_v) { ss_.append(data); } - else if constexpr (detail::has_data_v) { + else if constexpr (requires{ss_.append(data.data());}) /* TODO: update it by SFINAE with support c++17 */{ ss_.append(data.data()); } else if constexpr (detail::has_str_v) { @@ -187,7 +187,7 @@ class record_t { else { std::stringstream ss; ss << data; - ss_.append(ss.str()); + ss_.append(std::move(ss).str()); } return *this; diff --git a/src/coro_rpc/tests/rpc_api.cpp b/src/coro_rpc/tests/rpc_api.cpp index 7ad99a6d7..a73d8b1df 100644 --- a/src/coro_rpc/tests/rpc_api.cpp +++ b/src/coro_rpc/tests/rpc_api.cpp @@ -52,6 +52,70 @@ void echo_with_attachment(coro_rpc::context conn) { conn.response_msg(); } +void test_context(coro_rpc::context conn) { + auto *ctx=conn.get_context(); + if (ctx->has_closed()) { + throw std::runtime_error("connection is close!"); + } + ELOGV(INFO, "call function echo_with_attachment, conn ID:%d, request ID:%d", ctx->get_connection_id(),ctx->get_request_id()); + ELOGI << "remote endpoint: " << ctx->get_remote_endpoint()<<"local endpoint"<get_local_endpoint(); + std::string sv{ctx->get_request_attachment()}; + auto str = ctx->release_request_attachment(); + if (sv!=str) { + conn.response_error(coro_rpc::errc::interrupted); + ctx->close(); + return; + } + ctx->set_response_attachment(std::move(str)); + [conn=std::move(conn)]() mutable ->async_simple::coro::Lazy { + co_await coro_io::sleep_for(514ms); + ELOGV(INFO, "response in another executor"); + conn.response_msg(); + }().via(coro_io::get_global_executor()).detach(); +} +using namespace async_simple::coro; + +Lazy test_lazy_context() { + auto *ctx = co_await coro_rpc::get_context(); + if (ctx->has_closed()) { + throw std::runtime_error("connection is close!"); + } + ELOGV(INFO, "call function echo_with_attachment, conn ID:%d, request ID:%d", ctx->get_connection_id(),ctx->get_request_id()); + ELOGI << "remote endpoint: " << ctx->get_remote_endpoint()<<"local endpoint"<get_local_endpoint(); + std::string sv{ctx->get_request_attachment()}; + auto str = ctx->release_request_attachment(); + if (sv!=str) { + ctx->close(); + throw coro_rpc::errc::interrupted; + co_return; + } + ctx->set_response_attachment(std::move(str)); + auto ex=coro_io::get_global_executor(); + co_await coro_io::sleep_for(514ms,coro_io::get_global_executor()); + ELOGV(INFO, "response in another executor"); + co_return; +} + +Lazy test_response_error() { + throw coro_rpc::errc::io_error; + co_return; +} + +Lazy test_response_error2() { + throw coro_rpc::err_code{uint16_t{12244}}; + co_return; +} + +void test_response_error3() { + throw coro_rpc::errc::operation_canceled; + return; +} + +void test_response_error4() { + throw coro_rpc::err_code{uint16_t{12245}}; + return; +} + void coro_fun_with_user_define_connection_type(my_context conn) { conn.ctx_.response_msg(); } diff --git a/src/coro_rpc/tests/rpc_api.hpp b/src/coro_rpc/tests/rpc_api.hpp index 13b327660..293121e4d 100644 --- a/src/coro_rpc/tests/rpc_api.hpp +++ b/src/coro_rpc/tests/rpc_api.hpp @@ -39,6 +39,12 @@ void echo_with_attachment(coro_rpc::context conn); inline void error_with_context(coro_rpc::context conn) { conn.response_error(coro_rpc::err_code{104}, "My Error."); } +void test_context(coro_rpc::context conn); +async_simple::coro::Lazy test_lazy_context(); +async_simple::coro::Lazy test_response_error(); +async_simple::coro::Lazy test_response_error2(); +void test_response_error3(); +void test_response_error4(); void coro_fun_with_user_define_connection_type(my_context conn); void coro_fun_with_delay_return_void(coro_rpc::context conn); void coro_fun_with_delay_return_string(coro_rpc::context conn); diff --git a/src/coro_rpc/tests/test_coro_rpc_server.cpp b/src/coro_rpc/tests/test_coro_rpc_server.cpp index 3d9b52824..f190ee8f1 100644 --- a/src/coro_rpc/tests/test_coro_rpc_server.cpp +++ b/src/coro_rpc/tests/test_coro_rpc_server.cpp @@ -56,6 +56,8 @@ struct CoroServerTester : ServerTester { test_start_new_server_with_same_port(); test_server_send_bad_rpc_result(); test_server_send_no_body(); + test_context_func(); + test_return_err_by_throw_exception(); this->test_call_with_delay_func(); this->test_call_with_delay_func< coro_fun_with_user_define_connection_type>(); @@ -80,6 +82,9 @@ struct CoroServerTester : ServerTester { server.register_handler<&HelloService::hello>(&hello_service_); server.register_handler(); server.register_handler(); + server.register_handler(); + server.register_handler(); server.register_handler(); server.register_handler(); server.register_handler(); @@ -95,6 +100,35 @@ struct CoroServerTester : ServerTester { server.register_handler<&CoroServerTester::get_value>(this); } + void test_context_func() { + auto client = create_client(); + ELOGV(INFO, "run %s, client_id %d", __func__, client->get_client_id()); + client->set_req_attachment("1234567890987654321234567890"); + auto result = syncAwait(client->call()); + CHECK(client->get_resp_attachment() == "1234567890987654321234567890"); + CHECK(result); + client->set_req_attachment("01234567890987654321234567890"); + result = syncAwait(client->call()); + CHECK(client->get_resp_attachment() == "01234567890987654321234567890"); + CHECK(result); + } + void test_return_err_by_throw_exception() { + auto client = create_client(); + ELOGV(INFO, "run %s, client_id %d", __func__, client->get_client_id()); + auto result = syncAwait(client->call()); + REQUIRE(!result); + CHECK(result.error().code == coro_rpc::errc::io_error); + result = syncAwait(client->call()); + REQUIRE(!result); + CHECK(result.error().code == coro_rpc::errc{12244}); + result = syncAwait(client->call()); + REQUIRE(!result); + CHECK(result.error().code == coro_rpc::errc::operation_canceled); + result = syncAwait(client->call()); + REQUIRE(!result); + CHECK(result.error().code == coro_rpc::errc{12245}); + } + void test_function_not_registered() { g_action = {}; auto client = create_client(); From 4e2264888ae41b1d50411d2894b4b45e37b2828f Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Thu, 28 Mar 2024 20:54:48 +0800 Subject: [PATCH 07/19] fix bug --- include/ylt/coro_rpc/impl/coro_connection.hpp | 14 +++---- include/ylt/coro_rpc/impl/coro_rpc_client.hpp | 4 +- .../impl/protocol/coro_rpc_protocol.hpp | 7 +--- include/ylt/coro_rpc/impl/router.hpp | 30 ++++++-------- .../examples/base_examples/client.cpp | 2 +- .../examples/base_examples/rpc_service.cpp | 14 +++---- .../examples/file_transfer/rpc_service.cpp | 18 +++++---- src/coro_rpc/tests/rpc_api.cpp | 16 ++++---- src/coro_rpc/tests/rpc_api.hpp | 2 +- src/coro_rpc/tests/test_coro_rpc_client.cpp | 2 +- src/coro_rpc/tests/test_coro_rpc_server.cpp | 40 +++++++++++-------- 11 files changed, 76 insertions(+), 73 deletions(-) diff --git a/include/ylt/coro_rpc/impl/coro_connection.hpp b/include/ylt/coro_rpc/impl/coro_connection.hpp index 92d35081e..2d087d9f7 100644 --- a/include/ylt/coro_rpc/impl/coro_connection.hpp +++ b/include/ylt/coro_rpc/impl/coro_connection.hpp @@ -269,7 +269,7 @@ class coro_connection : public std::enable_shared_from_this { std::tie(resp_err, resp_buf) = result.value(); } context_info->conn_->template direct_response_msg( - resp_err, resp_buf, context_info->req_head_); + resp_err, resp_buf, context_info->req_head_,std::move(context_info->resp_attachment_)); }); }); } @@ -315,8 +315,7 @@ class coro_connection : public std::enable_shared_from_this { * @param ret object of message type */ template - void direct_response_msg(coro_rpc::errc &resp_err, std::string &resp_buf, - const typename rpc_protocol::req_header &req_head) { + void direct_response_msg(coro_rpc::errc &resp_err, std::string &resp_buf,const typename rpc_protocol::req_header &req_head, std::function&& attachment=[]{return std::string_view();}) { std::string resp_error_msg; if (!!resp_err) { resp_error_msg = std::move(resp_buf); @@ -324,13 +323,11 @@ class coro_connection : public std::enable_shared_from_this { ELOGV(WARNING, "rpc route/execute error, error msg: %s", resp_error_msg.data()); } std::string header_buf = rpc_protocol::prepare_response( - resp_buf, req_head, 0, resp_err, resp_error_msg); + resp_buf, req_head, attachment().length(), resp_err, resp_error_msg); response( std::move(header_buf), std::move(resp_buf), - [] { - return std::string_view{}; - }, + std::move(attachment), nullptr) .start([](auto &&) { }); @@ -356,7 +353,7 @@ class coro_connection : public std::enable_shared_from_this { }; std::string body_buf; std::string header_buf = rpc_protocol::prepare_response( - body_buf, req_head, 0, ec, error_msg, true); + body_buf, req_head, 0, ec, error_msg); response(std::move(header_buf), std::move(body_buf), std::move(attach_ment), shared_from_this()) .via(executor_) @@ -504,6 +501,7 @@ class coro_connection : public std::enable_shared_from_this { } void close() { + ELOGV(TRACE,"connection closed"); if (has_closed_) { return; } diff --git a/include/ylt/coro_rpc/impl/coro_rpc_client.hpp b/include/ylt/coro_rpc/impl/coro_rpc_client.hpp index f775f457f..12e8eb969 100644 --- a/include/ylt/coro_rpc/impl/coro_rpc_client.hpp +++ b/include/ylt/coro_rpc/impl/coro_rpc_client.hpp @@ -747,10 +747,11 @@ class coro_rpc_client { } } else { - err.val() = rpc_errc; if (rpc_errc != UINT8_MAX) { + err.val() = rpc_errc; ec = struct_pack::deserialize_to(err.msg, buffer); if SP_LIKELY (!ec) { + ELOGV(WARNING,"deserilaize rpc result failed"); error_happen = true; return rpc_result{unexpect_t{}, std::move(err)}; } @@ -758,6 +759,7 @@ class coro_rpc_client { else { ec = struct_pack::deserialize_to(err, buffer); if SP_LIKELY (!ec) { + ELOGV(WARNING,"deserilaize rpc result failed"); return rpc_result{unexpect_t{}, std::move(err)}; } } diff --git a/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp b/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp index 4c5e79372..578c1321e 100644 --- a/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp +++ b/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp @@ -134,8 +134,7 @@ struct coro_rpc_protocol { const req_header& req_header, std::size_t attachment_len, coro_rpc::errc rpc_err_code = {}, - std::string_view err_msg = {}, - bool is_user_defined_error = false) { + std::string_view err_msg = {}) { std::string err_msg_buf; std::string header_buf; header_buf.resize(RESP_HEAD_LEN); @@ -151,7 +150,6 @@ struct coro_rpc_protocol { err_msg_buf = "attachment larger than 4G:" + std::to_string(attachment_len) + "B"; err_msg = err_msg_buf; - is_user_defined_error = false; } else if (rpc_result.size() > UINT32_MAX) AS_UNLIKELY { @@ -161,12 +159,11 @@ struct coro_rpc_protocol { err_msg_buf = "body larger than 4G:" + std::to_string(attachment_len) + "B"; err_msg = err_msg_buf; - is_user_defined_error = false; } if (rpc_err_code != coro_rpc::errc{}) AS_UNLIKELY { rpc_result.clear(); - if (is_user_defined_error) { + if (static_cast(rpc_err_code)>UINT8_MAX) { struct_pack::serialize_to( rpc_result, std::pair{static_cast(rpc_err_code), err_msg}); diff --git a/include/ylt/coro_rpc/impl/router.hpp b/include/ylt/coro_rpc/impl/router.hpp index 645a599e3..f94fcdc90 100644 --- a/include/ylt/coro_rpc/impl/router.hpp +++ b/include/ylt/coro_rpc/impl/router.hpp @@ -258,17 +258,14 @@ class router { } } catch (coro_rpc::errc ec) { auto msg = coro_rpc::make_error_message(ec); - ELOGV(INFO, - "user return coro_rpc::errc, message: %s, value: %d, rpc " - "function name:%s ", - coro_rpc::make_error_message(ec), static_cast(ec), - get_name(route_key).data()); + ELOGI<< + "user return coro_rpc::errc, message:"<(ec) <<", rpc " + "function name:"<< get_name(route_key); co_return std::make_pair(ec, std::string{msg}); } catch (coro_rpc::err_code ec) { - ELOGV(INFO, - "user return coro_rpc::err_code, message: %s, value: %d, rpc " - "function name:%s ", - ec.message(), ec.val(), get_name(route_key).data()); + ELOGI<< + "user return coro_rpc::err_code, message:"<(ec), - get_name(route_key).data()); + ELOGI<< + "user return coro_rpc::errc, message:"<(ec) <<", rpc " + "function name:"<< get_name(route_key); return std::make_pair(ec, std::string{msg}); } catch (coro_rpc::err_code ec) { - ELOGV(INFO, - "user return coro_rpc::err_code, message: %s, value: %d, rpc " - "function name:%s ", - ec.message(), ec.val(), get_name(route_key).data()); + ELOGI<< + "user return coro_rpc::err_code, message:"< show_rpc_call() { ret = co_await client.call(); - assert(ret.error().code == 404); + assert(ret.error().code.val() == 404); assert(ret.error().msg == "404 Not Found."); ret = co_await client.call(); diff --git a/src/coro_rpc/examples/base_examples/rpc_service.cpp b/src/coro_rpc/examples/base_examples/rpc_service.cpp index 5b45d7c26..5a59f1c49 100644 --- a/src/coro_rpc/examples/base_examples/rpc_service.cpp +++ b/src/coro_rpc/examples/base_examples/rpc_service.cpp @@ -39,16 +39,16 @@ int A_add_B(int a, int b) { void echo_with_attachment(coro_rpc::context conn) { ELOGV(INFO, "call echo_with_attachment"); - std::string str = conn.release_request_attachment(); - conn.set_response_attachment(std::move(str)); + std::string str = conn.get_context()->release_request_attachment(); + conn.get_context()->set_response_attachment(std::move(str)); conn.response_msg(); } void echo_with_attachment2(coro_rpc::context conn) { ELOGV(INFO, "call echo_with_attachment2"); - std::string_view str = conn.get_request_attachment(); + std::string_view str = conn.get_context()->get_request_attachment(); // The live time of attachment is same as coro_rpc::context - conn.set_response_attachment([str, conn] { + conn.get_context()->set_response_attachment([str, conn] { return str; }); conn.response_msg(); @@ -107,10 +107,10 @@ void return_error(coro_rpc::context conn) { conn.response_error(coro_rpc::err_code{404}, "404 Not Found."); } void rpc_with_state_by_tag(coro_rpc::context conn) { - if (!conn.tag().has_value()) { - conn.tag() = uint64_t{0}; + if (!conn.get_context()->tag().has_value()) { + conn.get_context()->tag() = uint64_t{0}; } - auto &cnter = std::any_cast(conn.tag()); + auto &cnter = std::any_cast(conn.get_context()->tag()); ELOGV(INFO, "call count: %d", ++cnter); conn.response_msg(std::to_string(cnter)); } \ No newline at end of file diff --git a/src/coro_rpc/examples/file_transfer/rpc_service.cpp b/src/coro_rpc/examples/file_transfer/rpc_service.cpp index e375fc2b2..eaf9bcce5 100644 --- a/src/coro_rpc/examples/file_transfer/rpc_service.cpp +++ b/src/coro_rpc/examples/file_transfer/rpc_service.cpp @@ -6,18 +6,19 @@ std::string echo(std::string str) { return str; } void upload_file(coro_rpc::context conn, file_part part) { - if (!conn.tag().has_value()) { + auto &ctx=*conn.get_context(); + if (!ctx.tag().has_value()) { auto filename = std::to_string(std::time(0)) + std::filesystem::path(part.filename).extension().string(); - conn.tag() = std::make_shared( + ctx.tag() = std::make_shared( filename, std::ios::binary | std::ios::app); } - auto stream = std::any_cast>(conn.tag()); + auto stream = std::any_cast>(ctx.tag()); std::cout << "file part content size=" << part.content.size() << "\n"; stream->write(part.content.data(), part.content.size()); if (part.eof) { stream->close(); - conn.tag().reset(); + ctx.tag().reset(); std::cout << "file upload finished\n"; } @@ -26,7 +27,8 @@ void upload_file(coro_rpc::context conn, file_part part) { void download_file(coro_rpc::context conn, std::string filename) { - if (!conn.tag().has_value()) { + auto &ctx=*conn.get_context(); + if (!ctx.tag().has_value()) { std::string actual_filename = std::filesystem::path(filename).filename().string(); if (!std::filesystem::is_regular_file(actual_filename) || @@ -34,10 +36,10 @@ void download_file(coro_rpc::context conn, conn.response_msg(response_part{std::errc::invalid_argument}); return; } - conn.tag() = + ctx.tag() = std::make_shared(actual_filename, std::ios::binary); } - auto stream = std::any_cast>(conn.tag()); + auto stream = std::any_cast>(ctx.tag()); char buf[1024]; @@ -47,7 +49,7 @@ void download_file(coro_rpc::context conn, if (stream->eof()) { stream->close(); - conn.tag().reset(); + ctx.tag().reset(); } } diff --git a/src/coro_rpc/tests/rpc_api.cpp b/src/coro_rpc/tests/rpc_api.cpp index a73d8b1df..412f2b617 100644 --- a/src/coro_rpc/tests/rpc_api.cpp +++ b/src/coro_rpc/tests/rpc_api.cpp @@ -17,6 +17,7 @@ #include #include +#include "ylt/coro_rpc/impl/errno.h" using namespace coro_rpc; using namespace std::chrono_literals; @@ -67,11 +68,13 @@ void test_context(coro_rpc::context conn) { return; } ctx->set_response_attachment(std::move(str)); - [conn=std::move(conn)]() mutable ->async_simple::coro::Lazy { + [](coro_rpc::context conn) -> async_simple::coro::Lazy { co_await coro_io::sleep_for(514ms); ELOGV(INFO, "response in another executor"); conn.response_msg(); - }().via(coro_io::get_global_executor()).detach(); + }(std::move(conn)).via(coro_io::get_global_executor()).detach(); + ELOGV(INFO, "returning"); + return; } using namespace async_simple::coro; @@ -90,29 +93,28 @@ Lazy test_lazy_context() { co_return; } ctx->set_response_attachment(std::move(str)); - auto ex=coro_io::get_global_executor(); co_await coro_io::sleep_for(514ms,coro_io::get_global_executor()); ELOGV(INFO, "response in another executor"); co_return; } Lazy test_response_error() { - throw coro_rpc::errc::io_error; + throw coro_rpc::err_code{uint16_t{12243}}; co_return; } Lazy test_response_error2() { - throw coro_rpc::err_code{uint16_t{12244}}; + throw coro_rpc::errc::io_error; co_return; } void test_response_error3() { - throw coro_rpc::errc::operation_canceled; + throw coro_rpc::err_code{uint16_t{12243}}; return; } void test_response_error4() { - throw coro_rpc::err_code{uint16_t{12245}}; + throw coro_rpc::errc::io_error; return; } diff --git a/src/coro_rpc/tests/rpc_api.hpp b/src/coro_rpc/tests/rpc_api.hpp index 293121e4d..91fc1da8c 100644 --- a/src/coro_rpc/tests/rpc_api.hpp +++ b/src/coro_rpc/tests/rpc_api.hpp @@ -37,7 +37,7 @@ struct my_context { }; void echo_with_attachment(coro_rpc::context conn); inline void error_with_context(coro_rpc::context conn) { - conn.response_error(coro_rpc::err_code{104}, "My Error."); + conn.response_error(coro_rpc::err_code{1004}, "My Error."); } void test_context(coro_rpc::context conn); async_simple::coro::Lazy test_lazy_context(); diff --git a/src/coro_rpc/tests/test_coro_rpc_client.cpp b/src/coro_rpc/tests/test_coro_rpc_client.cpp index 77df32dc3..a820f8e73 100644 --- a/src/coro_rpc/tests/test_coro_rpc_client.cpp +++ b/src/coro_rpc/tests/test_coro_rpc_client.cpp @@ -420,7 +420,7 @@ TEST_CASE("testing client with context response user-defined error") { server.register_handler(); auto ret = client.sync_call(); REQUIRE(!ret.has_value()); - CHECK(ret.error().code == coro_rpc::errc{104}); + CHECK(ret.error().code == coro_rpc::errc{1004}); CHECK(ret.error().msg == "My Error."); CHECK(client.has_closed() == false); auto ret2 = client.sync_call(); diff --git a/src/coro_rpc/tests/test_coro_rpc_server.cpp b/src/coro_rpc/tests/test_coro_rpc_server.cpp index f190ee8f1..73e35ce98 100644 --- a/src/coro_rpc/tests/test_coro_rpc_server.cpp +++ b/src/coro_rpc/tests/test_coro_rpc_server.cpp @@ -105,28 +105,36 @@ struct CoroServerTester : ServerTester { ELOGV(INFO, "run %s, client_id %d", __func__, client->get_client_id()); client->set_req_attachment("1234567890987654321234567890"); auto result = syncAwait(client->call()); - CHECK(client->get_resp_attachment() == "1234567890987654321234567890"); CHECK(result); + CHECK(client->get_resp_attachment() == "1234567890987654321234567890"); client->set_req_attachment("01234567890987654321234567890"); result = syncAwait(client->call()); - CHECK(client->get_resp_attachment() == "01234567890987654321234567890"); CHECK(result); + CHECK(client->get_resp_attachment() == "01234567890987654321234567890"); } void test_return_err_by_throw_exception() { - auto client = create_client(); - ELOGV(INFO, "run %s, client_id %d", __func__, client->get_client_id()); - auto result = syncAwait(client->call()); - REQUIRE(!result); - CHECK(result.error().code == coro_rpc::errc::io_error); - result = syncAwait(client->call()); - REQUIRE(!result); - CHECK(result.error().code == coro_rpc::errc{12244}); - result = syncAwait(client->call()); - REQUIRE(!result); - CHECK(result.error().code == coro_rpc::errc::operation_canceled); - result = syncAwait(client->call()); - REQUIRE(!result); - CHECK(result.error().code == coro_rpc::errc{12245}); + { + auto client = create_client(); + ELOGV(INFO, "run %s, client_id %d", __func__, client->get_client_id()); + auto result = syncAwait(client->call()); + REQUIRE(!result); + CHECK(result.error().code == coro_rpc::errc{12243}); + result = syncAwait(client->call()); + REQUIRE(!result); + CHECK(client->has_closed()); + CHECK(result.error().code == coro_rpc::errc::io_error); + } + { + auto client = create_client(); + ELOGV(INFO, "run %s, client_id %d", __func__, client->get_client_id()); + auto result = syncAwait(client->call()); + REQUIRE(!result); + CHECK(result.error().code == coro_rpc::errc{12243}); + result = syncAwait(client->call()); + REQUIRE(!result); + CHECK(client->has_closed()); + CHECK(result.error().code == coro_rpc::errc::io_error); + } } void test_function_not_registered() { From d148178d8173bb793641854d1dd475f00bb4e58d Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Fri, 29 Mar 2024 18:21:23 +0800 Subject: [PATCH 08/19] add example --- include/ylt/coro_io/coro_io.hpp | 8 +- include/ylt/coro_rpc/impl/coro_rpc_client.hpp | 1 + include/ylt/coro_rpc/impl/expected.hpp | 6 +- .../examples/base_examples/client.cpp | 39 +++--- .../examples/base_examples/rpc_service.cpp | 117 ++++++++---------- .../examples/base_examples/rpc_service.h | 24 ++-- .../examples/base_examples/server.cpp | 8 +- 7 files changed, 92 insertions(+), 111 deletions(-) diff --git a/include/ylt/coro_io/coro_io.hpp b/include/ylt/coro_io/coro_io.hpp index 81cd605a4..14fe43d00 100644 --- a/include/ylt/coro_io/coro_io.hpp +++ b/include/ylt/coro_io/coro_io.hpp @@ -48,7 +48,7 @@ class callback_awaitor_base { template class callback_awaitor_impl { public: - callback_awaitor_impl(Derived &awaitor, const Op &op) noexcept + callback_awaitor_impl(Derived &awaitor, Op &op) noexcept : awaitor(awaitor), op(op) {} constexpr bool await_ready() const noexcept { return false; } void await_suspend(std::coroutine_handle<> handle) noexcept { @@ -69,7 +69,7 @@ class callback_awaitor_base { private: Derived &awaitor; - const Op &op; + Op &op; }; public: @@ -97,7 +97,7 @@ class callback_awaitor_base { Derived *obj; }; template - callback_awaitor_impl await_resume(const Op &op) noexcept { + callback_awaitor_impl await_resume(Op &&op) noexcept { return callback_awaitor_impl{static_cast(*this), op}; } @@ -312,7 +312,7 @@ inline async_simple::coro::Lazy sleep_for(Duration d) { template struct post_helper { - void operator()(auto handler) const { + void operator()(auto handler) { asio::dispatch(e, [this, handler]() { try { if constexpr (std::is_same_v>) { diff --git a/include/ylt/coro_rpc/impl/coro_rpc_client.hpp b/include/ylt/coro_rpc/impl/coro_rpc_client.hpp index 12e8eb969..44d58252f 100644 --- a/include/ylt/coro_rpc/impl/coro_rpc_client.hpp +++ b/include/ylt/coro_rpc/impl/coro_rpc_client.hpp @@ -757,6 +757,7 @@ class coro_rpc_client { } } else { + ec = struct_pack::deserialize_to(err, buffer); if SP_LIKELY (!ec) { ELOGV(WARNING,"deserilaize rpc result failed"); diff --git a/include/ylt/coro_rpc/impl/expected.hpp b/include/ylt/coro_rpc/impl/expected.hpp index e6d4c1082..02b91375b 100644 --- a/include/ylt/coro_rpc/impl/expected.hpp +++ b/include/ylt/coro_rpc/impl/expected.hpp @@ -44,7 +44,11 @@ using unexpected = tl::unexpected; using unexpect_t = tl::unexpect_t; #endif -template +namespace protocol { + struct coro_rpc_protocol; +} + +template using rpc_result = expected; } // namespace coro_rpc \ No newline at end of file diff --git a/src/coro_rpc/examples/base_examples/client.cpp b/src/coro_rpc/examples/base_examples/client.cpp index 9cfeb1f62..36faba911 100644 --- a/src/coro_rpc/examples/base_examples/client.cpp +++ b/src/coro_rpc/examples/base_examples/client.cpp @@ -32,40 +32,37 @@ Lazy show_rpc_call() { [[maybe_unused]] auto ec = co_await client.connect("127.0.0.1", "8801"); assert(!ec); - auto ret = co_await client.call(); - assert(ret.value() == "hello_world"s); + auto ret = co_await client.call("hello"); + assert(ret.value() == "hello"); + + ret = co_await client.call("42"); + assert(ret.value()=="42"); + + ret = co_await client.call("hi"); + assert(ret.value()=="hi"); + + ret = co_await client.call("hey"); + assert(ret.value()=="hey"); client.set_req_attachment("This is attachment."); auto ret_void = co_await client.call(); assert(client.get_resp_attachment() == "This is attachment."); - client.set_req_attachment("This is attachment2."); - ret_void = co_await client.call(); - assert(client.get_resp_attachment() == "This is attachment2."); - - auto ret_int = co_await client.call(12, 30); - assert(ret_int.value() == 42); - - ret = co_await client.call("coro_echo"); - assert(ret.value() == "coro_echo"s); - - ret = co_await client.call("hello_with_delay"s); - assert(ret.value() == "hello_with_delay"s); - ret = co_await client.call("nested_echo"s); assert(ret.value() == "nested_echo"s); ret = co_await client.call<&HelloService::hello>(); assert(ret.value() == "HelloService::hello"s); - ret = co_await client.call<&HelloService::hello_with_delay>( - "HelloService::hello_with_delay"s); - assert(ret.value() == "HelloService::hello_with_delay"s); + // TODO: fix return error + // ret_void = co_await client.call(); + + // assert(ret.error().code.val() == 404); + // assert(ret.error().msg == "404 Not Found."); - ret = co_await client.call(); + // ret_void = co_await client.call(); - assert(ret.error().code.val() == 404); - assert(ret.error().msg == "404 Not Found."); + // assert(ret.error().code.val() == 404); ret = co_await client.call(); assert(ret.value() == "1"); diff --git a/src/coro_rpc/examples/base_examples/rpc_service.cpp b/src/coro_rpc/examples/base_examples/rpc_service.cpp index 5a59f1c49..a9ac63bc4 100644 --- a/src/coro_rpc/examples/base_examples/rpc_service.cpp +++ b/src/coro_rpc/examples/base_examples/rpc_service.cpp @@ -21,96 +21,83 @@ #include #include +#include "async_simple/coro/Lazy.h" +#include "async_simple/coro/Sleep.h" +#include "ylt/coro_io/client_pool.hpp" +#include "ylt/coro_io/coro_io.hpp" +#include "ylt/coro_rpc/impl/coro_rpc_client.hpp" #include "ylt/coro_rpc/impl/errno.h" +#include "ylt/coro_rpc/impl/expected.hpp" +#include "ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp" using namespace coro_rpc; +using namespace async_simple::coro; +using namespace std::chrono_literals; -std::string hello_world() { - ELOGV(INFO, "call helloworld"); - return "hello_world"; +std::string_view echo(std::string_view data) { + ELOGV(INFO, "call echo"); + return data; } -bool return_bool_hello_world() { return true; } - -int A_add_B(int a, int b) { - ELOGV(INFO, "call A+B"); - return a + b; -} - -void echo_with_attachment(coro_rpc::context conn) { - ELOGV(INFO, "call echo_with_attachment"); - std::string str = conn.get_context()->release_request_attachment(); - conn.get_context()->set_response_attachment(std::move(str)); - conn.response_msg(); +Lazy coroutine_echo(std::string_view data) { + ELOGV(INFO, "call coroutine_echo"); + co_await coro_io::sleep_for(1s); + co_return data; } -void echo_with_attachment2(coro_rpc::context conn) { - ELOGV(INFO, "call echo_with_attachment2"); - std::string_view str = conn.get_context()->get_request_attachment(); - // The live time of attachment is same as coro_rpc::context - conn.get_context()->set_response_attachment([str, conn] { - return str; - }); - conn.response_msg(); +void async_echo_by_callback(coro_rpc::context conn, std::string_view/*rpc request data here*/ data) { + ELOGV(INFO, "call async_echo_by_callback"); + /* rpc function runs in global io thread pool */ + coro_io::post([conn,data] () mutable { + /* send work to global non-io thread pool */ + auto *ctx = conn.get_context(); + conn.response_msg(data); /*response here*/ + }).start([](auto&&){}); } -std::string echo(std::string_view sv) { return std::string{sv}; } - -async_simple::coro::Lazy coro_echo(std::string_view sv) { - ELOGV(INFO, "call coro_echo"); - co_await coro_io::sleep_for(std::chrono::milliseconds(100)); - ELOGV(INFO, "after sleep for a while"); - co_return std::string{sv}; +Lazy async_echo_by_coroutine(std::string_view sv) { + ELOGV(INFO, "call async_echo_by_coroutine"); + co_await coro_io::sleep_for(std::chrono::milliseconds(100)); //sleeping + co_return sv; } -void hello_with_delay(context conn, - std::string hello) { - ELOGV(INFO, "call HelloServer hello_with_delay"); - // create a new thread - std::thread([conn = std::move(conn), hello = std::move(hello)]() mutable { - // do some heavy work in this thread that won't block the io-thread, - std::cout << "running heavy work..." << std::endl; - std::this_thread::sleep_for(std::chrono::seconds{1}); - // Remember response before connection destruction! Or the connect will - // be closed. - conn.response_msg(hello); - }).detach(); +Lazy echo_with_attachment() { + ELOGV(INFO, "call echo_with_attachment"); + auto ctx=co_await coro_rpc::get_context(); + ctx->set_response_attachment(ctx->get_request_attachment()); /*zero-copy by string_view*/ } -async_simple::coro::Lazy nested_echo(std::string_view sv) { +Lazy nested_echo(std::string_view sv) { ELOGV(INFO, "start nested echo"); - coro_rpc::coro_rpc_client client(co_await coro_io::get_current_executor()); - [[maybe_unused]] auto ec = co_await client.connect("127.0.0.1", "8802"); - assert(!ec); + /*get a client by global client pool*/ + auto client=coro_io::g_clients_pool().at("127.0.0.1:8802"); + assert(client!=nullptr); ELOGV(INFO, "connect another server"); - auto ret = co_await client.call(sv); - assert(ret.value() == sv); - ELOGV(INFO, "get echo result from another server"); - co_return std::string{sv}; + auto ret = co_await client->send_request([sv](coro_rpc_client & client) { + return client.call(sv); + }); + co_return ret.value().value(); } -std::string HelloService::hello() { +std::string_view HelloService::hello() { ELOGV(INFO, "call HelloServer::hello"); return "HelloService::hello"; } -void HelloService::hello_with_delay( - coro_rpc::context conn, std::string hello) { - ELOGV(INFO, "call HelloServer::hello_with_delay"); - std::thread([conn = std::move(conn), hello = std::move(hello)]() mutable { - conn.response_msg("HelloService::hello_with_delay"); - }).detach(); - return; +void return_error_by_context(coro_rpc::context conn) { + conn.response_error(coro_rpc::err_code{404}, "404 Not Found."); } -void return_error(coro_rpc::context conn) { - conn.response_error(coro_rpc::err_code{404}, "404 Not Found."); +void return_error_by_exception() { + throw coro_rpc::err_code{404}; } -void rpc_with_state_by_tag(coro_rpc::context conn) { - if (!conn.get_context()->tag().has_value()) { - conn.get_context()->tag() = uint64_t{0}; + +Lazy rpc_with_state_by_tag() { + auto *ctx = co_await coro_rpc::get_context(); + if (!ctx->tag().has_value()) { + ctx->tag() = std::uint64_t{0}; } - auto &cnter = std::any_cast(conn.get_context()->tag()); + auto &cnter = std::any_cast(ctx->tag()); ELOGV(INFO, "call count: %d", ++cnter); - conn.response_msg(std::to_string(cnter)); + co_return std::to_string(cnter); } \ No newline at end of file diff --git a/src/coro_rpc/examples/base_examples/rpc_service.h b/src/coro_rpc/examples/base_examples/rpc_service.h index 1198009b7..3ed6668f2 100644 --- a/src/coro_rpc/examples/base_examples/rpc_service.h +++ b/src/coro_rpc/examples/base_examples/rpc_service.h @@ -20,21 +20,17 @@ #include #include -std::string hello_world(); -bool return_bool_hello_world(); -int A_add_B(int a, int b); -void hello_with_delay(coro_rpc::context conn, std::string hello); -std::string echo(std::string_view sv); -void echo_with_attachment(coro_rpc::context conn); -void echo_with_attachment2(coro_rpc::context conn); -void return_error(coro_rpc::context conn); -void rpc_with_state_by_tag(coro_rpc::context conn); -async_simple::coro::Lazy coro_echo(std::string_view sv); -async_simple::coro::Lazy nested_echo(std::string_view sv); +std::string_view echo(std::string_view data); +async_simple::coro::Lazy coroutine_echo(std::string_view data); +void async_echo_by_callback(coro_rpc::context conn, std::string_view/*rpc request data here*/ data); +async_simple::coro::Lazy async_echo_by_coroutine(std::string_view sv); +async_simple::coro::Lazy echo_with_attachment(); +async_simple::coro::Lazy nested_echo(std::string_view sv); +void return_error_by_context(coro_rpc::context conn); +void return_error_by_exception(); class HelloService { public: - std::string hello(); - void hello_with_delay(coro_rpc::context conn, std::string hello); + std::string_view hello(); }; - +async_simple::coro::Lazy rpc_with_state_by_tag(); #endif // CORO_RPC_RPC_API_HPP diff --git a/src/coro_rpc/examples/base_examples/server.cpp b/src/coro_rpc/examples/base_examples/server.cpp index e6cedb2dc..32cd1de0a 100644 --- a/src/coro_rpc/examples/base_examples/server.cpp +++ b/src/coro_rpc/examples/base_examples/server.cpp @@ -26,18 +26,14 @@ int main() { coro_rpc_server server2{/*thread=*/1, /*port=*/8802}; - server.register_handler(); // regist normal function for rpc - server.register_handler(); + server.register_handler(); // regist member function for rpc HelloService hello_service; server - .register_handler<&HelloService::hello, &HelloService::hello_with_delay>( + .register_handler<&HelloService::hello>( &hello_service); server2.register_handler(); From 97bc6caf23581c932fa0572a4f5b5b03bda0b183 Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Tue, 2 Apr 2024 11:42:55 +0800 Subject: [PATCH 09/19] add test for async --- include/ylt/coro_rpc/impl/coro_connection.hpp | 8 +++--- src/coro_rpc/benchmark/api/rpc_functions.hpp | 28 +++++++++++-------- src/coro_rpc/benchmark/data_gen.cpp | 7 ++++- src/coro_rpc/benchmark/server.hpp | 2 +- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/include/ylt/coro_rpc/impl/coro_connection.hpp b/include/ylt/coro_rpc/impl/coro_connection.hpp index 2d087d9f7..5e427271c 100644 --- a/include/ylt/coro_rpc/impl/coro_connection.hpp +++ b/include/ylt/coro_rpc/impl/coro_connection.hpp @@ -254,11 +254,10 @@ class coro_connection : public std::enable_shared_from_this { set_rpc_return_by_callback(); router .route_coro(coro_handler, payload, - serialize_proto.value(), key) + serialize_proto.value(), key) .via(executor_).setLazyLocal((void*)context_info.get()) - .start([context_info](auto &&result) mutable { - asio::dispatch([context_info=std::move(context_info),result = std::move(result)]() mutable { - coro_rpc::errc resp_err; + .start([context_info,this](auto &&result) mutable { + coro_rpc::errc resp_err; std::string resp_buf; if (result.hasError()) AS_UNLIKELY { @@ -268,6 +267,7 @@ class coro_connection : public std::enable_shared_from_this { else { std::tie(resp_err, resp_buf) = result.value(); } + executor_->schedule([context_info=std::move(context_info), resp_err = std::move(resp_err),resp_buf=std::move(resp_buf)]() mutable { context_info->conn_->template direct_response_msg( resp_err, resp_buf, context_info->req_head_,std::move(context_info->resp_attachment_)); }); diff --git a/src/coro_rpc/benchmark/api/rpc_functions.hpp b/src/coro_rpc/benchmark/api/rpc_functions.hpp index 5566b2709..dae8d9e3d 100644 --- a/src/coro_rpc/benchmark/api/rpc_functions.hpp +++ b/src/coro_rpc/benchmark/api/rpc_functions.hpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -24,20 +25,25 @@ #include "Monster.h" #include "Rect.h" #include "ValidateRequest.h" +#include "ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp" inline coro_io::io_context_pool pool(std::thread::hardware_concurrency()); - -inline std::string echo_4B(const std::string &str) { return str; } -inline std::string echo_50B(const std::string &str) { return str; } -inline std::string echo_100B(const std::string &str) { return str; } -inline std::string echo_500B(const std::string &str) { return str; } -inline std::string echo_1KB(const std::string &str) { return str; } -inline std::string echo_5KB(const std::string &str) { return str; } -inline std::string echo_10KB(const std::string &str) { return str; } +inline async_simple::coro::Lazy coroutine_async_echo(std::string_view str) { co_return str;} +inline void callback_async_echo(coro_rpc::context conn,std::string_view str) { + conn.response_msg(str); + return; +} +inline std::string_view echo_4B(std::string_view str) { return str; } +inline std::string_view echo_50B(std::string_view str) { return str; } +inline std::string_view echo_100B(std::string_view str) { return str; } +inline std::string_view echo_500B(std::string_view str) { return str; } +inline std::string_view echo_1KB(std::string_view str) { return str; } +inline std::string_view echo_5KB(std::string_view str) { return str; } +inline std::string_view echo_10KB(std::string_view str) { return str; } inline std::vector array_1K_int(std::vector ar) { return ar; } -inline std::vector array_1K_str_4B(std::vector ar) { +inline std::vector array_1K_str_4B(std::vector ar) { return ar; } @@ -63,8 +69,8 @@ inline void heavy_calculate(coro_rpc::context conn, int a) { }); return; } - -inline std::string download_10KB(int a) { return std::string(10000, 'A'); } +std::string s(10000, 'A'); +inline std::string_view download_10KB(int a) { return std::string_view{s}; } inline void long_tail_heavy_calculate(coro_rpc::context conn, int a) { static std::atomic g_index = 0; diff --git a/src/coro_rpc/benchmark/data_gen.cpp b/src/coro_rpc/benchmark/data_gen.cpp index 25e318bba..847087e89 100644 --- a/src/coro_rpc/benchmark/data_gen.cpp +++ b/src/coro_rpc/benchmark/data_gen.cpp @@ -60,7 +60,7 @@ int main() { std::filesystem::create_directories(coro_rpc::benchmark_file_path); syncAwait(client.call(std::vector(1000, 42))); syncAwait( - client.call(std::vector(1000, std::string{4, 'A'}))); + client.call(std::vector(1000, std::string_view{"AAAA"}))); syncAwait(client.call( std::vector(1000, rect{.p1 = {1.2, 3.4}, .p2 = {2.5, 4.6}}))); syncAwait( @@ -111,6 +111,11 @@ int main() { syncAwait(client.call(42)); syncAwait(client.call(42)); + coro_rpc::benchmark_file_path = "./test_data/async_test/"; + std::filesystem::create_directories(coro_rpc::benchmark_file_path); + syncAwait(client.call("echo")); + syncAwait(client.call("echo")); + server.stop(); started->wait(); diff --git a/src/coro_rpc/benchmark/server.hpp b/src/coro_rpc/benchmark/server.hpp index 046c7abf0..219958b9a 100644 --- a/src/coro_rpc/benchmark/server.hpp +++ b/src/coro_rpc/benchmark/server.hpp @@ -24,7 +24,7 @@ inline void register_handlers(coro_rpc::coro_rpc_server& server) { echo_4B, echo_100B, echo_500B, echo_1KB, echo_5KB, echo_10KB, async_io, block_io, heavy_calculate, long_tail_async_io, long_tail_block_io, long_tail_heavy_calculate, array_1K_int, array_1K_str_4B, array_1K_rect, - monsterFunc, ValidateRequestFunc, download_10KB>(); + monsterFunc, ValidateRequestFunc, download_10KB,callback_async_echo,coroutine_async_echo>(); server.register_handler< many_argument>(); From 94454035d3b885ea4ad1e0aeff9ed7a9d4ca3e24 Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Tue, 2 Apr 2024 13:26:21 +0800 Subject: [PATCH 10/19] [coro_rpc] refact error handle --- include/ylt/coro_rpc/impl/coro_connection.hpp | 32 +++--- include/ylt/coro_rpc/impl/coro_rpc_client.hpp | 2 +- include/ylt/coro_rpc/impl/coro_rpc_server.hpp | 6 +- include/ylt/coro_rpc/impl/errno.h | 39 +++---- include/ylt/coro_rpc/impl/router.hpp | 101 +++++------------- include/ylt/coro_rpc/impl/rpc_execute.hpp | 64 ++++++----- src/coro_rpc/tests/rpc_api.cpp | 4 +- src/coro_rpc/tests/test_coro_rpc_server.cpp | 4 +- src/coro_rpc/tests/test_router.cpp | 26 ++--- 9 files changed, 118 insertions(+), 160 deletions(-) diff --git a/include/ylt/coro_rpc/impl/coro_connection.hpp b/include/ylt/coro_rpc/impl/coro_connection.hpp index 5e427271c..483b0d9e3 100644 --- a/include/ylt/coro_rpc/impl/coro_connection.hpp +++ b/include/ylt/coro_rpc/impl/coro_connection.hpp @@ -254,27 +254,21 @@ class coro_connection : public std::enable_shared_from_this { set_rpc_return_by_callback(); router .route_coro(coro_handler, payload, - serialize_proto.value(), key) - .via(executor_).setLazyLocal((void*)context_info.get()) - .start([context_info,this](auto &&result) mutable { - coro_rpc::errc resp_err; - std::string resp_buf; - if (result.hasError()) - AS_UNLIKELY { - resp_err = coro_rpc::errc::interrupted; - resp_buf = "unknonw error"; - } - else { - std::tie(resp_err, resp_buf) = result.value(); - } - executor_->schedule([context_info=std::move(context_info), resp_err = std::move(resp_err),resp_buf=std::move(resp_buf)]() mutable { + serialize_proto.value(), key) + .via(executor_).setLazyLocal((void*)context_info.get()) + .start([key,&router,context_info](auto &&result) mutable { + std::pair &ret = result.value(); + if (ret.first) AS_UNLIKELY { + ELOGW<<"rpc error in function:"<conn_->get_executor()->schedule([context_info=std::move(context_info), ret = std::move(ret)]() mutable { context_info->conn_->template direct_response_msg( - resp_err, resp_buf, context_info->req_head_,std::move(context_info->resp_attachment_)); + ret.first, ret.second, context_info->req_head_,std::move(context_info->resp_attachment_)); }); }); } else { - auto [resp_err, resp_buf] = router.route(handler, payload, context_info, + auto &&[resp_err, resp_buf] = router.route(handler, payload, context_info, serialize_proto.value(), key); if (is_rpc_return_by_callback) { if (!resp_err) { @@ -315,9 +309,9 @@ class coro_connection : public std::enable_shared_from_this { * @param ret object of message type */ template - void direct_response_msg(coro_rpc::errc &resp_err, std::string &resp_buf,const typename rpc_protocol::req_header &req_head, std::function&& attachment=[]{return std::string_view();}) { + void direct_response_msg(coro_rpc::err_code &resp_err, std::string &resp_buf,const typename rpc_protocol::req_header &req_head, std::function&& attachment=[]{return std::string_view();}) { std::string resp_error_msg; - if (!!resp_err) { + if (resp_err) { resp_error_msg = std::move(resp_buf); resp_buf = {}; ELOGV(WARNING, "rpc route/execute error, error msg: %s", resp_error_msg.data()); @@ -396,7 +390,7 @@ class coro_connection : public std::enable_shared_from_this { std::any &tag() { return tag_; } const std::any &tag() const { return tag_; } - auto &get_executor() { return *executor_; } + auto get_executor() { return executor_; } asio::ip::tcp::endpoint get_remote_endpoint() {return socket_.remote_endpoint();} diff --git a/include/ylt/coro_rpc/impl/coro_rpc_client.hpp b/include/ylt/coro_rpc/impl/coro_rpc_client.hpp index 44d58252f..481df999b 100644 --- a/include/ylt/coro_rpc/impl/coro_rpc_client.hpp +++ b/include/ylt/coro_rpc/impl/coro_rpc_client.hpp @@ -767,7 +767,7 @@ class coro_rpc_client { } error_happen = true; // deserialize failed. - err = {errc::invalid_argument, "failed to deserialize rpc return value"}; + err = {errc::invalid_rpc_result, "failed to deserialize rpc return value"}; return rpc_result{unexpect_t{}, std::move(err)}; } diff --git a/include/ylt/coro_rpc/impl/coro_rpc_server.hpp b/include/ylt/coro_rpc/impl/coro_rpc_server.hpp index 6296036b2..6fef248b6 100644 --- a/include/ylt/coro_rpc/impl/coro_rpc_server.hpp +++ b/include/ylt/coro_rpc/impl/coro_rpc_server.hpp @@ -300,7 +300,7 @@ class coro_rpc_server_base { ec.message().data()); acceptor_.cancel(ec); acceptor_.close(ec); - return coro_rpc::errc::address_in_use; + return coro_rpc::errc::address_in_used; } #ifdef _MSC_VER acceptor_.set_option(tcp::acceptor::reuse_address(true)); @@ -311,7 +311,7 @@ class coro_rpc_server_base { if (ec) { ELOGV(ERROR, "get local endpoint port %d error : %s", port_.load(), ec.message().data()); - return coro_rpc::errc::address_in_use; + return coro_rpc::errc::address_in_used; } port_ = end_point.port(); @@ -360,7 +360,7 @@ class coro_rpc_server_base { std::unique_lock lock(conns_mtx_); conns_.emplace(conn_id, conn); } - start_one(conn).via(&conn->get_executor()).detach(); + start_one(conn).via(conn->get_executor()).detach(); } } diff --git a/include/ylt/coro_rpc/impl/errno.h b/include/ylt/coro_rpc/impl/errno.h index d785b30db..1bc2de612 100644 --- a/include/ylt/coro_rpc/impl/errno.h +++ b/include/ylt/coro_rpc/impl/errno.h @@ -23,44 +23,47 @@ enum class errc : uint16_t { io_error, not_connected, timed_out, - invalid_argument, - address_in_use, + invalid_rpc_arguments, + address_in_used, operation_canceled, - interrupted, + rpc_throw_exception, function_not_registered, protocol_error, unknown_protocol_version, message_too_large, server_has_ran, + invalid_rpc_result, }; inline constexpr std::string_view make_error_message(errc ec) noexcept { switch (ec) { case errc::ok: return "ok"; case errc::io_error: - return "io_error"; + return "io error"; case errc::not_connected: - return "not_connected"; + return "not connected"; case errc::timed_out: - return "timed_out"; - case errc::invalid_argument: - return "invalid_argument"; - case errc::address_in_use: - return "address_in_use"; + return "time out"; + case errc::invalid_rpc_arguments: + return "invalid rpc arg"; + case errc::address_in_used: + return "address in used"; case errc::operation_canceled: - return "operation_canceled"; - case errc::interrupted: - return "interrupted"; + return "operation canceled"; + case errc::rpc_throw_exception: + return "rpc throw exception"; case errc::function_not_registered: - return "function_not_registered"; + return "function not registered"; case errc::protocol_error: - return "protocol_error"; + return "protocol error"; case errc::message_too_large: - return "message_too_large"; + return "message too large"; case errc::server_has_ran: - return "server_has_ran"; + return "server has ran"; + case errc::invalid_rpc_result: + return "invalid rpc result"; default: - return "unknown_user-defined_error"; + return "unknown user-defined error"; } } struct err_code { diff --git a/include/ylt/coro_rpc/impl/router.hpp b/include/ylt/coro_rpc/impl/router.hpp index f94fcdc90..39863454a 100644 --- a/include/ylt/coro_rpc/impl/router.hpp +++ b/include/ylt/coro_rpc/impl/router.hpp @@ -30,6 +30,7 @@ #include #include "rpc_execute.hpp" +#include "ylt/coro_rpc/impl/expected.hpp" namespace coro_rpc { @@ -46,21 +47,20 @@ template typename map_t = std::unordered_map> class router { - using router_handler_t = std::function( + + +public: + using router_handler_t = std::function( std::string_view, rpc_context &context_info, typename rpc_protocol::supported_serialize_protocols protocols)>; using coro_router_handler_t = - std::function>( + std::function>( std::string_view, typename rpc_protocol::supported_serialize_protocols protocols)>; using route_key = typename rpc_protocol::route_key_t; - std::unordered_map handlers_; - std::unordered_map coro_handlers_; - std::unordered_map id2name_; - private: const std::string &get_name(const route_key &key) { static std::string empty_string; if (auto it = id2name_.find(key); it != id2name_.end()) { @@ -69,6 +69,11 @@ class router { else return empty_string; } + private: + + std::unordered_map handlers_; + std::unordered_map coro_handlers_; + std::unordered_map id2name_; // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100611 // We use this struct instead of lambda for workaround @@ -77,7 +82,7 @@ class router { std::string_view data; Self *self; template - async_simple::coro::Lazy> operator()( + async_simple::coro::Lazy> operator()( const serialize_protocol &) { return internal::execute_coro( data, self); @@ -88,7 +93,7 @@ class router { struct execute_visitor { std::string_view data; template - async_simple::coro::Lazy> operator()( + async_simple::coro::Lazy> operator() ( const serialize_protocol &) { return internal::execute_coro( data); @@ -230,7 +235,7 @@ class router { return nullptr; } - async_simple::coro::Lazy> route_coro( + async_simple::coro::Lazy> route_coro( auto handler, std::string_view data, typename rpc_protocol::supported_serialize_protocols protocols, const typename rpc_protocol::route_key_t &route_key) { @@ -243,52 +248,25 @@ class router { #endif // clang-format off - auto res = co_await (*handler)(data, protocols); - // clang-format on - if (res.has_value()) - AS_LIKELY { - co_return std::make_pair(coro_rpc::errc{}, - std::move(res.value())); - } - else { // deserialize failed - ELOGV(ERROR, "payload deserialize failed in rpc function: %s", - get_name(route_key).data()); - co_return std::make_pair(coro_rpc::errc::invalid_argument, - "invalid rpc function arguments"s); - } + co_return co_await (*handler)(data, protocols); } catch (coro_rpc::errc ec) { - auto msg = coro_rpc::make_error_message(ec); - ELOGI<< - "user return coro_rpc::errc, message:"<(ec) <<", rpc " - "function name:"<< get_name(route_key); - co_return std::make_pair(ec, std::string{msg}); + co_return std::make_pair(err_code{ec}, std::string{coro_rpc::make_error_message(ec)}); } catch (coro_rpc::err_code ec) { - ELOGI<< - "user return coro_rpc::err_code, message:"< route( + std::pair route( auto handler, std::string_view data, rpc_context &context_info, typename rpc_protocol::supported_serialize_protocols protocols, @@ -300,46 +278,23 @@ class router { #ifndef NDEBUG ELOGV(INFO, "route function name: %s", get_name(route_key).data()); #endif - auto res = (*handler)(data, context_info, protocols); - if (res.has_value()) - AS_LIKELY { - return std::make_pair(coro_rpc::errc{}, std::move(res.value())); - } - else { // deserialize failed - ELOGV(ERROR, "payload deserialize failed in rpc function: %s", - get_name(route_key).data()); - return std::make_pair(coro_rpc::errc::invalid_argument, - "invalid rpc function arguments"s); - } + return (*handler)(data, context_info, protocols); } catch (coro_rpc::errc ec) { auto msg = coro_rpc::make_error_message(ec); - ELOGI<< - "user return coro_rpc::errc, message:"<(ec) <<", rpc " - "function name:"<< get_name(route_key); - return std::make_pair(ec, std::string{msg}); + return std::make_pair(err_code{ec}, std::string{msg}); } catch (coro_rpc::err_code ec) { - ELOGI<< - "user return coro_rpc::err_code, message:"<>; using rpc_conn = std::shared_ptr; template -inline std::optional execute( +inline std::pair execute( std::string_view data, rpc_context &context_info, Self *self = nullptr) { + using namespace std::string_literals; using T = decltype(func); using param_type = util::function_parameters_t; using return_type = util::function_return_type_t; @@ -76,8 +79,9 @@ inline std::optional execute( is_ok = serialize_proto::deserialize_to(args, data); } - if (!is_ok) - AS_UNLIKELY { return std::nullopt; } + if (!is_ok) + AS_UNLIKELY { return std::pair{err_code{errc::invalid_rpc_arguments}, + "invalid rpc arg"s}; } if constexpr (std::is_void_v) { if constexpr (std::is_void_v) { @@ -95,35 +99,34 @@ inline std::optional execute( } } else { - auto &o = *self; if constexpr (has_coro_conn_v) { - // call void o.func(coro_conn, args...) + // call void self->func(coro_conn, args...) std::apply(func, std::tuple_cat( std::forward_as_tuple( - o, context_base( + *self, context_base( context_info)), std::move(args))); } else { - // call void o.func(args...) + // call void self->func(args...) std::apply(func, - std::tuple_cat(std::forward_as_tuple(o), std::move(args))); + std::tuple_cat(std::forward_as_tuple(*self), std::move(args))); } } + return std::pair{err_code{},serialize_proto::serialize()}; } else { if constexpr (std::is_void_v) { // call return_type func(args...) - return serialize_proto::serialize(std::apply(func, std::move(args))); + return std::pair{err_code{},serialize_proto::serialize(std::apply(func, std::move(args)))}; } else { - auto &o = *self; - // call return_type o.func(args...) + // call return_type self->func(args...) - return serialize_proto::serialize(std::apply( - func, std::tuple_cat(std::forward_as_tuple(o), std::move(args)))); + return std::pair{err_code{},serialize_proto::serialize(std::apply( + func, std::tuple_cat(std::forward_as_tuple(*self), std::move(args))))}; } } } @@ -135,24 +138,25 @@ inline std::optional execute( else { (self->*func)(); } + return std::pair{err_code{},serialize_proto::serialize()}; } else { if constexpr (std::is_void_v) { - return serialize_proto::serialize(func()); + return std::pair{err_code{},serialize_proto::serialize(func())}; } else { - return serialize_proto::serialize((self->*func)()); + return std::pair{err_code{},serialize_proto::serialize((self->*func)())}; } } } - return serialize_proto::serialize(); } template -inline async_simple::coro::Lazy> execute_coro( +inline async_simple::coro::Lazy> execute_coro( std::string_view data, Self *self = nullptr) { + using namespace std::string_literals; using T = decltype(func); using param_type = util::function_parameters_t; using return_type = typename get_type_t< @@ -169,29 +173,31 @@ inline async_simple::coro::Lazy> execute_coro( if constexpr (size > 0) { is_ok = serialize_proto::deserialize_to(args, data); } + if (!is_ok) + AS_UNLIKELY { co_return std::make_pair(coro_rpc::errc::invalid_rpc_arguments, + "invalid rpc function arguments"s); } if constexpr (std::is_void_v) { if constexpr (std::is_void_v) { // call void func(args...) co_await std::apply(func, std::move(args)); } else { - auto &o = *self; - // call void o.func(args...) + // call void self->func(args...) co_await std::apply( - func, std::tuple_cat(std::forward_as_tuple(o), std::move(args))); + func, std::tuple_cat(std::forward_as_tuple(*self), std::move(args))); } + co_return std::pair{err_code{},serialize_proto::serialize()}; } else { if constexpr (std::is_void_v) { // call return_type func(args...) - co_return serialize_proto::serialize( - co_await std::apply(func, std::move(args))); + co_return std::pair{err_code{},serialize_proto::serialize( + co_await std::apply(func, std::move(args)))}; } else { - auto &o = *self; - // call return_type o.func(args...) - co_return serialize_proto::serialize(co_await std::apply( - func, std::tuple_cat(std::forward_as_tuple(o), std::move(args)))); + // call return_type self->func(args...) + co_return std::pair{err_code{},serialize_proto::serialize(co_await std::apply( + func, std::tuple_cat(std::forward_as_tuple(*self), std::move(args))))}; } } } @@ -205,18 +211,18 @@ inline async_simple::coro::Lazy> execute_coro( co_await (self->*func)(); // clang-format on } + co_return std::pair{err_code{},serialize_proto::serialize()}; } else { if constexpr (std::is_void_v) { - co_return serialize_proto::serialize(co_await func()); + co_return std::pair{err_code{},serialize_proto::serialize(co_await func())}; } else { // clang-format off - co_return serialize_proto::serialize(co_await (self->*func)()); + co_return std::pair{err_code{},serialize_proto::serialize(co_await (self->*func)())}; // clang-format on } } } - co_return serialize_proto::serialize(); } } // namespace coro_rpc::internal \ No newline at end of file diff --git a/src/coro_rpc/tests/rpc_api.cpp b/src/coro_rpc/tests/rpc_api.cpp index 412f2b617..b1f101371 100644 --- a/src/coro_rpc/tests/rpc_api.cpp +++ b/src/coro_rpc/tests/rpc_api.cpp @@ -63,7 +63,7 @@ void test_context(coro_rpc::context conn) { std::string sv{ctx->get_request_attachment()}; auto str = ctx->release_request_attachment(); if (sv!=str) { - conn.response_error(coro_rpc::errc::interrupted); + conn.response_error(coro_rpc::errc::rpc_throw_exception); ctx->close(); return; } @@ -89,7 +89,7 @@ Lazy test_lazy_context() { auto str = ctx->release_request_attachment(); if (sv!=str) { ctx->close(); - throw coro_rpc::errc::interrupted; + throw coro_rpc::errc::rpc_throw_exception; co_return; } ctx->set_response_attachment(std::move(str)); diff --git a/src/coro_rpc/tests/test_coro_rpc_server.cpp b/src/coro_rpc/tests/test_coro_rpc_server.cpp index 73e35ce98..bbec5f3f7 100644 --- a/src/coro_rpc/tests/test_coro_rpc_server.cpp +++ b/src/coro_rpc/tests/test_coro_rpc_server.cpp @@ -168,7 +168,7 @@ struct CoroServerTester : ServerTester { auto new_server = coro_rpc_server(2, std::stoi(this->port_)); auto ec = new_server.async_start(); REQUIRE(!ec); - REQUIRE_MESSAGE(ec.error() == coro_rpc::errc::address_in_use, + REQUIRE_MESSAGE(ec.error() == coro_rpc::errc::address_in_used, ec.error().message()); } ELOGV(INFO, "OH NO"); @@ -178,7 +178,7 @@ struct CoroServerTester : ServerTester { ELOGV(INFO, "run %s, client_id %d", __func__, client->get_client_id()); auto ret = this->call(client); CHECK_MESSAGE( - ret.error().code == coro_rpc::errc::invalid_argument, + ret.error().code == coro_rpc::errc::invalid_rpc_result, std::to_string(client->get_client_id()).append(ret.error().msg)); g_action = {}; } diff --git a/src/coro_rpc/tests/test_router.cpp b/src/coro_rpc/tests/test_router.cpp index 152f1944d..0f8a87f08 100644 --- a/src/coro_rpc/tests/test_router.cpp +++ b/src/coro_rpc/tests/test_router.cpp @@ -95,7 +95,7 @@ get_result(const auto &pair) { } } // deserialize failed. - err = {coro_rpc::errc::invalid_argument, + err = {coro_rpc::errc::invalid_rpc_arguments, "failed to deserialize rpc return value"}; return return_type{unexpect_t{}, std::move(err)}; } @@ -259,16 +259,16 @@ TEST_CASE("testing invalid arguments") { CHECK(!pair.first); pair = test_route<&test_class::plus_one>(ctx); - CHECK(pair.first == coro_rpc::errc::invalid_argument); + CHECK(pair.first == coro_rpc::errc::invalid_rpc_arguments); pair = test_route<&test_class::plus_one>(ctx, 42, 42); - CHECK(pair.first == coro_rpc::errc::invalid_argument); + CHECK(pair.first == coro_rpc::errc::invalid_rpc_arguments); pair = test_route<&test_class::plus_one>(ctx, "test"); - CHECK(pair.first == coro_rpc::errc::invalid_argument); + CHECK(pair.first == coro_rpc::errc::invalid_rpc_arguments); pair = test_route<&test_class::get_str>(ctx, "test"); - CHECK(pair.first == coro_rpc::errc::invalid_argument); + CHECK(pair.first == coro_rpc::errc::invalid_rpc_arguments); pair = test_route<&test_class::get_str>(ctx, std::string("test")); CHECK(!pair.first); @@ -281,7 +281,7 @@ TEST_CASE("testing invalid arguments") { router.register_handler(); pair = test_route(ctx, "test"); - CHECK(pair.first == coro_rpc::errc::invalid_argument); + CHECK(pair.first == coro_rpc::errc::invalid_rpc_arguments); pair = test_route(ctx, std::string("test")); CHECK(!pair.first); @@ -289,16 +289,16 @@ TEST_CASE("testing invalid arguments") { CHECK(r.value() == "test"); pair = test_route(ctx, 42, 42); - CHECK(pair.first == coro_rpc::errc::invalid_argument); + CHECK(pair.first == coro_rpc::errc::invalid_rpc_arguments); pair = test_route(ctx); - CHECK(pair.first == coro_rpc::errc::invalid_argument); + CHECK(pair.first == coro_rpc::errc::invalid_rpc_arguments); pair = test_route(ctx, 42); CHECK(!pair.first); pair = test_route(ctx, std::string("invalid arguments")); - CHECK(pair.first == coro_rpc::errc::invalid_argument); + CHECK(pair.first == coro_rpc::errc::invalid_rpc_arguments); // register_handler(); // test_route(ctx, 42); // will crash @@ -311,12 +311,12 @@ TEST_CASE("testing invalid buffer") { g_head_offset = 2; pair = test_route(ctx, 42); - CHECK(pair.first == coro_rpc::errc::invalid_argument); + CHECK(pair.first == coro_rpc::errc::invalid_rpc_arguments); g_head_offset = 0; g_tail_offset = 2; pair = test_route(ctx, 42); - CHECK(pair.first == coro_rpc::errc::invalid_argument); + CHECK(pair.first == coro_rpc::errc::invalid_rpc_arguments); g_tail_offset = 0; } @@ -329,12 +329,12 @@ TEST_CASE("testing exceptions") { std::pair pair{}; pair = test_route(ctx); - CHECK(pair.first == coro_rpc::errc::interrupted); + CHECK(pair.first == coro_rpc::errc::rpc_throw_exception); auto r = get_result(pair); std::cout << r.error().msg << "\n"; pair = test_route(ctx); - CHECK(pair.first == coro_rpc::errc::interrupted); + CHECK(pair.first == coro_rpc::errc::rpc_throw_exception); r = get_result(pair); std::cout << r.error().msg << "\n"; } From 1c34e23aef6972ae668ed504f48ed3071cd1277c Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Tue, 2 Apr 2024 15:43:37 +0800 Subject: [PATCH 11/19] [coro_rpc] context support get_rpc_function_name. add log when rpc error happened. --- include/ylt/coro_rpc/impl/context.hpp | 2 + include/ylt/coro_rpc/impl/coro_connection.hpp | 52 +++++++++++-------- src/coro_rpc/tests/test_router.cpp | 2 +- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/include/ylt/coro_rpc/impl/context.hpp b/include/ylt/coro_rpc/impl/context.hpp index 76febdf6a..fdf3ea132 100644 --- a/include/ylt/coro_rpc/impl/context.hpp +++ b/include/ylt/coro_rpc/impl/context.hpp @@ -29,6 +29,7 @@ #include "coro_connection.hpp" #include "ylt/coro_rpc/impl/errno.h" #include "ylt/util/type_traits.h" +#include "ylt/util/utils.hpp" namespace coro_rpc { /*! @@ -78,6 +79,7 @@ class context_base { std::string_view error_msg) { if (!check_status()) AS_UNLIKELY { return; }; + ELOGI << "rpc error in function:" << self_->get_rpc_function_name() << ". error code:" << error_code.ec << ". message : "<< error_msg; self_->conn_->template response_error(error_code, error_msg, self_->req_head_); } diff --git a/include/ylt/coro_rpc/impl/coro_connection.hpp b/include/ylt/coro_rpc/impl/coro_connection.hpp index 483b0d9e3..58d704dcb 100644 --- a/include/ylt/coro_rpc/impl/coro_connection.hpp +++ b/include/ylt/coro_rpc/impl/coro_connection.hpp @@ -26,11 +26,14 @@ #include #include #include +#include #include #include +#include "async_simple/Common.h" #include "ylt/coro_io/coro_io.hpp" #include "ylt/coro_rpc/impl/errno.h" +#include "ylt/util/utils.hpp" #ifdef UNIT_TEST_INJECT #include "inject_action.hpp" #endif @@ -45,6 +48,8 @@ struct context_info_t { #ifndef CORO_RPC_TEST private: #endif + typename rpc_protocol::route_key_t key; + typename rpc_protocol::router& router; std::shared_ptr conn_; typename rpc_protocol::req_header req_head_; std::string req_body_; @@ -57,11 +62,11 @@ struct context_info_t { template friend class context_base; friend class coro_connection; - context_info_t(std::shared_ptr &&conn) - : conn_(std::move(conn)) {} - context_info_t(std::shared_ptr &&conn, + context_info_t(typename rpc_protocol::router& r,std::shared_ptr &&conn) + : router(r),conn_(std::move(conn)) {} + context_info_t(typename rpc_protocol::router& r,std::shared_ptr &&conn, std::string &&req_body_buf, std::string &&req_attachment_buf) - : conn_(std::move(conn)), + : router(r), conn_(std::move(conn)), req_body_(std::move(req_body_buf)), req_attachment_(std::move(req_attachment_buf)) {} uint64_t get_connection_id() noexcept; @@ -78,6 +83,9 @@ struct context_info_t { asio::ip::tcp::endpoint get_local_endpoint() const noexcept; asio::ip::tcp::endpoint get_remote_endpoint() const noexcept; uint64_t get_request_id() const noexcept; + std::string_view get_rpc_function_name() const { + return router.get_name(key); + } }; /*! @@ -168,7 +176,7 @@ class coro_connection : public std::enable_shared_from_this { async_simple::coro::Lazy start_impl( typename rpc_protocol::router &router, Socket &socket) noexcept { auto context_info = - std::make_shared>(shared_from_this()); + std::make_shared>(router,shared_from_this()); reset_timer(); while (true) { typename rpc_protocol::req_header req_head_tmp; @@ -201,17 +209,17 @@ class coro_connection : public std::enable_shared_from_this { #endif // try to reuse context - if (is_rpc_return_by_callback) { + if (is_rpc_return_by_callback_) { // cant reuse context,make shared new one - is_rpc_return_by_callback = false; + is_rpc_return_by_callback_ = false; if (context_info->status_ != context_status::finish_response) { // cant reuse buffer - context_info = std::make_shared>( + context_info = std::make_shared>(router, shared_from_this()); } else { // reuse string buffer - context_info = std::make_shared>( + context_info = std::make_shared>(router, shared_from_this(), std::move(context_info->req_body_), std::move(context_info->req_attachment_)); } @@ -219,6 +227,7 @@ class coro_connection : public std::enable_shared_from_this { auto &req_head = context_info->req_head_; auto &body = context_info->req_body_; auto &req_attachment = context_info->req_attachment_; + auto &key = context_info->key; req_head = std::move(req_head_tmp); auto serialize_proto = rpc_protocol::get_serialize_protocol(req_head); @@ -245,37 +254,38 @@ class coro_connection : public std::enable_shared_from_this { break; } - auto key = rpc_protocol::get_route_key(req_head); + key = rpc_protocol::get_route_key(req_head); auto handler = router.get_handler(key); ++delay_resp_cnt; if (!handler) { auto coro_handler = router.get_coro_handler(key); - set_rpc_return_by_callback(); router .route_coro(coro_handler, payload, serialize_proto.value(), key) .via(executor_).setLazyLocal((void*)context_info.get()) - .start([key,&router,context_info](auto &&result) mutable { + .start([context_info](auto &&result) mutable { std::pair &ret = result.value(); if (ret.first) AS_UNLIKELY { - ELOGW<<"rpc error in function:"<get_rpc_function_name() << ". error code:" << ret.first.ec << ". message : "<< ret.second; } - context_info->conn_->get_executor()->schedule([context_info=std::move(context_info), ret = std::move(ret)]() mutable { + auto executor = context_info->conn_->get_executor(); + executor->schedule([context_info=std::move(context_info), ret = std::move(ret)]() mutable { context_info->conn_->template direct_response_msg( - ret.first, ret.second, context_info->req_head_,std::move(context_info->resp_attachment_)); + ret.first, ret.second, context_info->req_head_,std::move(context_info->resp_attachment_)); + }); }); - }); } else { auto &&[resp_err, resp_buf] = router.route(handler, payload, context_info, serialize_proto.value(), key); - if (is_rpc_return_by_callback) { + if (is_rpc_return_by_callback_) { if (!resp_err) { continue; } else { - is_rpc_return_by_callback = false; + ELOGI << "rpc error in function:" << context_info->get_rpc_function_name() << ". error code:" << resp_err.ec << ". message : "<< resp_buf; + is_rpc_return_by_callback_ = false; } } #ifdef UNIT_TEST_INJECT @@ -354,7 +364,7 @@ class coro_connection : public std::enable_shared_from_this { .detach(); } - void set_rpc_return_by_callback() { is_rpc_return_by_callback = true; } + void set_rpc_return_by_callback() { is_rpc_return_by_callback_ = true; } /*! * Check the connection has closed or not @@ -543,7 +553,7 @@ class coro_connection : public std::enable_shared_from_this { std::deque< std::tuple>> write_queue_; - bool is_rpc_return_by_callback{false}; + bool is_rpc_return_by_callback_{false}; // if don't get any message in keep_alive_timeout_duration_, the connection // will be closed when enable_check_timeout_ is true. @@ -551,7 +561,7 @@ class coro_connection : public std::enable_shared_from_this { bool enable_check_timeout_{false}; asio::steady_timer timer_; std::atomic has_closed_{false}; - + QuitCallback quit_callback_{nullptr}; uint64_t conn_id_{0}; uint64_t delay_resp_cnt{0}; diff --git a/src/coro_rpc/tests/test_router.cpp b/src/coro_rpc/tests/test_router.cpp index 0f8a87f08..b53e5b930 100644 --- a/src/coro_rpc/tests/test_router.cpp +++ b/src/coro_rpc/tests/test_router.cpp @@ -167,7 +167,7 @@ void bar3(int val) { std::cout << "bar3 val=" << val << "\n"; } using namespace test_util; auto ctx = std::make_shared< - coro_rpc::context_info_t>(nullptr); + coro_rpc::context_info_t>(router,nullptr); struct person { int id; From 82916f57a74c99aa576573f3824a72dda0aca337 Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Tue, 2 Apr 2024 16:07:13 +0800 Subject: [PATCH 12/19] move rpc_error to better namespace. add support for rpc function throw rpc_error --- include/ylt/coro_rpc/impl/coro_rpc_client.hpp | 24 +++++++++---------- include/ylt/coro_rpc/impl/errno.h | 11 +++++++-- include/ylt/coro_rpc/impl/expected.hpp | 2 +- .../impl/protocol/coro_rpc_protocol.hpp | 10 +------- include/ylt/coro_rpc/impl/router.hpp | 5 ++++ src/coro_rpc/tests/rpc_api.cpp | 14 +++++++++++ src/coro_rpc/tests/rpc_api.hpp | 2 ++ src/coro_rpc/tests/test_coro_rpc_server.cpp | 18 +++++++++++++- src/coro_rpc/tests/test_router.cpp | 4 ++-- src/coro_rpc/tests/test_variadic.cpp | 1 - 10 files changed, 63 insertions(+), 28 deletions(-) diff --git a/include/ylt/coro_rpc/impl/coro_rpc_client.hpp b/include/ylt/coro_rpc/impl/coro_rpc_client.hpp index 481df999b..890ca1bdc 100644 --- a/include/ylt/coro_rpc/impl/coro_rpc_client.hpp +++ b/include/ylt/coro_rpc/impl/coro_rpc_client.hpp @@ -109,7 +109,7 @@ class coro_rpc_client { using coro_rpc_protocol = coro_rpc::protocol::coro_rpc_protocol; public: - const inline static coro_rpc_protocol::rpc_error connect_error = { + const inline static rpc_error connect_error = { errc::io_error, "client has been closed"}; struct config { uint32_t client_id = 0; @@ -289,7 +289,7 @@ class coro_rpc_client { ELOGV(ERROR, "client has been closed, please re-connect"); auto ret = rpc_result{ unexpect_t{}, - coro_rpc_protocol::rpc_error{ + rpc_error{ errc::io_error, "client has been closed, please re-connect"}}; co_return ret; } @@ -299,7 +299,7 @@ class coro_rpc_client { if (!ssl_init_ret_) { ret = rpc_result{ unexpect_t{}, - coro_rpc_protocol::rpc_error{ + rpc_error{ errc::not_connected, std::string{make_error_message(errc::not_connected)}}}; co_return ret; @@ -329,7 +329,7 @@ class coro_rpc_client { if (is_timeout_) { ret = rpc_result{ unexpect_t{}, - coro_rpc_protocol::rpc_error{errc::timed_out, "rpc call timed out"}}; + rpc_error{errc::timed_out, "rpc call timed out"}}; } #ifdef UNIT_TEST_INJECT @@ -543,7 +543,7 @@ class coro_rpc_client { if (buffer.empty()) { r = rpc_result{ unexpect_t{}, - coro_rpc_protocol::rpc_error{errc::message_too_large, + rpc_error{errc::message_too_large, "rpc body serialize size too big"}}; co_return r; } @@ -566,7 +566,7 @@ class coro_rpc_client { close(); r = rpc_result{ unexpect_t{}, - coro_rpc_protocol::rpc_error{errc::io_error, ret.first.message()}}; + rpc_error{errc::io_error, ret.first.message()}}; co_return r; } else if (g_action == @@ -578,7 +578,7 @@ class coro_rpc_client { close(); r = rpc_result{ unexpect_t{}, - coro_rpc_protocol::rpc_error{errc::io_error, ret.first.message()}}; + rpc_error{errc::io_error, ret.first.message()}}; co_return r; } else if (g_action == @@ -589,7 +589,7 @@ class coro_rpc_client { socket_->shutdown(asio::ip::tcp::socket::shutdown_send); r = rpc_result{ unexpect_t{}, - coro_rpc_protocol::rpc_error{errc::io_error, ret.first.message()}}; + rpc_error{errc::io_error, ret.first.message()}}; co_return r; } else { @@ -615,7 +615,7 @@ class coro_rpc_client { config_.client_id); r = rpc_result{ unexpect_t{}, - coro_rpc_protocol::rpc_error{errc::io_error, ret.first.message()}}; + rpc_error{errc::io_error, ret.first.message()}}; close(); co_return r; } @@ -669,12 +669,12 @@ class coro_rpc_client { if (is_timeout_) { r = rpc_result{ unexpect_t{}, - coro_rpc_protocol::rpc_error{.code = errc::timed_out, .msg = {}}}; + rpc_error{.code = errc::timed_out, .msg = {}}}; } else { r = rpc_result{ unexpect_t{}, - coro_rpc_protocol::rpc_error{.code = errc::io_error, + rpc_error{.code = errc::io_error, .msg = ret.first.message()}}; } close(); @@ -733,7 +733,7 @@ class coro_rpc_client { bool &error_happen) { rpc_return_type_t ret; struct_pack::err_code ec; - coro_rpc_protocol::rpc_error err; + rpc_error err; if (rpc_errc == 0) AS_LIKELY { ec = struct_pack::deserialize_to(ret, buffer); diff --git a/include/ylt/coro_rpc/impl/errno.h b/include/ylt/coro_rpc/impl/errno.h index 1bc2de612..6955e96d0 100644 --- a/include/ylt/coro_rpc/impl/errno.h +++ b/include/ylt/coro_rpc/impl/errno.h @@ -13,8 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include - +#include #include #pragma once namespace coro_rpc { @@ -92,4 +91,12 @@ struct err_code { inline bool operator!(err_code ec) noexcept { return ec == errc::ok; } inline bool operator!(errc ec) noexcept { return ec == errc::ok; } +struct rpc_error { + coro_rpc::err_code code; //!< error code + std::string msg; //!< error message + uint16_t& val() { return *(uint16_t*)&(code.ec); } + const uint16_t& val() const { return *(uint16_t*)&(code.ec); } +}; +STRUCT_PACK_REFL(rpc_error, val(), msg); + }; // namespace coro_rpc \ No newline at end of file diff --git a/include/ylt/coro_rpc/impl/expected.hpp b/include/ylt/coro_rpc/impl/expected.hpp index 02b91375b..18909b2d4 100644 --- a/include/ylt/coro_rpc/impl/expected.hpp +++ b/include/ylt/coro_rpc/impl/expected.hpp @@ -49,6 +49,6 @@ namespace protocol { } template -using rpc_result = expected; +using rpc_result = expected; } // namespace coro_rpc \ No newline at end of file diff --git a/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp b/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp index 578c1321e..def98ce9e 100644 --- a/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp +++ b/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp @@ -184,12 +184,7 @@ struct coro_rpc_protocol { * The `rpc_error` struct holds the error code `code` and error message * `msg`. */ - struct rpc_error { - coro_rpc::err_code code; //!< error code - std::string msg; //!< error message - uint16_t& val() { return *(uint16_t*)&(code.ec); } - const uint16_t& val() const { return *(uint16_t*)&(code.ec); } - }; + // internal variable constexpr static inline int8_t magic_number = 21; @@ -201,8 +196,6 @@ struct coro_rpc_protocol { static_assert(RESP_HEAD_LEN == 16); }; -STRUCT_PACK_REFL(coro_rpc_protocol::rpc_error, val(), msg); - template uint64_t get_request_id(const typename rpc_protocol::req_header& header) noexcept { if constexpr (std::is_same_v) { @@ -216,7 +209,6 @@ uint64_t get_request_id(const typename rpc_protocol::req_header& header) noexcep template using context = coro_rpc::context_base; -using rpc_error = protocol::coro_rpc_protocol::rpc_error; template async_simple::coro::Lazy*> get_context() { diff --git a/include/ylt/coro_rpc/impl/router.hpp b/include/ylt/coro_rpc/impl/router.hpp index 39863454a..28ae51659 100644 --- a/include/ylt/coro_rpc/impl/router.hpp +++ b/include/ylt/coro_rpc/impl/router.hpp @@ -31,6 +31,7 @@ #include "rpc_execute.hpp" #include "ylt/coro_rpc/impl/expected.hpp" +#include "ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp" namespace coro_rpc { @@ -253,6 +254,8 @@ class router { co_return std::make_pair(err_code{ec}, std::string{coro_rpc::make_error_message(ec)}); } catch (coro_rpc::err_code ec) { co_return std::make_pair(ec, std::string{ec.message()}); + } catch (coro_rpc::rpc_error& err) { + co_return std::make_pair(err.code, std::move(err.msg)); } catch (const std::exception &e) { co_return std::make_pair(coro_rpc::errc::rpc_throw_exception, e.what()); } catch (...) { @@ -284,6 +287,8 @@ class router { return std::make_pair(err_code{ec}, std::string{msg}); } catch (coro_rpc::err_code ec) { return std::make_pair(ec, std::string{ec.message()}); + } catch (coro_rpc::rpc_error& err) { + return std::make_pair(err.code, std::move(err.msg)); } catch (const std::exception &e) { return std::make_pair(err_code{coro_rpc::errc::rpc_throw_exception}, e.what()); } catch (...) { diff --git a/src/coro_rpc/tests/rpc_api.cpp b/src/coro_rpc/tests/rpc_api.cpp index b1f101371..9deb9db17 100644 --- a/src/coro_rpc/tests/rpc_api.cpp +++ b/src/coro_rpc/tests/rpc_api.cpp @@ -15,6 +15,7 @@ */ #include "rpc_api.hpp" +#include #include #include #include "ylt/coro_rpc/impl/errno.h" @@ -60,6 +61,10 @@ void test_context(coro_rpc::context conn) { } ELOGV(INFO, "call function echo_with_attachment, conn ID:%d, request ID:%d", ctx->get_connection_id(),ctx->get_request_id()); ELOGI << "remote endpoint: " << ctx->get_remote_endpoint()<<"local endpoint"<get_local_endpoint(); + if (ctx->get_rpc_function_name() != "test_context") { + throw std::runtime_error("get error rpc function name!"); + } + ELOGI<< "rpc function name:"<get_rpc_function_name(); std::string sv{ctx->get_request_attachment()}; auto str = ctx->release_request_attachment(); if (sv!=str) { @@ -118,6 +123,15 @@ void test_response_error4() { return; } +void test_response_error5() { + throw coro_rpc::rpc_error{coro_rpc::errc::address_in_used,"error with user-defined msg"}; + return; +} + +Lazy test_response_error6() { + throw coro_rpc::rpc_error{coro_rpc::errc::address_in_used,"error with user-defined msg"}; +} + void coro_fun_with_user_define_connection_type(my_context conn) { conn.ctx_.response_msg(); } diff --git a/src/coro_rpc/tests/rpc_api.hpp b/src/coro_rpc/tests/rpc_api.hpp index 91fc1da8c..73efc177f 100644 --- a/src/coro_rpc/tests/rpc_api.hpp +++ b/src/coro_rpc/tests/rpc_api.hpp @@ -45,6 +45,8 @@ async_simple::coro::Lazy test_response_error(); async_simple::coro::Lazy test_response_error2(); void test_response_error3(); void test_response_error4(); +void test_response_error5(); +async_simple::coro::Lazy test_response_error6(); void coro_fun_with_user_define_connection_type(my_context conn); void coro_fun_with_delay_return_void(coro_rpc::context conn); void coro_fun_with_delay_return_string(coro_rpc::context conn); diff --git a/src/coro_rpc/tests/test_coro_rpc_server.cpp b/src/coro_rpc/tests/test_coro_rpc_server.cpp index bbec5f3f7..6aa20aeb7 100644 --- a/src/coro_rpc/tests/test_coro_rpc_server.cpp +++ b/src/coro_rpc/tests/test_coro_rpc_server.cpp @@ -84,7 +84,7 @@ struct CoroServerTester : ServerTester { server.register_handler(); server.register_handler(); server.register_handler(); + test_response_error3, test_response_error4,test_response_error5,test_response_error6>(); server.register_handler(); server.register_handler(); server.register_handler(); @@ -135,6 +135,22 @@ struct CoroServerTester : ServerTester { CHECK(client->has_closed()); CHECK(result.error().code == coro_rpc::errc::io_error); } + { + auto client = create_client(); + ELOGV(INFO, "run %s, client_id %d", __func__, client->get_client_id()); + auto result = syncAwait(client->call()); + REQUIRE(!result); + CHECK(result.error().code == coro_rpc::errc::address_in_used); + CHECK(result.error().msg=="error with user-defined msg"); + } + { + auto client = create_client(); + ELOGV(INFO, "run %s, client_id %d", __func__, client->get_client_id()); + auto result = syncAwait(client->call()); + REQUIRE(!result); + CHECK(result.error().code == coro_rpc::errc::address_in_used); + CHECK(result.error().msg=="error with user-defined msg"); + } } void test_function_not_registered() { diff --git a/src/coro_rpc/tests/test_router.cpp b/src/coro_rpc/tests/test_router.cpp index b53e5b930..5debde8d2 100644 --- a/src/coro_rpc/tests/test_router.cpp +++ b/src/coro_rpc/tests/test_router.cpp @@ -75,7 +75,7 @@ get_result(const auto &pair) { coro_rpc_protocol>; rpc_return_type_t ret; struct_pack::err_code ec; - coro_rpc_protocol::rpc_error err; + rpc_error err; if (!rpc_errc) { ec = struct_pack::deserialize_to(ret, buffer); if (!ec) { @@ -108,7 +108,7 @@ void check_result(const auto &pair, size_t offset = 0) { typename RPC_trait::return_type r; auto res = struct_pack::deserialize_to(r, data); if (res) { - coro_rpc_protocol::rpc_error r; + rpc_error r; auto res = struct_pack::deserialize_to(r, data); CHECK(!res); } diff --git a/src/coro_rpc/tests/test_variadic.cpp b/src/coro_rpc/tests/test_variadic.cpp index 1f6feba63..79a8b0153 100644 --- a/src/coro_rpc/tests/test_variadic.cpp +++ b/src/coro_rpc/tests/test_variadic.cpp @@ -55,6 +55,5 @@ TEST_CASE("test varadic param") { CHECK(ret); if (ret) { CHECK(ret == "1145142.000000Hello coro_rpc!hellohiwhat"); - std::cout << ret.value() << std::endl; } } From 58569e1d9c06e4a0800b75089a307e467945d4e6 Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Tue, 2 Apr 2024 16:42:13 +0800 Subject: [PATCH 13/19] remove support for throw errc/err_code --- include/ylt/coro_rpc/impl/router.hpp | 9 -------- src/coro_rpc/tests/rpc_api.cpp | 22 +----------------- src/coro_rpc/tests/rpc_api.hpp | 4 ---- src/coro_rpc/tests/test_coro_rpc_server.cpp | 25 +-------------------- 4 files changed, 2 insertions(+), 58 deletions(-) diff --git a/include/ylt/coro_rpc/impl/router.hpp b/include/ylt/coro_rpc/impl/router.hpp index 28ae51659..27b444b88 100644 --- a/include/ylt/coro_rpc/impl/router.hpp +++ b/include/ylt/coro_rpc/impl/router.hpp @@ -250,10 +250,6 @@ class router { #endif // clang-format off co_return co_await (*handler)(data, protocols); - } catch (coro_rpc::errc ec) { - co_return std::make_pair(err_code{ec}, std::string{coro_rpc::make_error_message(ec)}); - } catch (coro_rpc::err_code ec) { - co_return std::make_pair(ec, std::string{ec.message()}); } catch (coro_rpc::rpc_error& err) { co_return std::make_pair(err.code, std::move(err.msg)); } catch (const std::exception &e) { @@ -282,11 +278,6 @@ class router { ELOGV(INFO, "route function name: %s", get_name(route_key).data()); #endif return (*handler)(data, context_info, protocols); - } catch (coro_rpc::errc ec) { - auto msg = coro_rpc::make_error_message(ec); - return std::make_pair(err_code{ec}, std::string{msg}); - } catch (coro_rpc::err_code ec) { - return std::make_pair(ec, std::string{ec.message()}); } catch (coro_rpc::rpc_error& err) { return std::make_pair(err.code, std::move(err.msg)); } catch (const std::exception &e) { diff --git a/src/coro_rpc/tests/rpc_api.cpp b/src/coro_rpc/tests/rpc_api.cpp index 9deb9db17..892f5a148 100644 --- a/src/coro_rpc/tests/rpc_api.cpp +++ b/src/coro_rpc/tests/rpc_api.cpp @@ -94,7 +94,7 @@ Lazy test_lazy_context() { auto str = ctx->release_request_attachment(); if (sv!=str) { ctx->close(); - throw coro_rpc::errc::rpc_throw_exception; + throw rpc_error{coro_rpc::errc::io_error,"attachment error!"}; co_return; } ctx->set_response_attachment(std::move(str)); @@ -103,26 +103,6 @@ Lazy test_lazy_context() { co_return; } -Lazy test_response_error() { - throw coro_rpc::err_code{uint16_t{12243}}; - co_return; -} - -Lazy test_response_error2() { - throw coro_rpc::errc::io_error; - co_return; -} - -void test_response_error3() { - throw coro_rpc::err_code{uint16_t{12243}}; - return; -} - -void test_response_error4() { - throw coro_rpc::errc::io_error; - return; -} - void test_response_error5() { throw coro_rpc::rpc_error{coro_rpc::errc::address_in_used,"error with user-defined msg"}; return; diff --git a/src/coro_rpc/tests/rpc_api.hpp b/src/coro_rpc/tests/rpc_api.hpp index 73efc177f..5bd63e0b9 100644 --- a/src/coro_rpc/tests/rpc_api.hpp +++ b/src/coro_rpc/tests/rpc_api.hpp @@ -41,10 +41,6 @@ inline void error_with_context(coro_rpc::context conn) { } void test_context(coro_rpc::context conn); async_simple::coro::Lazy test_lazy_context(); -async_simple::coro::Lazy test_response_error(); -async_simple::coro::Lazy test_response_error2(); -void test_response_error3(); -void test_response_error4(); void test_response_error5(); async_simple::coro::Lazy test_response_error6(); void coro_fun_with_user_define_connection_type(my_context conn); diff --git a/src/coro_rpc/tests/test_coro_rpc_server.cpp b/src/coro_rpc/tests/test_coro_rpc_server.cpp index 6aa20aeb7..bc7f97974 100644 --- a/src/coro_rpc/tests/test_coro_rpc_server.cpp +++ b/src/coro_rpc/tests/test_coro_rpc_server.cpp @@ -83,8 +83,7 @@ struct CoroServerTester : ServerTester { server.register_handler(); server.register_handler(); server.register_handler(); - server.register_handler(); + server.register_handler(); server.register_handler(); server.register_handler(); server.register_handler(); @@ -113,28 +112,6 @@ struct CoroServerTester : ServerTester { CHECK(client->get_resp_attachment() == "01234567890987654321234567890"); } void test_return_err_by_throw_exception() { - { - auto client = create_client(); - ELOGV(INFO, "run %s, client_id %d", __func__, client->get_client_id()); - auto result = syncAwait(client->call()); - REQUIRE(!result); - CHECK(result.error().code == coro_rpc::errc{12243}); - result = syncAwait(client->call()); - REQUIRE(!result); - CHECK(client->has_closed()); - CHECK(result.error().code == coro_rpc::errc::io_error); - } - { - auto client = create_client(); - ELOGV(INFO, "run %s, client_id %d", __func__, client->get_client_id()); - auto result = syncAwait(client->call()); - REQUIRE(!result); - CHECK(result.error().code == coro_rpc::errc{12243}); - result = syncAwait(client->call()); - REQUIRE(!result); - CHECK(client->has_closed()); - CHECK(result.error().code == coro_rpc::errc::io_error); - } { auto client = create_client(); ELOGV(INFO, "run %s, client_id %d", __func__, client->get_client_id()); From 90e8b8135335c13cc5773240eddeb8dcdb9d48f8 Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Tue, 2 Apr 2024 16:53:05 +0800 Subject: [PATCH 14/19] fix format --- include/ylt/coro_rpc/coro_rpc_context.hpp | 1 - include/ylt/coro_rpc/impl/context.hpp | 9 +- include/ylt/coro_rpc/impl/coro_connection.hpp | 131 ++++++++++-------- include/ylt/coro_rpc/impl/coro_rpc_client.hpp | 44 +++--- include/ylt/coro_rpc/impl/errno.h | 2 +- include/ylt/coro_rpc/impl/expected.hpp | 5 +- .../impl/protocol/coro_rpc_protocol.hpp | 19 +-- include/ylt/coro_rpc/impl/router.hpp | 33 +++-- include/ylt/coro_rpc/impl/rpc_execute.hpp | 91 ++++++------ 9 files changed, 180 insertions(+), 155 deletions(-) diff --git a/include/ylt/coro_rpc/coro_rpc_context.hpp b/include/ylt/coro_rpc/coro_rpc_context.hpp index 2557e32bd..a50d6ad29 100644 --- a/include/ylt/coro_rpc/coro_rpc_context.hpp +++ b/include/ylt/coro_rpc/coro_rpc_context.hpp @@ -14,5 +14,4 @@ * limitations under the License. */ #pragma once - #include "impl/protocol/coro_rpc_protocol.hpp" diff --git a/include/ylt/coro_rpc/impl/context.hpp b/include/ylt/coro_rpc/impl/context.hpp index fdf3ea132..84fde1aa2 100644 --- a/include/ylt/coro_rpc/impl/context.hpp +++ b/include/ylt/coro_rpc/impl/context.hpp @@ -79,7 +79,8 @@ class context_base { std::string_view error_msg) { if (!check_status()) AS_UNLIKELY { return; }; - ELOGI << "rpc error in function:" << self_->get_rpc_function_name() << ". error code:" << error_code.ec << ". message : "<< error_msg; + ELOGI << "rpc error in function:" << self_->get_rpc_function_name() + << ". error code:" << error_code.ec << ". message : " << error_msg; self_->conn_->template response_error(error_code, error_msg, self_->req_head_); } @@ -129,12 +130,10 @@ class context_base { /*finish here*/ self_->status_ = context_status::finish_response; } - const context_info_t* get_context() const noexcept { - return self_.get(); - } - context_info_t* get_context() noexcept { + const context_info_t *get_context() const noexcept { return self_.get(); } + context_info_t *get_context() noexcept { return self_.get(); } }; template diff --git a/include/ylt/coro_rpc/impl/coro_connection.hpp b/include/ylt/coro_rpc/impl/coro_connection.hpp index 58d704dcb..9e5068c65 100644 --- a/include/ylt/coro_rpc/impl/coro_connection.hpp +++ b/include/ylt/coro_rpc/impl/coro_connection.hpp @@ -46,10 +46,10 @@ enum class context_status : int { init, start_response, finish_response }; template struct context_info_t { #ifndef CORO_RPC_TEST -private: + private: #endif typename rpc_protocol::route_key_t key; - typename rpc_protocol::router& router; + typename rpc_protocol::router &router; std::shared_ptr conn_; typename rpc_protocol::req_header req_head_; std::string req_body_; @@ -58,15 +58,19 @@ struct context_info_t { return std::string_view{}; }; std::atomic status_ = context_status::init; -public: + + public: template friend class context_base; friend class coro_connection; - context_info_t(typename rpc_protocol::router& r,std::shared_ptr &&conn) - : router(r),conn_(std::move(conn)) {} - context_info_t(typename rpc_protocol::router& r,std::shared_ptr &&conn, + context_info_t(typename rpc_protocol::router &r, + std::shared_ptr &&conn) + : router(r), conn_(std::move(conn)) {} + context_info_t(typename rpc_protocol::router &r, + std::shared_ptr &&conn, std::string &&req_body_buf, std::string &&req_attachment_buf) - : router(r), conn_(std::move(conn)), + : router(r), + conn_(std::move(conn)), req_body_(std::move(req_body_buf)), req_attachment_(std::move(req_attachment_buf)) {} uint64_t get_connection_id() noexcept; @@ -82,7 +86,7 @@ struct context_info_t { const std::any &tag() const noexcept; asio::ip::tcp::endpoint get_local_endpoint() const noexcept; asio::ip::tcp::endpoint get_remote_endpoint() const noexcept; - uint64_t get_request_id() const noexcept; + uint64_t get_request_id() const noexcept; std::string_view get_rpc_function_name() const { return router.get_name(key); } @@ -175,8 +179,8 @@ class coro_connection : public std::enable_shared_from_this { template async_simple::coro::Lazy start_impl( typename rpc_protocol::router &router, Socket &socket) noexcept { - auto context_info = - std::make_shared>(router,shared_from_this()); + auto context_info = std::make_shared>( + router, shared_from_this()); reset_timer(); while (true) { typename rpc_protocol::req_header req_head_tmp; @@ -214,13 +218,13 @@ class coro_connection : public std::enable_shared_from_this { is_rpc_return_by_callback_ = false; if (context_info->status_ != context_status::finish_response) { // cant reuse buffer - context_info = std::make_shared>(router, - shared_from_this()); + context_info = std::make_shared>( + router, shared_from_this()); } else { // reuse string buffer - context_info = std::make_shared>(router, - shared_from_this(), std::move(context_info->req_body_), + context_info = std::make_shared>( + router, shared_from_this(), std::move(context_info->req_body_), std::move(context_info->req_attachment_)); } } @@ -260,31 +264,39 @@ class coro_connection : public std::enable_shared_from_this { if (!handler) { auto coro_handler = router.get_coro_handler(key); set_rpc_return_by_callback(); - router - .route_coro(coro_handler, payload, - serialize_proto.value(), key) - .via(executor_).setLazyLocal((void*)context_info.get()) + router.route_coro(coro_handler, payload, serialize_proto.value(), key) + .via(executor_) + .setLazyLocal((void *)context_info.get()) .start([context_info](auto &&result) mutable { - std::pair &ret = result.value(); - if (ret.first) AS_UNLIKELY { - ELOGI << "rpc error in function:" << context_info->get_rpc_function_name() << ". error code:" << ret.first.ec << ". message : "<< ret.second; - } + std::pair &ret = result.value(); + if (ret.first) + AS_UNLIKELY { + ELOGI << "rpc error in function:" + << context_info->get_rpc_function_name() + << ". error code:" << ret.first.ec + << ". message : " << ret.second; + } auto executor = context_info->conn_->get_executor(); - executor->schedule([context_info=std::move(context_info), ret = std::move(ret)]() mutable { + executor->schedule([context_info = std::move(context_info), + ret = std::move(ret)]() mutable { context_info->conn_->template direct_response_msg( - ret.first, ret.second, context_info->req_head_,std::move(context_info->resp_attachment_)); - }); + ret.first, ret.second, context_info->req_head_, + std::move(context_info->resp_attachment_)); }); + }); } else { - auto &&[resp_err, resp_buf] = router.route(handler, payload, context_info, - serialize_proto.value(), key); + auto &&[resp_err, resp_buf] = router.route( + handler, payload, context_info, serialize_proto.value(), key); if (is_rpc_return_by_callback_) { if (!resp_err) { continue; } else { - ELOGI << "rpc error in function:" << context_info->get_rpc_function_name() << ". error code:" << resp_err.ec << ". message : "<< resp_buf; + ELOGI << "rpc error in function:" + << context_info->get_rpc_function_name() + << ". error code:" << resp_err.ec + << ". message : " << resp_buf; is_rpc_return_by_callback_ = false; } } @@ -293,7 +305,7 @@ class coro_connection : public std::enable_shared_from_this { ELOGV(WARN, "inject action: close_socket_after_send_length", conn_id_, client_id_); std::string header_buf = rpc_protocol::prepare_response( - resp_buf, req_head, 0, resp_err, ""); + resp_buf, req_head, 0, resp_err, ""); co_await coro_io::async_write(socket, asio::buffer(header_buf)); close(); break; @@ -319,20 +331,24 @@ class coro_connection : public std::enable_shared_from_this { * @param ret object of message type */ template - void direct_response_msg(coro_rpc::err_code &resp_err, std::string &resp_buf,const typename rpc_protocol::req_header &req_head, std::function&& attachment=[]{return std::string_view();}) { + void direct_response_msg( + coro_rpc::err_code &resp_err, std::string &resp_buf, + const typename rpc_protocol::req_header &req_head, + std::function &&attachment = [] { + return std::string_view(); + }) { std::string resp_error_msg; if (resp_err) { resp_error_msg = std::move(resp_buf); resp_buf = {}; - ELOGV(WARNING, "rpc route/execute error, error msg: %s", resp_error_msg.data()); + ELOGV(WARNING, "rpc route/execute error, error msg: %s", + resp_error_msg.data()); } std::string header_buf = rpc_protocol::prepare_response( resp_buf, req_head, attachment().length(), resp_err, resp_error_msg); - response( - std::move(header_buf), std::move(resp_buf), - std::move(attachment), - nullptr) + response(std::move(header_buf), std::move(resp_buf), std::move(attachment), + nullptr) .start([](auto &&) { }); } @@ -356,8 +372,8 @@ class coro_connection : public std::enable_shared_from_this { return {}; }; std::string body_buf; - std::string header_buf = rpc_protocol::prepare_response( - body_buf, req_head, 0, ec, error_msg); + std::string header_buf = + rpc_protocol::prepare_response(body_buf, req_head, 0, ec, error_msg); response(std::move(header_buf), std::move(body_buf), std::move(attach_ment), shared_from_this()) .via(executor_) @@ -402,9 +418,13 @@ class coro_connection : public std::enable_shared_from_this { auto get_executor() { return executor_; } - asio::ip::tcp::endpoint get_remote_endpoint() {return socket_.remote_endpoint();} + asio::ip::tcp::endpoint get_remote_endpoint() { + return socket_.remote_endpoint(); + } - asio::ip::tcp::endpoint get_local_endpoint() {return socket_.local_endpoint();} + asio::ip::tcp::endpoint get_local_endpoint() { + return socket_.local_endpoint(); + } private: async_simple::coro::Lazy response( @@ -505,7 +525,7 @@ class coro_connection : public std::enable_shared_from_this { } void close() { - ELOGV(TRACE,"connection closed"); + ELOGV(TRACE, "connection closed"); if (has_closed_) { return; } @@ -561,7 +581,7 @@ class coro_connection : public std::enable_shared_from_this { bool enable_check_timeout_{false}; asio::steady_timer timer_; std::atomic has_closed_{false}; - + QuitCallback quit_callback_{nullptr}; uint64_t conn_id_{0}; uint64_t delay_resp_cnt{0}; @@ -584,7 +604,7 @@ uint64_t context_info_t::get_connection_id() noexcept { } template -uint64_t context_info_t::has_closed() const noexcept { +uint64_t context_info_t::has_closed() const noexcept { return conn_->has_closed(); } @@ -594,26 +614,27 @@ void context_info_t::close() { } template -uint64_t context_info_t::get_connection_id() const noexcept { - -} +uint64_t context_info_t::get_connection_id() const noexcept {} template -void context_info_t::set_response_attachment(std::string attachment) { +void context_info_t::set_response_attachment( + std::string attachment) { set_response_attachment([attachment = std::move(attachment)] { return std::string_view{attachment}; }); } template -void context_info_t::set_response_attachment(std::string_view attachment) { +void context_info_t::set_response_attachment( + std::string_view attachment) { set_response_attachment([attachment] { return attachment; }); } template -void context_info_t::set_response_attachment(std::function attachment) { +void context_info_t::set_response_attachment( + std::function attachment) { resp_attachment_ = std::move(attachment); } @@ -628,27 +649,29 @@ std::string context_info_t::release_request_attachment() { } template -std::any & context_info_t::tag() noexcept { +std::any &context_info_t::tag() noexcept { return conn_->tag(); } template -const std::any & context_info_t::tag() const noexcept { +const std::any &context_info_t::tag() const noexcept { return conn_->tag(); } template -asio::ip::tcp::endpoint context_info_t::get_local_endpoint() const noexcept { +asio::ip::tcp::endpoint context_info_t::get_local_endpoint() + const noexcept { return conn_->get_local_endpoint(); } template -asio::ip::tcp::endpoint context_info_t::get_remote_endpoint() const noexcept { +asio::ip::tcp::endpoint context_info_t::get_remote_endpoint() + const noexcept { return conn_->get_remote_endpoint(); } namespace protocol { - template - uint64_t get_request_id(const typename rpc_protocol::req_header&) noexcept; +template +uint64_t get_request_id(const typename rpc_protocol::req_header &) noexcept; } template uint64_t context_info_t::get_request_id() const noexcept { diff --git a/include/ylt/coro_rpc/impl/coro_rpc_client.hpp b/include/ylt/coro_rpc/impl/coro_rpc_client.hpp index 890ca1bdc..b3d924f7a 100644 --- a/include/ylt/coro_rpc/impl/coro_rpc_client.hpp +++ b/include/ylt/coro_rpc/impl/coro_rpc_client.hpp @@ -109,8 +109,8 @@ class coro_rpc_client { using coro_rpc_protocol = coro_rpc::protocol::coro_rpc_protocol; public: - const inline static rpc_error connect_error = { - errc::io_error, "client has been closed"}; + const inline static rpc_error connect_error = {errc::io_error, + "client has been closed"}; struct config { uint32_t client_id = 0; std::chrono::milliseconds timeout_duration = @@ -289,8 +289,8 @@ class coro_rpc_client { ELOGV(ERROR, "client has been closed, please re-connect"); auto ret = rpc_result{ unexpect_t{}, - rpc_error{ - errc::io_error, "client has been closed, please re-connect"}}; + rpc_error{errc::io_error, + "client has been closed, please re-connect"}}; co_return ret; } @@ -299,9 +299,8 @@ class coro_rpc_client { if (!ssl_init_ret_) { ret = rpc_result{ unexpect_t{}, - rpc_error{ - errc::not_connected, - std::string{make_error_message(errc::not_connected)}}}; + rpc_error{errc::not_connected, + std::string{make_error_message(errc::not_connected)}}}; co_return ret; } #endif @@ -328,8 +327,7 @@ class coro_rpc_client { if (is_timeout_) { ret = rpc_result{ - unexpect_t{}, - rpc_error{errc::timed_out, "rpc call timed out"}}; + unexpect_t{}, rpc_error{errc::timed_out, "rpc call timed out"}}; } #ifdef UNIT_TEST_INJECT @@ -542,9 +540,8 @@ class coro_rpc_client { rpc_result r{}; if (buffer.empty()) { r = rpc_result{ - unexpect_t{}, - rpc_error{errc::message_too_large, - "rpc body serialize size too big"}}; + unexpect_t{}, rpc_error{errc::message_too_large, + "rpc body serialize size too big"}}; co_return r; } #ifdef GENERATE_BENCHMARK_DATA @@ -565,8 +562,7 @@ class coro_rpc_client { ELOGV(INFO, "client_id %d close socket", config_.client_id); close(); r = rpc_result{ - unexpect_t{}, - rpc_error{errc::io_error, ret.first.message()}}; + unexpect_t{}, rpc_error{errc::io_error, ret.first.message()}}; co_return r; } else if (g_action == @@ -577,8 +573,7 @@ class coro_rpc_client { ELOGV(INFO, "client_id %d close socket", config_.client_id); close(); r = rpc_result{ - unexpect_t{}, - rpc_error{errc::io_error, ret.first.message()}}; + unexpect_t{}, rpc_error{errc::io_error, ret.first.message()}}; co_return r; } else if (g_action == @@ -588,8 +583,7 @@ class coro_rpc_client { ELOGV(INFO, "client_id %d shutdown", config_.client_id); socket_->shutdown(asio::ip::tcp::socket::shutdown_send); r = rpc_result{ - unexpect_t{}, - rpc_error{errc::io_error, ret.first.message()}}; + unexpect_t{}, rpc_error{errc::io_error, ret.first.message()}}; co_return r; } else { @@ -614,8 +608,7 @@ class coro_rpc_client { ELOGV(INFO, "client_id %d client_close_socket_after_send_payload", config_.client_id); r = rpc_result{ - unexpect_t{}, - rpc_error{errc::io_error, ret.first.message()}}; + unexpect_t{}, rpc_error{errc::io_error, ret.first.message()}}; close(); co_return r; } @@ -668,14 +661,12 @@ class coro_rpc_client { #endif if (is_timeout_) { r = rpc_result{ - unexpect_t{}, - rpc_error{.code = errc::timed_out, .msg = {}}}; + unexpect_t{}, rpc_error{.code = errc::timed_out, .msg = {}}}; } else { r = rpc_result{ unexpect_t{}, - rpc_error{.code = errc::io_error, - .msg = ret.first.message()}}; + rpc_error{.code = errc::io_error, .msg = ret.first.message()}}; } close(); co_return r; @@ -751,16 +742,15 @@ class coro_rpc_client { err.val() = rpc_errc; ec = struct_pack::deserialize_to(err.msg, buffer); if SP_LIKELY (!ec) { - ELOGV(WARNING,"deserilaize rpc result failed"); + ELOGV(WARNING, "deserilaize rpc result failed"); error_happen = true; return rpc_result{unexpect_t{}, std::move(err)}; } } else { - ec = struct_pack::deserialize_to(err, buffer); if SP_LIKELY (!ec) { - ELOGV(WARNING,"deserilaize rpc result failed"); + ELOGV(WARNING, "deserilaize rpc result failed"); return rpc_result{unexpect_t{}, std::move(err)}; } } diff --git a/include/ylt/coro_rpc/impl/errno.h b/include/ylt/coro_rpc/impl/errno.h index 6955e96d0..22dcb8aeb 100644 --- a/include/ylt/coro_rpc/impl/errno.h +++ b/include/ylt/coro_rpc/impl/errno.h @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include #include +#include #pragma once namespace coro_rpc { enum class errc : uint16_t { diff --git a/include/ylt/coro_rpc/impl/expected.hpp b/include/ylt/coro_rpc/impl/expected.hpp index 18909b2d4..4a0a7e91e 100644 --- a/include/ylt/coro_rpc/impl/expected.hpp +++ b/include/ylt/coro_rpc/impl/expected.hpp @@ -45,10 +45,11 @@ using unexpect_t = tl::unexpect_t; #endif namespace protocol { - struct coro_rpc_protocol; +struct coro_rpc_protocol; } -template +template using rpc_result = expected; } // namespace coro_rpc \ No newline at end of file diff --git a/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp b/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp index def98ce9e..9260d007d 100644 --- a/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp +++ b/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp @@ -163,7 +163,7 @@ struct coro_rpc_protocol { if (rpc_err_code != coro_rpc::errc{}) AS_UNLIKELY { rpc_result.clear(); - if (static_cast(rpc_err_code)>UINT8_MAX) { + if (static_cast(rpc_err_code) > UINT8_MAX) { struct_pack::serialize_to( rpc_result, std::pair{static_cast(rpc_err_code), err_msg}); @@ -185,7 +185,6 @@ struct coro_rpc_protocol { * `msg`. */ - // internal variable constexpr static inline int8_t magic_number = 21; @@ -196,9 +195,11 @@ struct coro_rpc_protocol { static_assert(RESP_HEAD_LEN == 16); }; -template -uint64_t get_request_id(const typename rpc_protocol::req_header& header) noexcept { - if constexpr (std::is_same_v) { +template +uint64_t get_request_id( + const typename rpc_protocol::req_header& header) noexcept { + if constexpr (std::is_same_v) { return header.seq_num; } else { @@ -210,10 +211,10 @@ template using context = coro_rpc::context_base; -template +template async_simple::coro::Lazy*> get_context() { - auto *ctx=co_await async_simple::coro::LazyLocals{}; - assert(ctx!=nullptr); - co_return (context_info_t*)ctx; + auto* ctx = co_await async_simple::coro::LazyLocals{}; + assert(ctx != nullptr); + co_return(context_info_t*) ctx; } } // namespace coro_rpc \ No newline at end of file diff --git a/include/ylt/coro_rpc/impl/router.hpp b/include/ylt/coro_rpc/impl/router.hpp index 27b444b88..1414b8e4e 100644 --- a/include/ylt/coro_rpc/impl/router.hpp +++ b/include/ylt/coro_rpc/impl/router.hpp @@ -48,15 +48,14 @@ template typename map_t = std::unordered_map> class router { + public: + using router_handler_t = + std::function( + std::string_view, rpc_context &context_info, + typename rpc_protocol::supported_serialize_protocols protocols)>; - -public: - using router_handler_t = std::function( - std::string_view, rpc_context &context_info, - typename rpc_protocol::supported_serialize_protocols protocols)>; - - using coro_router_handler_t = - std::function>( + using coro_router_handler_t = std::function< + async_simple::coro::Lazy>( std::string_view, typename rpc_protocol::supported_serialize_protocols protocols)>; @@ -70,8 +69,8 @@ class router { else return empty_string; } - private: + private: std::unordered_map handlers_; std::unordered_map coro_handlers_; std::unordered_map id2name_; @@ -83,8 +82,8 @@ class router { std::string_view data; Self *self; template - async_simple::coro::Lazy> operator()( - const serialize_protocol &) { + async_simple::coro::Lazy> + operator()(const serialize_protocol &) { return internal::execute_coro( data, self); } @@ -94,8 +93,8 @@ class router { struct execute_visitor { std::string_view data; template - async_simple::coro::Lazy> operator() ( - const serialize_protocol &) { + async_simple::coro::Lazy> + operator()(const serialize_protocol &) { return internal::execute_coro( data); } @@ -236,10 +235,10 @@ class router { return nullptr; } - async_simple::coro::Lazy> route_coro( - auto handler, std::string_view data, - typename rpc_protocol::supported_serialize_protocols protocols, - const typename rpc_protocol::route_key_t &route_key) { + async_simple::coro::Lazy> + route_coro(auto handler, std::string_view data, + typename rpc_protocol::supported_serialize_protocols protocols, + const typename rpc_protocol::route_key_t &route_key) { using namespace std::string_literals; if (handler) AS_LIKELY { diff --git a/include/ylt/coro_rpc/impl/rpc_execute.hpp b/include/ylt/coro_rpc/impl/rpc_execute.hpp index b8c763fbb..cdaf153d3 100644 --- a/include/ylt/coro_rpc/impl/rpc_execute.hpp +++ b/include/ylt/coro_rpc/impl/rpc_execute.hpp @@ -22,8 +22,8 @@ #include #include -#include "coro_connection.hpp" #include "context.hpp" +#include "coro_connection.hpp" #include "ylt/coro_rpc/impl/errno.h" #include "ylt/easylog.hpp" #include "ylt/util/type_traits.h" @@ -51,7 +51,7 @@ using rpc_context = std::shared_ptr>; using rpc_conn = std::shared_ptr; template -inline std::pair execute( +inline std::pair execute( std::string_view data, rpc_context &context_info, Self *self = nullptr) { using namespace std::string_literals; @@ -79,9 +79,11 @@ inline std::pair execute( is_ok = serialize_proto::deserialize_to(args, data); } - if (!is_ok) - AS_UNLIKELY { return std::pair{err_code{errc::invalid_rpc_arguments}, - "invalid rpc arg"s}; } + if (!is_ok) + AS_UNLIKELY { + return std::pair{err_code{errc::invalid_rpc_arguments}, + "invalid rpc arg"s}; + } if constexpr (std::is_void_v) { if constexpr (std::is_void_v) { @@ -101,32 +103,35 @@ inline std::pair execute( else { if constexpr (has_coro_conn_v) { // call void self->func(coro_conn, args...) - std::apply(func, - std::tuple_cat( - std::forward_as_tuple( - *self, context_base( - context_info)), - std::move(args))); + std::apply( + func, std::tuple_cat( + std::forward_as_tuple( + *self, context_base( + context_info)), + std::move(args))); } else { // call void self->func(args...) - std::apply(func, - std::tuple_cat(std::forward_as_tuple(*self), std::move(args))); + std::apply(func, std::tuple_cat(std::forward_as_tuple(*self), + std::move(args))); } } - return std::pair{err_code{},serialize_proto::serialize()}; + return std::pair{err_code{}, serialize_proto::serialize()}; } else { if constexpr (std::is_void_v) { // call return_type func(args...) - return std::pair{err_code{},serialize_proto::serialize(std::apply(func, std::move(args)))}; + return std::pair{err_code{}, serialize_proto::serialize( + std::apply(func, std::move(args)))}; } else { // call return_type self->func(args...) - return std::pair{err_code{},serialize_proto::serialize(std::apply( - func, std::tuple_cat(std::forward_as_tuple(*self), std::move(args))))}; + return std::pair{err_code{}, + serialize_proto::serialize(std::apply( + func, std::tuple_cat(std::forward_as_tuple(*self), + std::move(args))))}; } } } @@ -138,14 +143,15 @@ inline std::pair execute( else { (self->*func)(); } - return std::pair{err_code{},serialize_proto::serialize()}; + return std::pair{err_code{}, serialize_proto::serialize()}; } else { if constexpr (std::is_void_v) { - return std::pair{err_code{},serialize_proto::serialize(func())}; + return std::pair{err_code{}, serialize_proto::serialize(func())}; } else { - return std::pair{err_code{},serialize_proto::serialize((self->*func)())}; + return std::pair{err_code{}, + serialize_proto::serialize((self->*func)())}; } } } @@ -153,9 +159,8 @@ inline std::pair execute( template -inline async_simple::coro::Lazy> execute_coro( - std::string_view data, - Self *self = nullptr) { +inline async_simple::coro::Lazy> +execute_coro(std::string_view data, Self *self = nullptr) { using namespace std::string_literals; using T = decltype(func); using param_type = util::function_parameters_t; @@ -165,7 +170,9 @@ inline async_simple::coro::Lazy> execu if constexpr (!std::is_void_v) { using First = std::tuple_element_t<0, param_type>; constexpr bool is_conn = requires { typename First::return_type; }; - static_assert(!is_conn,"context is not allowed as parameter in coroutine function"); + static_assert( + !is_conn, + "context is not allowed as parameter in coroutine function"); bool is_ok = true; constexpr size_t size = std::tuple_size_v; @@ -173,31 +180,36 @@ inline async_simple::coro::Lazy> execu if constexpr (size > 0) { is_ok = serialize_proto::deserialize_to(args, data); } - if (!is_ok) - AS_UNLIKELY { co_return std::make_pair(coro_rpc::errc::invalid_rpc_arguments, - "invalid rpc function arguments"s); } + if (!is_ok) + AS_UNLIKELY { + co_return std::make_pair(coro_rpc::errc::invalid_rpc_arguments, + "invalid rpc function arguments"s); + } if constexpr (std::is_void_v) { if constexpr (std::is_void_v) { - // call void func(args...) - co_await std::apply(func, std::move(args)); + // call void func(args...) + co_await std::apply(func, std::move(args)); } else { - // call void self->func(args...) - co_await std::apply( - func, std::tuple_cat(std::forward_as_tuple(*self), std::move(args))); + // call void self->func(args...) + co_await std::apply(func, std::tuple_cat(std::forward_as_tuple(*self), + std::move(args))); } - co_return std::pair{err_code{},serialize_proto::serialize()}; + co_return std::pair{err_code{}, serialize_proto::serialize()}; } else { if constexpr (std::is_void_v) { // call return_type func(args...) - co_return std::pair{err_code{},serialize_proto::serialize( - co_await std::apply(func, std::move(args)))}; + co_return std::pair{err_code{}, + serialize_proto::serialize( + co_await std::apply(func, std::move(args)))}; } else { // call return_type self->func(args...) - co_return std::pair{err_code{},serialize_proto::serialize(co_await std::apply( - func, std::tuple_cat(std::forward_as_tuple(*self), std::move(args))))}; + co_return std::pair{ + err_code{}, serialize_proto::serialize(co_await std::apply( + func, std::tuple_cat(std::forward_as_tuple(*self), + std::move(args))))}; } } } @@ -211,11 +223,12 @@ inline async_simple::coro::Lazy> execu co_await (self->*func)(); // clang-format on } - co_return std::pair{err_code{},serialize_proto::serialize()}; + co_return std::pair{err_code{}, serialize_proto::serialize()}; } else { if constexpr (std::is_void_v) { - co_return std::pair{err_code{},serialize_proto::serialize(co_await func())}; + co_return std::pair{err_code{}, + serialize_proto::serialize(co_await func())}; } else { // clang-format off From 0df79a93c0f4db69ed25359c5e53b7077b578634 Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Tue, 2 Apr 2024 17:48:44 +0800 Subject: [PATCH 15/19] fix format --- include/ylt/coro_rpc/impl/coro_connection.hpp | 22 +++++------ .../impl/protocol/coro_rpc_protocol.hpp | 2 +- include/ylt/easylog/record.hpp | 2 +- src/coro_rpc/benchmark/api/rpc_functions.hpp | 11 ++++-- src/coro_rpc/benchmark/data_gen.cpp | 4 +- src/coro_rpc/benchmark/server.hpp | 3 +- .../examples/base_examples/rpc_service.cpp | 29 +++++++------- .../examples/base_examples/rpc_service.h | 10 +++-- .../examples/base_examples/server.cpp | 10 ++--- .../examples/file_transfer/rpc_service.cpp | 4 +- src/coro_rpc/tests/rpc_api.cpp | 38 ++++++++++++------- src/coro_rpc/tests/rpc_api.hpp | 5 ++- src/coro_rpc/tests/test_coro_rpc_server.cpp | 6 +-- src/coro_rpc/tests/test_router.cpp | 3 +- 14 files changed, 88 insertions(+), 61 deletions(-) diff --git a/include/ylt/coro_rpc/impl/coro_connection.hpp b/include/ylt/coro_rpc/impl/coro_connection.hpp index 9e5068c65..13aa9869e 100644 --- a/include/ylt/coro_rpc/impl/coro_connection.hpp +++ b/include/ylt/coro_rpc/impl/coro_connection.hpp @@ -48,8 +48,8 @@ struct context_info_t { #ifndef CORO_RPC_TEST private: #endif - typename rpc_protocol::route_key_t key; - typename rpc_protocol::router &router; + typename rpc_protocol::route_key_t key_; + typename rpc_protocol::router &router_; std::shared_ptr conn_; typename rpc_protocol::req_header req_head_; std::string req_body_; @@ -65,11 +65,11 @@ struct context_info_t { friend class coro_connection; context_info_t(typename rpc_protocol::router &r, std::shared_ptr &&conn) - : router(r), conn_(std::move(conn)) {} + : router_(r), conn_(std::move(conn)) {} context_info_t(typename rpc_protocol::router &r, std::shared_ptr &&conn, std::string &&req_body_buf, std::string &&req_attachment_buf) - : router(r), + : router_(r), conn_(std::move(conn)), req_body_(std::move(req_body_buf)), req_attachment_(std::move(req_attachment_buf)) {} @@ -88,7 +88,7 @@ struct context_info_t { asio::ip::tcp::endpoint get_remote_endpoint() const noexcept; uint64_t get_request_id() const noexcept; std::string_view get_rpc_function_name() const { - return router.get_name(key); + return router_.get_name(key_); } }; @@ -231,7 +231,7 @@ class coro_connection : public std::enable_shared_from_this { auto &req_head = context_info->req_head_; auto &body = context_info->req_body_; auto &req_attachment = context_info->req_attachment_; - auto &key = context_info->key; + auto &key = context_info->key_; req_head = std::move(req_head_tmp); auto serialize_proto = rpc_protocol::get_serialize_protocol(req_head); @@ -260,7 +260,7 @@ class coro_connection : public std::enable_shared_from_this { key = rpc_protocol::get_route_key(req_head); auto handler = router.get_handler(key); - ++delay_resp_cnt; + ++rpc_processing_cnt_; if (!handler) { auto coro_handler = router.get_coro_handler(key); set_rpc_return_by_callback(); @@ -444,8 +444,8 @@ class coro_connection : public std::enable_shared_from_this { #endif write_queue_.emplace_back(std::move(header_buf), std::move(body_buf), std::move(resp_attachment)); - --delay_resp_cnt; - assert(delay_resp_cnt >= 0); + --rpc_processing_cnt_; + assert(rpc_processing_cnt_ >= 0); reset_timer(); if (write_queue_.size() == 1) { if (self == nullptr) @@ -539,7 +539,7 @@ class coro_connection : public std::enable_shared_from_this { } void reset_timer() { - if (!enable_check_timeout_ || delay_resp_cnt != 0) { + if (!enable_check_timeout_ || rpc_processing_cnt_ != 0) { return; } @@ -584,7 +584,7 @@ class coro_connection : public std::enable_shared_from_this { QuitCallback quit_callback_{nullptr}; uint64_t conn_id_{0}; - uint64_t delay_resp_cnt{0}; + uint64_t rpc_processing_cnt_{0}; std::any tag_; diff --git a/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp b/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp index 9260d007d..c161b4b44 100644 --- a/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp +++ b/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp @@ -215,6 +215,6 @@ template async_simple::coro::Lazy*> get_context() { auto* ctx = co_await async_simple::coro::LazyLocals{}; assert(ctx != nullptr); - co_return(context_info_t*) ctx; + co_return (context_info_t*) ctx; } } // namespace coro_rpc \ No newline at end of file diff --git a/include/ylt/easylog/record.hpp b/include/ylt/easylog/record.hpp index 211291b24..8c8eee617 100644 --- a/include/ylt/easylog/record.hpp +++ b/include/ylt/easylog/record.hpp @@ -174,7 +174,7 @@ class record_t { else if constexpr (detail::c_array_v) { ss_.append(data); } - else if constexpr (requires{ss_.append(data.data());}) /* TODO: update it by SFINAE with support c++17 */{ + else if constexpr (detail::has_data_v) { ss_.append(data.data()); } else if constexpr (detail::has_str_v) { diff --git a/src/coro_rpc/benchmark/api/rpc_functions.hpp b/src/coro_rpc/benchmark/api/rpc_functions.hpp index dae8d9e3d..440e56fa3 100644 --- a/src/coro_rpc/benchmark/api/rpc_functions.hpp +++ b/src/coro_rpc/benchmark/api/rpc_functions.hpp @@ -28,8 +28,12 @@ #include "ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp" inline coro_io::io_context_pool pool(std::thread::hardware_concurrency()); -inline async_simple::coro::Lazy coroutine_async_echo(std::string_view str) { co_return str;} -inline void callback_async_echo(coro_rpc::context conn,std::string_view str) { +inline async_simple::coro::Lazy coroutine_async_echo( + std::string_view str) { + co_return str; +} +inline void callback_async_echo(coro_rpc::context conn, + std::string_view str) { conn.response_msg(str); return; } @@ -43,7 +47,8 @@ inline std::string_view echo_10KB(std::string_view str) { return str; } inline std::vector array_1K_int(std::vector ar) { return ar; } -inline std::vector array_1K_str_4B(std::vector ar) { +inline std::vector array_1K_str_4B( + std::vector ar) { return ar; } diff --git a/src/coro_rpc/benchmark/data_gen.cpp b/src/coro_rpc/benchmark/data_gen.cpp index 847087e89..da330a656 100644 --- a/src/coro_rpc/benchmark/data_gen.cpp +++ b/src/coro_rpc/benchmark/data_gen.cpp @@ -59,8 +59,8 @@ int main() { coro_rpc::benchmark_file_path = "./test_data/complex_test/"; std::filesystem::create_directories(coro_rpc::benchmark_file_path); syncAwait(client.call(std::vector(1000, 42))); - syncAwait( - client.call(std::vector(1000, std::string_view{"AAAA"}))); + syncAwait(client.call( + std::vector(1000, std::string_view{"AAAA"}))); syncAwait(client.call( std::vector(1000, rect{.p1 = {1.2, 3.4}, .p2 = {2.5, 4.6}}))); syncAwait( diff --git a/src/coro_rpc/benchmark/server.hpp b/src/coro_rpc/benchmark/server.hpp index 219958b9a..878867cd8 100644 --- a/src/coro_rpc/benchmark/server.hpp +++ b/src/coro_rpc/benchmark/server.hpp @@ -24,7 +24,8 @@ inline void register_handlers(coro_rpc::coro_rpc_server& server) { echo_4B, echo_100B, echo_500B, echo_1KB, echo_5KB, echo_10KB, async_io, block_io, heavy_calculate, long_tail_async_io, long_tail_block_io, long_tail_heavy_calculate, array_1K_int, array_1K_str_4B, array_1K_rect, - monsterFunc, ValidateRequestFunc, download_10KB,callback_async_echo,coroutine_async_echo>(); + monsterFunc, ValidateRequestFunc, download_10KB, callback_async_echo, + coroutine_async_echo>(); server.register_handler< many_argument>(); diff --git a/src/coro_rpc/examples/base_examples/rpc_service.cpp b/src/coro_rpc/examples/base_examples/rpc_service.cpp index a9ac63bc4..0bb1d6cc2 100644 --- a/src/coro_rpc/examples/base_examples/rpc_service.cpp +++ b/src/coro_rpc/examples/base_examples/rpc_service.cpp @@ -36,7 +36,7 @@ using namespace std::chrono_literals; std::string_view echo(std::string_view data) { ELOGV(INFO, "call echo"); - return data; + return data; } Lazy coroutine_echo(std::string_view data) { @@ -45,35 +45,40 @@ Lazy coroutine_echo(std::string_view data) { co_return data; } -void async_echo_by_callback(coro_rpc::context conn, std::string_view/*rpc request data here*/ data) { +void async_echo_by_callback( + coro_rpc::context conn, + std::string_view /*rpc request data here*/ data) { ELOGV(INFO, "call async_echo_by_callback"); /* rpc function runs in global io thread pool */ - coro_io::post([conn,data] () mutable { + coro_io::post([conn, data]() mutable { /* send work to global non-io thread pool */ auto *ctx = conn.get_context(); conn.response_msg(data); /*response here*/ - }).start([](auto&&){}); + }).start([](auto &&) { + }); } Lazy async_echo_by_coroutine(std::string_view sv) { ELOGV(INFO, "call async_echo_by_coroutine"); - co_await coro_io::sleep_for(std::chrono::milliseconds(100)); //sleeping + co_await coro_io::sleep_for(std::chrono::milliseconds(100)); // sleeping co_return sv; } Lazy echo_with_attachment() { ELOGV(INFO, "call echo_with_attachment"); - auto ctx=co_await coro_rpc::get_context(); - ctx->set_response_attachment(ctx->get_request_attachment()); /*zero-copy by string_view*/ + auto ctx = co_await coro_rpc::get_context(); + ctx->set_response_attachment( + ctx->get_request_attachment()); /*zero-copy by string_view*/ } Lazy nested_echo(std::string_view sv) { ELOGV(INFO, "start nested echo"); /*get a client by global client pool*/ - auto client=coro_io::g_clients_pool().at("127.0.0.1:8802"); - assert(client!=nullptr); + auto client = + coro_io::g_clients_pool().at("127.0.0.1:8802"); + assert(client != nullptr); ELOGV(INFO, "connect another server"); - auto ret = co_await client->send_request([sv](coro_rpc_client & client) { + auto ret = co_await client->send_request([sv](coro_rpc_client &client) { return client.call(sv); }); co_return ret.value().value(); @@ -88,9 +93,7 @@ void return_error_by_context(coro_rpc::context conn) { conn.response_error(coro_rpc::err_code{404}, "404 Not Found."); } -void return_error_by_exception() { - throw coro_rpc::err_code{404}; -} +void return_error_by_exception() { throw coro_rpc::err_code{404}; } Lazy rpc_with_state_by_tag() { auto *ctx = co_await coro_rpc::get_context(); diff --git a/src/coro_rpc/examples/base_examples/rpc_service.h b/src/coro_rpc/examples/base_examples/rpc_service.h index 3ed6668f2..6f51d4729 100644 --- a/src/coro_rpc/examples/base_examples/rpc_service.h +++ b/src/coro_rpc/examples/base_examples/rpc_service.h @@ -21,9 +21,13 @@ #include std::string_view echo(std::string_view data); -async_simple::coro::Lazy coroutine_echo(std::string_view data); -void async_echo_by_callback(coro_rpc::context conn, std::string_view/*rpc request data here*/ data); -async_simple::coro::Lazy async_echo_by_coroutine(std::string_view sv); +async_simple::coro::Lazy coroutine_echo( + std::string_view data); +void async_echo_by_callback( + coro_rpc::context conn, + std::string_view /*rpc request data here*/ data); +async_simple::coro::Lazy async_echo_by_coroutine( + std::string_view sv); async_simple::coro::Lazy echo_with_attachment(); async_simple::coro::Lazy nested_echo(std::string_view sv); void return_error_by_context(coro_rpc::context conn); diff --git a/src/coro_rpc/examples/base_examples/server.cpp b/src/coro_rpc/examples/base_examples/server.cpp index 32cd1de0a..d12442b60 100644 --- a/src/coro_rpc/examples/base_examples/server.cpp +++ b/src/coro_rpc/examples/base_examples/server.cpp @@ -26,15 +26,15 @@ int main() { coro_rpc_server server2{/*thread=*/1, /*port=*/8802}; - // regist normal function for rpc - server.register_handler(); + server.register_handler(); // regist member function for rpc HelloService hello_service; - server - .register_handler<&HelloService::hello>( - &hello_service); + server.register_handler<&HelloService::hello>(&hello_service); server2.register_handler(); // async start server diff --git a/src/coro_rpc/examples/file_transfer/rpc_service.cpp b/src/coro_rpc/examples/file_transfer/rpc_service.cpp index eaf9bcce5..e034218a5 100644 --- a/src/coro_rpc/examples/file_transfer/rpc_service.cpp +++ b/src/coro_rpc/examples/file_transfer/rpc_service.cpp @@ -6,7 +6,7 @@ std::string echo(std::string str) { return str; } void upload_file(coro_rpc::context conn, file_part part) { - auto &ctx=*conn.get_context(); + auto &ctx = *conn.get_context(); if (!ctx.tag().has_value()) { auto filename = std::to_string(std::time(0)) + std::filesystem::path(part.filename).extension().string(); @@ -27,7 +27,7 @@ void upload_file(coro_rpc::context conn, file_part part) { void download_file(coro_rpc::context conn, std::string filename) { - auto &ctx=*conn.get_context(); + auto &ctx = *conn.get_context(); if (!ctx.tag().has_value()) { std::string actual_filename = std::filesystem::path(filename).filename().string(); diff --git a/src/coro_rpc/tests/rpc_api.cpp b/src/coro_rpc/tests/rpc_api.cpp index 892f5a148..c27b553ad 100644 --- a/src/coro_rpc/tests/rpc_api.cpp +++ b/src/coro_rpc/tests/rpc_api.cpp @@ -18,6 +18,7 @@ #include #include #include + #include "ylt/coro_rpc/impl/errno.h" using namespace coro_rpc; @@ -48,26 +49,29 @@ int long_run_func(int val) { } void echo_with_attachment(coro_rpc::context conn) { - ELOGV(INFO, "call function echo_with_attachment, conn ID:%d", conn.get_context()->get_connection_id()); + ELOGV(INFO, "call function echo_with_attachment, conn ID:%d", + conn.get_context()->get_connection_id()); auto str = conn.get_context()->release_request_attachment(); conn.get_context()->set_response_attachment(std::move(str)); conn.response_msg(); } void test_context(coro_rpc::context conn) { - auto *ctx=conn.get_context(); + auto *ctx = conn.get_context(); if (ctx->has_closed()) { throw std::runtime_error("connection is close!"); } - ELOGV(INFO, "call function echo_with_attachment, conn ID:%d, request ID:%d", ctx->get_connection_id(),ctx->get_request_id()); - ELOGI << "remote endpoint: " << ctx->get_remote_endpoint()<<"local endpoint"<get_local_endpoint(); + ELOGV(INFO, "call function echo_with_attachment, conn ID:%d, request ID:%d", + ctx->get_connection_id(), ctx->get_request_id()); + ELOGI << "remote endpoint: " << ctx->get_remote_endpoint() << "local endpoint" + << ctx->get_local_endpoint(); if (ctx->get_rpc_function_name() != "test_context") { throw std::runtime_error("get error rpc function name!"); } - ELOGI<< "rpc function name:"<get_rpc_function_name(); + ELOGI << "rpc function name:" << ctx->get_rpc_function_name(); std::string sv{ctx->get_request_attachment()}; auto str = ctx->release_request_attachment(); - if (sv!=str) { + if (sv != str) { conn.response_error(coro_rpc::errc::rpc_throw_exception); ctx->close(); return; @@ -77,7 +81,9 @@ void test_context(coro_rpc::context conn) { co_await coro_io::sleep_for(514ms); ELOGV(INFO, "response in another executor"); conn.response_msg(); - }(std::move(conn)).via(coro_io::get_global_executor()).detach(); + }(std::move(conn)) + .via(coro_io::get_global_executor()) + .detach(); ELOGV(INFO, "returning"); return; } @@ -88,28 +94,32 @@ Lazy test_lazy_context() { if (ctx->has_closed()) { throw std::runtime_error("connection is close!"); } - ELOGV(INFO, "call function echo_with_attachment, conn ID:%d, request ID:%d", ctx->get_connection_id(),ctx->get_request_id()); - ELOGI << "remote endpoint: " << ctx->get_remote_endpoint()<<"local endpoint"<get_local_endpoint(); + ELOGV(INFO, "call function echo_with_attachment, conn ID:%d, request ID:%d", + ctx->get_connection_id(), ctx->get_request_id()); + ELOGI << "remote endpoint: " << ctx->get_remote_endpoint() << "local endpoint" + << ctx->get_local_endpoint(); std::string sv{ctx->get_request_attachment()}; auto str = ctx->release_request_attachment(); - if (sv!=str) { + if (sv != str) { ctx->close(); - throw rpc_error{coro_rpc::errc::io_error,"attachment error!"}; + throw rpc_error{coro_rpc::errc::io_error, "attachment error!"}; co_return; } ctx->set_response_attachment(std::move(str)); - co_await coro_io::sleep_for(514ms,coro_io::get_global_executor()); + co_await coro_io::sleep_for(514ms, coro_io::get_global_executor()); ELOGV(INFO, "response in another executor"); co_return; } void test_response_error5() { - throw coro_rpc::rpc_error{coro_rpc::errc::address_in_used,"error with user-defined msg"}; + throw coro_rpc::rpc_error{coro_rpc::errc::address_in_used, + "error with user-defined msg"}; return; } Lazy test_response_error6() { - throw coro_rpc::rpc_error{coro_rpc::errc::address_in_used,"error with user-defined msg"}; + throw coro_rpc::rpc_error{coro_rpc::errc::address_in_used, + "error with user-defined msg"}; } void coro_fun_with_user_define_connection_type(my_context conn) { diff --git a/src/coro_rpc/tests/rpc_api.hpp b/src/coro_rpc/tests/rpc_api.hpp index 5bd63e0b9..9050230ba 100644 --- a/src/coro_rpc/tests/rpc_api.hpp +++ b/src/coro_rpc/tests/rpc_api.hpp @@ -53,7 +53,9 @@ void coro_fun_with_delay_return_void_cost_long_time( coro_rpc::context conn); inline async_simple::coro::Lazy coro_func_return_void(int i) { auto ctx = co_await coro_rpc::get_context(); - ELOGV(INFO,"call function coro_func_return_void, connection id:%d,request id:%d",ctx->get_connection_id(),ctx->get_request_id()); + ELOGV(INFO, + "call function coro_func_return_void, connection id:%d,request id:%d", + ctx->get_connection_id(), ctx->get_request_id()); co_return; } inline async_simple::coro::Lazy coro_func(int i) { co_return i; } @@ -64,6 +66,7 @@ class HelloService { static std::string static_hello(); async_simple::coro::Lazy coro_func(int i) { co_return i; } async_simple::coro::Lazy coro_func_return_void(int i) { co_return; } + private: }; namespace ns_login { diff --git a/src/coro_rpc/tests/test_coro_rpc_server.cpp b/src/coro_rpc/tests/test_coro_rpc_server.cpp index 064888746..da2f88d42 100644 --- a/src/coro_rpc/tests/test_coro_rpc_server.cpp +++ b/src/coro_rpc/tests/test_coro_rpc_server.cpp @@ -147,7 +147,7 @@ struct CoroServerTester : ServerTester { server.register_handler(); server.register_handler(); server.register_handler(); - server.register_handler(); + server.register_handler(); server.register_handler(); server.register_handler(); server.register_handler(); @@ -182,7 +182,7 @@ struct CoroServerTester : ServerTester { auto result = syncAwait(client->call()); REQUIRE(!result); CHECK(result.error().code == coro_rpc::errc::address_in_used); - CHECK(result.error().msg=="error with user-defined msg"); + CHECK(result.error().msg == "error with user-defined msg"); } { auto client = create_client(); @@ -190,7 +190,7 @@ struct CoroServerTester : ServerTester { auto result = syncAwait(client->call()); REQUIRE(!result); CHECK(result.error().code == coro_rpc::errc::address_in_used); - CHECK(result.error().msg=="error with user-defined msg"); + CHECK(result.error().msg == "error with user-defined msg"); } } diff --git a/src/coro_rpc/tests/test_router.cpp b/src/coro_rpc/tests/test_router.cpp index 5debde8d2..9c7aaac0d 100644 --- a/src/coro_rpc/tests/test_router.cpp +++ b/src/coro_rpc/tests/test_router.cpp @@ -167,7 +167,8 @@ void bar3(int val) { std::cout << "bar3 val=" << val << "\n"; } using namespace test_util; auto ctx = std::make_shared< - coro_rpc::context_info_t>(router,nullptr); + coro_rpc::context_info_t>(router, + nullptr); struct person { int id; From c26fb943f6dc8de0e9687ef48ee276af02525312 Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Tue, 2 Apr 2024 17:55:52 +0800 Subject: [PATCH 16/19] add example --- .../examples/base_examples/client.cpp | 11 +++++--- .../examples/base_examples/rpc_service.cpp | 28 ++++++++++++++++++- .../examples/base_examples/rpc_service.h | 1 + .../examples/base_examples/server.cpp | 8 +++--- 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/coro_rpc/examples/base_examples/client.cpp b/src/coro_rpc/examples/base_examples/client.cpp index 36faba911..bc6ca3057 100644 --- a/src/coro_rpc/examples/base_examples/client.cpp +++ b/src/coro_rpc/examples/base_examples/client.cpp @@ -36,13 +36,13 @@ Lazy show_rpc_call() { assert(ret.value() == "hello"); ret = co_await client.call("42"); - assert(ret.value()=="42"); - + assert(ret.value() == "42"); + ret = co_await client.call("hi"); - assert(ret.value()=="hi"); + assert(ret.value() == "hi"); ret = co_await client.call("hey"); - assert(ret.value()=="hey"); + assert(ret.value() == "hey"); client.set_req_attachment("This is attachment."); auto ret_void = co_await client.call(); @@ -54,6 +54,9 @@ Lazy show_rpc_call() { ret = co_await client.call<&HelloService::hello>(); assert(ret.value() == "HelloService::hello"s); + ret_void = co_await client.call(); + assert(ret_void); + // TODO: fix return error // ret_void = co_await client.call(); diff --git a/src/coro_rpc/examples/base_examples/rpc_service.cpp b/src/coro_rpc/examples/base_examples/rpc_service.cpp index 0bb1d6cc2..e1df1d2c0 100644 --- a/src/coro_rpc/examples/base_examples/rpc_service.cpp +++ b/src/coro_rpc/examples/base_examples/rpc_service.cpp @@ -64,6 +64,30 @@ Lazy async_echo_by_coroutine(std::string_view sv) { co_return sv; } +Lazy get_ctx_info() { + ELOGV(INFO, "call get_ctx_info"); + auto *ctx = co_await coro_rpc::get_context(); + if (ctx->has_closed()) { + throw std::runtime_error("connection is close!"); + } + ELOGV(INFO, "call function echo_with_attachment, conn ID:%d, request ID:%d", + ctx->get_connection_id(), ctx->get_request_id()); + ELOGI << "remote endpoint: " << ctx->get_remote_endpoint() << "local endpoint" + << ctx->get_local_endpoint(); + std::string sv{ctx->get_request_attachment()}; + auto str = ctx->release_request_attachment(); + if (sv != str) { + ctx->close(); + throw rpc_error{coro_rpc::errc::io_error, "attachment error!"}; + co_return; + } + ctx->set_response_attachment(std::move(str)); + co_await coro_io::sleep_for(514ms, coro_io::get_global_executor()); + ELOGV(INFO, "response in another executor"); + co_return; + co_return; +} + Lazy echo_with_attachment() { ELOGV(INFO, "call echo_with_attachment"); auto ctx = co_await coro_rpc::get_context(); @@ -93,7 +117,9 @@ void return_error_by_context(coro_rpc::context conn) { conn.response_error(coro_rpc::err_code{404}, "404 Not Found."); } -void return_error_by_exception() { throw coro_rpc::err_code{404}; } +void return_error_by_exception() { + throw coro_rpc::rpc_error{coro_rpc::errc{404}, "rpc not found."}; +} Lazy rpc_with_state_by_tag() { auto *ctx = co_await coro_rpc::get_context(); diff --git a/src/coro_rpc/examples/base_examples/rpc_service.h b/src/coro_rpc/examples/base_examples/rpc_service.h index 6f51d4729..97896b943 100644 --- a/src/coro_rpc/examples/base_examples/rpc_service.h +++ b/src/coro_rpc/examples/base_examples/rpc_service.h @@ -32,6 +32,7 @@ async_simple::coro::Lazy echo_with_attachment(); async_simple::coro::Lazy nested_echo(std::string_view sv); void return_error_by_context(coro_rpc::context conn); void return_error_by_exception(); +async_simple::coro::Lazy get_ctx_info(); class HelloService { public: std::string_view hello(); diff --git a/src/coro_rpc/examples/base_examples/server.cpp b/src/coro_rpc/examples/base_examples/server.cpp index d12442b60..c7afd710a 100644 --- a/src/coro_rpc/examples/base_examples/server.cpp +++ b/src/coro_rpc/examples/base_examples/server.cpp @@ -27,10 +27,10 @@ int main() { coro_rpc_server server2{/*thread=*/1, /*port=*/8802}; // regist normal function for rpc - server.register_handler(); + server.register_handler< + echo, coroutine_echo, async_echo_by_callback, async_echo_by_coroutine, + echo_with_attachment, nested_echo, return_error_by_context, + return_error_by_exception, rpc_with_state_by_tag, get_ctx_info>(); // regist member function for rpc HelloService hello_service; From 720f9691bee308c8af73e5520134b2bb778185a2 Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Tue, 2 Apr 2024 18:36:11 +0800 Subject: [PATCH 17/19] add support for normal function get context --- include/ylt/coro_rpc/impl/coro_connection.hpp | 23 +++++++---- .../impl/protocol/coro_rpc_protocol.hpp | 18 ++++++++- .../examples/base_examples/rpc_service.cpp | 8 ++-- .../examples/base_examples/rpc_service.h | 2 +- src/coro_rpc/tests/rpc_api.cpp | 39 +++++++------------ src/coro_rpc/tests/rpc_api.hpp | 5 ++- src/coro_rpc/tests/test_coro_rpc_server.cpp | 9 ++++- 7 files changed, 62 insertions(+), 42 deletions(-) diff --git a/include/ylt/coro_rpc/impl/coro_connection.hpp b/include/ylt/coro_rpc/impl/coro_connection.hpp index 13aa9869e..231353752 100644 --- a/include/ylt/coro_rpc/impl/coro_connection.hpp +++ b/include/ylt/coro_rpc/impl/coro_connection.hpp @@ -38,7 +38,6 @@ #include "inject_action.hpp" #endif namespace coro_rpc { - class coro_connection; using rpc_conn = std::shared_ptr; @@ -92,6 +91,11 @@ struct context_info_t { } }; +namespace detail { +template +context_info_t *&set_context(); +} + /*! * TODO: add doc */ @@ -286,6 +290,7 @@ class coro_connection : public std::enable_shared_from_this { }); } else { + coro_rpc::detail::set_context() = context_info.get(); auto &&[resp_err, resp_buf] = router.route( handler, payload, context_info, serialize_proto.value(), key); if (is_rpc_return_by_callback_) { @@ -319,7 +324,12 @@ class coro_connection : public std::enable_shared_from_this { resp_buf[0] = resp_buf[0] + 1; } #endif - direct_response_msg(resp_err, resp_buf, req_head); + direct_response_msg( + resp_err, resp_buf, req_head, + std::move(context_info->resp_attachment_)); + context_info->resp_attachment_ = [] { + return std::string_view{}; + }; } } cancel_timer(); @@ -331,12 +341,9 @@ class coro_connection : public std::enable_shared_from_this { * @param ret object of message type */ template - void direct_response_msg( - coro_rpc::err_code &resp_err, std::string &resp_buf, - const typename rpc_protocol::req_header &req_head, - std::function &&attachment = [] { - return std::string_view(); - }) { + void direct_response_msg(coro_rpc::err_code &resp_err, std::string &resp_buf, + const typename rpc_protocol::req_header &req_head, + std::function &&attachment) { std::string resp_error_msg; if (resp_err) { resp_error_msg = std::move(resp_buf); diff --git a/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp b/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp index c161b4b44..9d48ee7e1 100644 --- a/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp +++ b/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp @@ -212,9 +212,23 @@ using context = coro_rpc::context_base; template -async_simple::coro::Lazy*> get_context() { +async_simple::coro::Lazy*> get_context_in_coro() { auto* ctx = co_await async_simple::coro::LazyLocals{}; assert(ctx != nullptr); - co_return (context_info_t*) ctx; + co_return(context_info_t*) ctx; } + +namespace detail { +template +context_info_t*& set_context() { + thread_local static context_info_t* ctx; + return ctx; +} +} // namespace detail + +template +context_info_t* get_context() { + return detail::set_context(); +} + } // namespace coro_rpc \ No newline at end of file diff --git a/src/coro_rpc/examples/base_examples/rpc_service.cpp b/src/coro_rpc/examples/base_examples/rpc_service.cpp index e1df1d2c0..27f04db59 100644 --- a/src/coro_rpc/examples/base_examples/rpc_service.cpp +++ b/src/coro_rpc/examples/base_examples/rpc_service.cpp @@ -66,7 +66,7 @@ Lazy async_echo_by_coroutine(std::string_view sv) { Lazy get_ctx_info() { ELOGV(INFO, "call get_ctx_info"); - auto *ctx = co_await coro_rpc::get_context(); + auto *ctx = co_await coro_rpc::get_context_in_coro(); if (ctx->has_closed()) { throw std::runtime_error("connection is close!"); } @@ -88,9 +88,9 @@ Lazy get_ctx_info() { co_return; } -Lazy echo_with_attachment() { +void echo_with_attachment() { ELOGV(INFO, "call echo_with_attachment"); - auto ctx = co_await coro_rpc::get_context(); + auto ctx = coro_rpc::get_context(); ctx->set_response_attachment( ctx->get_request_attachment()); /*zero-copy by string_view*/ } @@ -122,7 +122,7 @@ void return_error_by_exception() { } Lazy rpc_with_state_by_tag() { - auto *ctx = co_await coro_rpc::get_context(); + auto *ctx = co_await coro_rpc::get_context_in_coro(); if (!ctx->tag().has_value()) { ctx->tag() = std::uint64_t{0}; } diff --git a/src/coro_rpc/examples/base_examples/rpc_service.h b/src/coro_rpc/examples/base_examples/rpc_service.h index 97896b943..368568f06 100644 --- a/src/coro_rpc/examples/base_examples/rpc_service.h +++ b/src/coro_rpc/examples/base_examples/rpc_service.h @@ -28,7 +28,7 @@ void async_echo_by_callback( std::string_view /*rpc request data here*/ data); async_simple::coro::Lazy async_echo_by_coroutine( std::string_view sv); -async_simple::coro::Lazy echo_with_attachment(); +void echo_with_attachment(); async_simple::coro::Lazy nested_echo(std::string_view sv); void return_error_by_context(coro_rpc::context conn); void return_error_by_exception(); diff --git a/src/coro_rpc/tests/rpc_api.cpp b/src/coro_rpc/tests/rpc_api.cpp index c27b553ad..7ed6c6bc2 100644 --- a/src/coro_rpc/tests/rpc_api.cpp +++ b/src/coro_rpc/tests/rpc_api.cpp @@ -55,9 +55,8 @@ void echo_with_attachment(coro_rpc::context conn) { conn.get_context()->set_response_attachment(std::move(str)); conn.response_msg(); } - -void test_context(coro_rpc::context conn) { - auto *ctx = conn.get_context(); +template +void test_ctx_impl(T *ctx, std::string_view name) { if (ctx->has_closed()) { throw std::runtime_error("connection is close!"); } @@ -65,18 +64,25 @@ void test_context(coro_rpc::context conn) { ctx->get_connection_id(), ctx->get_request_id()); ELOGI << "remote endpoint: " << ctx->get_remote_endpoint() << "local endpoint" << ctx->get_local_endpoint(); - if (ctx->get_rpc_function_name() != "test_context") { + if (ctx->get_rpc_function_name() != name) { throw std::runtime_error("get error rpc function name!"); } ELOGI << "rpc function name:" << ctx->get_rpc_function_name(); std::string sv{ctx->get_request_attachment()}; auto str = ctx->release_request_attachment(); if (sv != str) { - conn.response_error(coro_rpc::errc::rpc_throw_exception); - ctx->close(); - return; + throw std::runtime_error("coro_rpc::errc::rpc_throw_exception"); } ctx->set_response_attachment(std::move(str)); +} +void test_context() { + auto *ctx = coro_rpc::get_context(); + test_ctx_impl(ctx, "test_context"); + return; +} +void test_callback_context(coro_rpc::context conn) { + auto *ctx = conn.get_context(); + test_ctx_impl(ctx, "test_callback_context"); [](coro_rpc::context conn) -> async_simple::coro::Lazy { co_await coro_io::sleep_for(514ms); ELOGV(INFO, "response in another executor"); @@ -84,28 +90,13 @@ void test_context(coro_rpc::context conn) { }(std::move(conn)) .via(coro_io::get_global_executor()) .detach(); - ELOGV(INFO, "returning"); return; } using namespace async_simple::coro; Lazy test_lazy_context() { - auto *ctx = co_await coro_rpc::get_context(); - if (ctx->has_closed()) { - throw std::runtime_error("connection is close!"); - } - ELOGV(INFO, "call function echo_with_attachment, conn ID:%d, request ID:%d", - ctx->get_connection_id(), ctx->get_request_id()); - ELOGI << "remote endpoint: " << ctx->get_remote_endpoint() << "local endpoint" - << ctx->get_local_endpoint(); - std::string sv{ctx->get_request_attachment()}; - auto str = ctx->release_request_attachment(); - if (sv != str) { - ctx->close(); - throw rpc_error{coro_rpc::errc::io_error, "attachment error!"}; - co_return; - } - ctx->set_response_attachment(std::move(str)); + auto *ctx = co_await coro_rpc::get_context_in_coro(); + test_ctx_impl(ctx, "test_lazy_context"); co_await coro_io::sleep_for(514ms, coro_io::get_global_executor()); ELOGV(INFO, "response in another executor"); co_return; diff --git a/src/coro_rpc/tests/rpc_api.hpp b/src/coro_rpc/tests/rpc_api.hpp index 9050230ba..7d905531f 100644 --- a/src/coro_rpc/tests/rpc_api.hpp +++ b/src/coro_rpc/tests/rpc_api.hpp @@ -39,7 +39,8 @@ void echo_with_attachment(coro_rpc::context conn); inline void error_with_context(coro_rpc::context conn) { conn.response_error(coro_rpc::err_code{1004}, "My Error."); } -void test_context(coro_rpc::context conn); +void test_context(); +void test_callback_context(coro_rpc::context conn); async_simple::coro::Lazy test_lazy_context(); void test_response_error5(); async_simple::coro::Lazy test_response_error6(); @@ -52,7 +53,7 @@ void coro_fun_with_delay_return_string_twice( void coro_fun_with_delay_return_void_cost_long_time( coro_rpc::context conn); inline async_simple::coro::Lazy coro_func_return_void(int i) { - auto ctx = co_await coro_rpc::get_context(); + auto ctx = co_await coro_rpc::get_context_in_coro(); ELOGV(INFO, "call function coro_func_return_void, connection id:%d,request id:%d", ctx->get_connection_id(), ctx->get_request_id()); diff --git a/src/coro_rpc/tests/test_coro_rpc_server.cpp b/src/coro_rpc/tests/test_coro_rpc_server.cpp index da2f88d42..6cf512043 100644 --- a/src/coro_rpc/tests/test_coro_rpc_server.cpp +++ b/src/coro_rpc/tests/test_coro_rpc_server.cpp @@ -146,7 +146,8 @@ struct CoroServerTester : ServerTester { server.register_handler<&HelloService::hello>(&hello_service_); server.register_handler(); server.register_handler(); - server.register_handler(); + server.register_handler(); server.register_handler(); server.register_handler(); server.register_handler(); @@ -170,6 +171,12 @@ struct CoroServerTester : ServerTester { auto result = syncAwait(client->call()); CHECK(result); CHECK(client->get_resp_attachment() == "1234567890987654321234567890"); + + client->set_req_attachment("12345678909876543212345678901"); + result = syncAwait(client->call()); + CHECK(result); + CHECK(client->get_resp_attachment() == "12345678909876543212345678901"); + client->set_req_attachment("01234567890987654321234567890"); result = syncAwait(client->call()); CHECK(result); From f89622f5b5cd162af6190132a54a169f3b46b090 Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Wed, 3 Apr 2024 11:28:37 +0800 Subject: [PATCH 18/19] fix compile --- include/ylt/coro_rpc/impl/coro_connection.hpp | 4 +++- .../coro_rpc/impl/protocol/coro_rpc_protocol.hpp | 4 ++-- src/coro_io/tests/test_coro_channel.cpp | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/include/ylt/coro_rpc/impl/coro_connection.hpp b/include/ylt/coro_rpc/impl/coro_connection.hpp index 231353752..f0be2b297 100644 --- a/include/ylt/coro_rpc/impl/coro_connection.hpp +++ b/include/ylt/coro_rpc/impl/coro_connection.hpp @@ -621,7 +621,9 @@ void context_info_t::close() { } template -uint64_t context_info_t::get_connection_id() const noexcept {} +uint64_t context_info_t::get_connection_id() const noexcept { + return conn_->get_connection_id(); +} template void context_info_t::set_response_attachment( diff --git a/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp b/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp index 9d48ee7e1..2e537a86d 100644 --- a/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp +++ b/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp @@ -219,7 +219,7 @@ async_simple::coro::Lazy*> get_context_in_coro() { } namespace detail { -template +template context_info_t*& set_context() { thread_local static context_info_t* ctx; return ctx; @@ -228,7 +228,7 @@ context_info_t*& set_context() { template context_info_t* get_context() { - return detail::set_context(); + return detail::set_context(); } } // namespace coro_rpc \ No newline at end of file diff --git a/src/coro_io/tests/test_coro_channel.cpp b/src/coro_io/tests/test_coro_channel.cpp index bdd343ebf..384ce62ee 100644 --- a/src/coro_io/tests/test_coro_channel.cpp +++ b/src/coro_io/tests/test_coro_channel.cpp @@ -6,6 +6,19 @@ #include using namespace std::chrono_literals; +#ifndef __clang__ +#ifdef __GNUC__ +#include +#if __GNUC_PREREQ(10, 3) // If gcc_version >= 10.3 +#define IS_OK +#endif +#else +#define IS_OK +#endif +#else +#define IS_OK +#endif + async_simple::coro::Lazy test_coro_channel() { auto ch = coro_io::create_channel(1000); @@ -112,6 +125,7 @@ async_simple::coro::Lazy test_select_channel() { } void callback_lazy() { +#ifdef IS_OK using namespace async_simple::coro; auto test0 = []() mutable -> Lazy { co_return 41; @@ -144,6 +158,7 @@ void callback_lazy() { CHECK(result == 83); })); CHECK(index == 0); +#endif } TEST_CASE("test channel send recieve, test select channel and coroutine") { From c8ce83596c3e3a73d4577a0f812c32132a56ff47 Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Wed, 3 Apr 2024 11:31:12 +0800 Subject: [PATCH 19/19] fix format --- include/ylt/coro_io/io_context_pool.hpp | 2 +- include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/ylt/coro_io/io_context_pool.hpp b/include/ylt/coro_io/io_context_pool.hpp index 8cef68df9..07eb8e522 100644 --- a/include/ylt/coro_io/io_context_pool.hpp +++ b/include/ylt/coro_io/io_context_pool.hpp @@ -17,8 +17,8 @@ #include #include -#include #include +#include #include #include #include diff --git a/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp b/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp index 2e537a86d..b74a566e3 100644 --- a/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp +++ b/include/ylt/coro_rpc/impl/protocol/coro_rpc_protocol.hpp @@ -215,7 +215,7 @@ template async_simple::coro::Lazy*> get_context_in_coro() { auto* ctx = co_await async_simple::coro::LazyLocals{}; assert(ctx != nullptr); - co_return(context_info_t*) ctx; + co_return (context_info_t*) ctx; } namespace detail {