mirror of
https://github.com/qicosmos/rest_rpc.git
synced 2026-08-29 08:34:47 +08:00
safe call
This commit is contained in:
@@ -197,6 +197,11 @@ struct dummy1 {
|
|||||||
MSGPACK_DEFINE(id, str);
|
MSGPACK_DEFINE(id, str);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::string echo(rpc_conn conn, const std::string &src);
|
||||||
|
struct dummy {
|
||||||
|
int add(rpc_conn conn, int a, int b);
|
||||||
|
};
|
||||||
|
|
||||||
void test_echo() {
|
void test_echo() {
|
||||||
rpc_client client("127.0.0.1", 9000);
|
rpc_client client("127.0.0.1", 9000);
|
||||||
bool r = client.connect();
|
bool r = client.connect();
|
||||||
@@ -212,10 +217,27 @@ void test_echo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto result = client.call<std::string>("echo", "test");
|
// safe call, same with `client.call<std::string>("echo", "test")`
|
||||||
|
auto result = client.call<echo>("test");
|
||||||
std::cout << result << std::endl;
|
std::cout << result << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// safe call member function
|
||||||
|
auto result = client.call<&dummy::add>(1, 2);
|
||||||
|
std::cout << result << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
client.async_call(
|
||||||
|
"echo",
|
||||||
|
[](const asio::error_code &ec, string_view data) {
|
||||||
|
auto str = as<std::string>(data);
|
||||||
|
std::cout << "echo " << str << '\n';
|
||||||
|
},
|
||||||
|
"test");
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto result = client.call<std::string>("delay_echo", "test");
|
auto result = client.call<std::string>("delay_echo", "test");
|
||||||
std::cout << result << std::endl;
|
std::cout << result << std::endl;
|
||||||
@@ -637,8 +659,8 @@ void benchmark_test() {
|
|||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
// benchmark_test();
|
// benchmark_test();
|
||||||
test_connect();
|
// test_connect();
|
||||||
test_callback();
|
// test_callback();
|
||||||
test_echo();
|
test_echo();
|
||||||
test_sync_client();
|
test_sync_client();
|
||||||
test_async_client();
|
test_async_client();
|
||||||
|
|||||||
@@ -66,11 +66,15 @@ struct function_traits<std::function<Ret(Args...)>>
|
|||||||
|
|
||||||
template <typename ReturnType, typename ClassType, typename... Args>
|
template <typename ReturnType, typename ClassType, typename... Args>
|
||||||
struct function_traits<ReturnType (ClassType::*)(Args...)>
|
struct function_traits<ReturnType (ClassType::*)(Args...)>
|
||||||
: function_traits<ReturnType(Args...)> {};
|
: function_traits<ReturnType(Args...)> {
|
||||||
|
using class_type = ClassType;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename ReturnType, typename ClassType, typename... Args>
|
template <typename ReturnType, typename ClassType, typename... Args>
|
||||||
struct function_traits<ReturnType (ClassType::*)(Args...) const>
|
struct function_traits<ReturnType (ClassType::*)(Args...) const>
|
||||||
: function_traits<ReturnType(Args...)> {};
|
: function_traits<ReturnType(Args...)> {
|
||||||
|
using class_type = ClassType;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Callable>
|
template <typename Callable>
|
||||||
struct function_traits : function_traits<decltype(&Callable::operator())> {};
|
struct function_traits : function_traits<decltype(&Callable::operator())> {};
|
||||||
@@ -114,6 +118,15 @@ using nth_type_of = nonstd::tuple_element_t<N, std::tuple<Args...>>;
|
|||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
using last_type_of = nth_type_of<sizeof...(Args) - 1, Args...>;
|
using last_type_of = nth_type_of<sizeof...(Args) - 1, Args...>;
|
||||||
|
|
||||||
|
template <typename T> struct remove_first { using type = T; };
|
||||||
|
|
||||||
|
template <class First, class... Second>
|
||||||
|
struct remove_first<std::tuple<First, Second...>> {
|
||||||
|
using type = std::tuple<Second...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> using remove_first_t = typename remove_first<T>::type;
|
||||||
} // namespace rest_rpc
|
} // namespace rest_rpc
|
||||||
|
|
||||||
#endif // REST_RPC_META_UTIL_HPP
|
#endif // REST_RPC_META_UTIL_HPP
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "client_util.hpp"
|
#include "client_util.hpp"
|
||||||
#include "const_vars.h"
|
#include "const_vars.h"
|
||||||
|
#include "function_name.h"
|
||||||
#include "md5.hpp"
|
#include "md5.hpp"
|
||||||
#include "meta_util.hpp"
|
#include "meta_util.hpp"
|
||||||
#include "use_asio.hpp"
|
#include "use_asio.hpp"
|
||||||
@@ -216,7 +217,7 @@ public:
|
|||||||
// sync call
|
// sync call
|
||||||
template <size_t TIMEOUT, typename T = void, typename... Args>
|
template <size_t TIMEOUT, typename T = void, typename... Args>
|
||||||
typename std::enable_if<std::is_void<T>::value>::type
|
typename std::enable_if<std::is_void<T>::value>::type
|
||||||
call(const std::string &rpc_name, Args &&...args) {
|
call(std::string_view rpc_name, Args &&...args) {
|
||||||
auto future_result =
|
auto future_result =
|
||||||
async_call<FUTURE>(rpc_name, std::forward<Args>(args)...);
|
async_call<FUTURE>(rpc_name, std::forward<Args>(args)...);
|
||||||
auto status = future_result.wait_for(std::chrono::milliseconds(TIMEOUT));
|
auto status = future_result.wait_for(std::chrono::milliseconds(TIMEOUT));
|
||||||
@@ -230,13 +231,13 @@ public:
|
|||||||
|
|
||||||
template <typename T = void, typename... Args>
|
template <typename T = void, typename... Args>
|
||||||
typename std::enable_if<std::is_void<T>::value>::type
|
typename std::enable_if<std::is_void<T>::value>::type
|
||||||
call(const std::string &rpc_name, Args &&...args) {
|
call(std::string_view rpc_name, Args &&...args) {
|
||||||
call<DEFAULT_TIMEOUT, T>(rpc_name, std::forward<Args>(args)...);
|
call<DEFAULT_TIMEOUT, T>(rpc_name, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t TIMEOUT, typename T, typename... Args>
|
template <size_t TIMEOUT, typename T, typename... Args>
|
||||||
typename std::enable_if<!std::is_void<T>::value, T>::type
|
typename std::enable_if<!std::is_void<T>::value, T>::type
|
||||||
call(const std::string &rpc_name, Args &&...args) {
|
call(std::string_view rpc_name, Args &&...args) {
|
||||||
auto future_result =
|
auto future_result =
|
||||||
async_call<FUTURE>(rpc_name, std::forward<Args>(args)...);
|
async_call<FUTURE>(rpc_name, std::forward<Args>(args)...);
|
||||||
auto status = future_result.wait_for(std::chrono::milliseconds(TIMEOUT));
|
auto status = future_result.wait_for(std::chrono::milliseconds(TIMEOUT));
|
||||||
@@ -250,12 +251,23 @@ public:
|
|||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
typename std::enable_if<!std::is_void<T>::value, T>::type
|
typename std::enable_if<!std::is_void<T>::value, T>::type
|
||||||
call(const std::string &rpc_name, Args &&...args) {
|
call(std::string_view rpc_name, Args &&...args) {
|
||||||
return call<DEFAULT_TIMEOUT, T>(rpc_name, std::forward<Args>(args)...);
|
return call<DEFAULT_TIMEOUT, T>(rpc_name, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <auto func, typename... Args> auto call(Args &&...args) {
|
||||||
|
using args_tuple = typename function_traits<decltype(func)>::tuple_type;
|
||||||
|
static_assert(std::is_constructible_v<remove_first_t<args_tuple>, Args...>,
|
||||||
|
"called rpc function and arguments are not match");
|
||||||
|
|
||||||
|
constexpr auto rpc_name = get_func_name<func>();
|
||||||
|
using R = typename function_traits<decltype(func)>::return_type;
|
||||||
|
|
||||||
|
return call<R>(rpc_name, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
template <CallModel model, typename... Args>
|
template <CallModel model, typename... Args>
|
||||||
future_result<req_result> async_call(const std::string &rpc_name,
|
future_result<req_result> async_call(std::string_view rpc_name,
|
||||||
Args &&...args) {
|
Args &&...args) {
|
||||||
auto p = std::make_shared<std::promise<req_result>>();
|
auto p = std::make_shared<std::promise<req_result>>();
|
||||||
std::future<req_result> future = p->get_future();
|
std::future<req_result> future = p->get_future();
|
||||||
@@ -271,7 +283,7 @@ public:
|
|||||||
rpc_service::msgpack_codec codec;
|
rpc_service::msgpack_codec codec;
|
||||||
auto ret = codec.pack_args(std::forward<Args>(args)...);
|
auto ret = codec.pack_args(std::forward<Args>(args)...);
|
||||||
write(fu_id, request_type::req_res, std::move(ret),
|
write(fu_id, request_type::req_res, std::move(ret),
|
||||||
MD5::MD5Hash32(rpc_name.data()));
|
MD5::MD5Hash32(rpc_name.data(), rpc_name.length()));
|
||||||
return future_result<req_result>{fu_id, std::move(future)};
|
return future_result<req_result>{fu_id, std::move(future)};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,12 +304,13 @@ public:
|
|||||||
sbuffer.write(encoded_func_name_and_args.data(),
|
sbuffer.write(encoded_func_name_and_args.data(),
|
||||||
encoded_func_name_and_args.size());
|
encoded_func_name_and_args.size());
|
||||||
write(fu_id, request_type::req_res, std::move(sbuffer),
|
write(fu_id, request_type::req_res, std::move(sbuffer),
|
||||||
MD5::MD5Hash32(encoded_func_name_and_args.data()));
|
MD5::MD5Hash32(encoded_func_name_and_args.data(),
|
||||||
|
encoded_func_name_and_args.length()));
|
||||||
return fu_id;
|
return fu_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t TIMEOUT = DEFAULT_TIMEOUT, typename... Args>
|
template <size_t TIMEOUT = DEFAULT_TIMEOUT, typename... Args>
|
||||||
void async_call(const std::string &rpc_name,
|
void async_call(std::string_view rpc_name,
|
||||||
std::function<void(asio::error_code, string_view)> cb,
|
std::function<void(asio::error_code, string_view)> cb,
|
||||||
Args &&...args) {
|
Args &&...args) {
|
||||||
if (!has_connected_) {
|
if (!has_connected_) {
|
||||||
@@ -321,7 +334,7 @@ public:
|
|||||||
rpc_service::msgpack_codec codec;
|
rpc_service::msgpack_codec codec;
|
||||||
auto ret = codec.pack_args(std::forward<Args>(args)...);
|
auto ret = codec.pack_args(std::forward<Args>(args)...);
|
||||||
write(cb_id, request_type::req_res, std::move(ret),
|
write(cb_id, request_type::req_res, std::move(ret),
|
||||||
MD5::MD5Hash32(rpc_name.data()));
|
MD5::MD5Hash32(rpc_name.data(), rpc_name.length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop() {
|
void stop() {
|
||||||
@@ -580,7 +593,8 @@ private:
|
|||||||
void send_subscribe(const std::string &key, const std::string &token) {
|
void send_subscribe(const std::string &key, const std::string &token) {
|
||||||
rpc_service::msgpack_codec codec;
|
rpc_service::msgpack_codec codec;
|
||||||
auto ret = codec.pack_args(key, token);
|
auto ret = codec.pack_args(key, token);
|
||||||
write(0, request_type::sub_pub, std::move(ret), MD5::MD5Hash32(key.data()));
|
write(0, request_type::sub_pub, std::move(ret),
|
||||||
|
MD5::MD5Hash32(key.data(), key.length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void resend_subscribe() {
|
void resend_subscribe() {
|
||||||
|
|||||||
Reference in New Issue
Block a user