@@ -73,6 +73,11 @@ class client_pool;
73
73
74
74
namespace coro_rpc {
75
75
76
+ struct request_config_t {
77
+ std::optional<std::chrono::milliseconds> request_timeout_duration;
78
+ std::string_view request_attachment;
79
+ std::span<char > resp_attachment_buf;
80
+ };
76
81
inline uint64_t get_global_client_id () {
77
82
static std::atomic<uint64_t > cid = 0 ;
78
83
return cid.fetch_add (1 , std::memory_order::relaxed);
@@ -97,32 +102,42 @@ struct resp_body {
97
102
std::string read_buf_;
98
103
std::string resp_attachment_buf_;
99
104
};
105
+ namespace detail {
106
+ struct async_rpc_result_base {
107
+ private:
108
+ resp_body buffer_;
109
+ std::string_view attachment_;
110
+
111
+ public:
112
+ async_rpc_result_base () = default ;
113
+ async_rpc_result_base (resp_body &&buffer, std::string_view attachment)
114
+ : buffer_(std::move(buffer)), attachment_(attachment) {}
115
+ std::string_view get_attachment () const noexcept { return attachment_; }
116
+ bool is_attachment_in_external_buf () const noexcept {
117
+ return buffer_.resp_attachment_buf_ .data () == attachment_.data ();
118
+ }
119
+ resp_body release_buffer () { return std::move (buffer_); }
120
+ };
121
+ } // namespace detail
100
122
101
123
template <typename T>
102
- struct async_rpc_result_value_t {
124
+ struct async_rpc_result_value_t : public detail ::async_rpc_result_base {
103
125
private:
104
126
T result_;
105
- resp_body buffer_;
106
127
107
128
public:
108
- async_rpc_result_value_t (T &&result, resp_body &&buffer)
109
- : result_(std::move(result)), buffer_(std::move(buffer)) {}
129
+ async_rpc_result_value_t (T &&result, resp_body &&buffer,
130
+ std::string_view attachment)
131
+ : result_(std::move(result)),
132
+ async_rpc_result_base (std::move(buffer), attachment) {}
110
133
async_rpc_result_value_t (T &&result) : result_(std::move(result)) {}
111
134
T &result () noexcept { return result_; }
112
135
const T &result () const noexcept { return result_; }
113
- std::string_view get_attachment () const noexcept {
114
- return buffer_.resp_attachment_buf_ ;
115
- }
116
- resp_body release_buffer () { return std::move (buffer_); }
117
136
};
118
137
119
138
template <>
120
- struct async_rpc_result_value_t <void > {
121
- resp_body buffer_;
122
- std::string_view attachment () const noexcept {
123
- return buffer_.resp_attachment_buf_ ;
124
- }
125
- resp_body release_buffer () { return std::move (buffer_); }
139
+ struct async_rpc_result_value_t <void > : public detail::async_rpc_result_base {
140
+ using async_rpc_result_base::async_rpc_result_base;
126
141
};
127
142
128
143
template <typename T>
@@ -317,8 +332,9 @@ class coro_rpc_client {
317
332
template <auto func, typename ... Args>
318
333
async_simple::coro::Lazy<rpc_result<decltype (get_return_type<func>())>> call(
319
334
Args &&...args) {
320
- return call_for<func>(config_.request_timeout_duration ,
321
- std::forward<Args>(args)...);
335
+ return call<func>(
336
+ request_config_t {{}, req_attachment_, resp_attachment_buffer_},
337
+ std::forward<Args>(args)...);
322
338
}
323
339
324
340
/* !
@@ -335,13 +351,22 @@ class coro_rpc_client {
335
351
template <auto func, typename ... Args>
336
352
async_simple::coro::Lazy<rpc_result<decltype (get_return_type<func>())>>
337
353
call_for(auto request_timeout_duration, Args &&...args) {
354
+ return call<func>(
355
+ request_config_t {request_timeout_duration, req_attachment_,
356
+ resp_attachment_buffer_},
357
+ std::forward<Args>(args)...);
358
+ }
359
+
360
+ template <auto func, typename ... Args>
361
+ async_simple::coro::Lazy<rpc_result<decltype (get_return_type<func>())>> call (
362
+ request_config_t config, Args &&...args) {
338
363
using return_type = decltype (get_return_type<func>());
339
- auto async_result =
340
- co_await co_await send_request_for_with_attachment<func, Args...>(
341
- request_timeout_duration, req_attachment_,
342
- std::forward<Args>(args)...);
364
+ auto async_result = co_await co_await send_request<func, Args...>(
365
+ std::move (config), std::forward<Args>(args)...);
343
366
req_attachment_ = {};
367
+ resp_attachment_buffer_ = {};
344
368
if (async_result) {
369
+ resp_attachment_ = async_result->get_attachment ();
345
370
control_->resp_buffer_ = async_result->release_buffer ();
346
371
if constexpr (std::is_same_v<return_type, void >) {
347
372
co_return expected<return_type, rpc_error>{};
@@ -377,13 +402,24 @@ class coro_rpc_client {
377
402
req_attachment_ = attachment;
378
403
return true ;
379
404
}
405
+ void set_resp_attachment_buf (std::span<char > buffer) {
406
+ resp_attachment_buffer_ = buffer;
407
+ }
380
408
381
- std::string_view get_resp_attachment () const {
382
- return control_->resp_buffer_ .resp_attachment_buf_ ;
409
+ std::string_view get_resp_attachment () const { return resp_attachment_; }
410
+
411
+ bool is_resp_attachment_in_external_buf () const {
412
+ return resp_attachment_.data () !=
413
+ control_->resp_buffer_ .resp_attachment_buf_ .data ();
383
414
}
384
415
385
416
std::string release_resp_attachment () {
386
- return std::move (control_->resp_buffer_ .resp_attachment_buf_ );
417
+ if (is_resp_attachment_in_external_buf ()) {
418
+ return std::move (control_->resp_buffer_ .resp_attachment_buf_ );
419
+ }
420
+ else {
421
+ return {};
422
+ }
387
423
}
388
424
389
425
template <typename T, typename U>
@@ -713,6 +749,7 @@ class coro_rpc_client {
713
749
714
750
struct async_rpc_raw_result_value_type {
715
751
resp_body buffer_;
752
+ std::string_view attachment;
716
753
uint8_t errc_;
717
754
};
718
755
@@ -724,13 +761,21 @@ class coro_rpc_client {
724
761
struct handler_t {
725
762
std::unique_ptr<coro_io::period_timer> timer_;
726
763
async_simple::Promise<async_rpc_raw_result> promise_;
764
+ std::span<char > response_attachment_buffer_;
727
765
handler_t (std::unique_ptr<coro_io::period_timer> &&timer,
728
- async_simple::Promise<async_rpc_raw_result> &&promise)
729
- : timer_(std::move(timer)), promise_(std::move(promise)) {}
766
+ async_simple::Promise<async_rpc_raw_result> &&promise,
767
+ std::span<char > buffer = {})
768
+ : timer_(std::move(timer)),
769
+ promise_ (std::move(promise)),
770
+ response_attachment_buffer_(buffer) {}
771
+ std::span<char > &get_buffer () { return response_attachment_buffer_; }
730
772
void operator ()(resp_body &&buffer, uint8_t rpc_errc) {
731
773
timer_->cancel ();
732
- promise_.setValue (async_rpc_raw_result{
733
- async_rpc_raw_result_value_type{std::move (buffer), rpc_errc}});
774
+ promise_.setValue (async_rpc_raw_result{async_rpc_raw_result_value_type{
775
+ std::move (buffer),
776
+ std::string_view{response_attachment_buffer_.data (),
777
+ response_attachment_buffer_.size ()},
778
+ rpc_errc}});
734
779
}
735
780
void local_error (std::error_code &ec) {
736
781
timer_->cancel ();
@@ -810,8 +855,8 @@ class coro_rpc_client {
810
855
private:
811
856
template <auto func, typename ... Args>
812
857
async_simple::coro::Lazy<rpc_error> send_request_for_impl (
813
- auto request_timeout_duration , uint32_t &id, coro_io::period_timer &timer,
814
- std::string_view attachment, Args &&...args) {
858
+ request_config_t &config , uint32_t &id, coro_io::period_timer &timer,
859
+ Args &&...args) {
815
860
using R = decltype (get_return_type<func>());
816
861
817
862
if (control_->has_closed_ )
@@ -829,21 +874,24 @@ class coro_rpc_client {
829
874
830
875
static_check<func, Args...>();
831
876
832
- if (request_timeout_duration.count () >= 0 ) {
833
- timeout (timer, request_timeout_duration, " rpc call timer canceled" )
877
+ if (config.request_timeout_duration ->count () >= 0 ) {
878
+ timeout (timer, *config.request_timeout_duration ,
879
+ " rpc call timer canceled" )
834
880
.start ([](auto &&) {
835
881
});
836
882
}
837
883
838
884
#ifdef YLT_ENABLE_SSL
839
885
if (!config_.ssl_cert_path .empty ()) {
840
886
assert (control_->ssl_stream_ );
841
- co_return co_await send_impl<func>(*control_->ssl_stream_ , id, attachment,
887
+ co_return co_await send_impl<func>(*control_->ssl_stream_ , id,
888
+ config.request_attachment ,
842
889
std::forward<Args>(args)...);
843
890
}
844
891
else {
845
892
#endif
846
- co_return co_await send_impl<func>(control_->socket_ , id, attachment,
893
+ co_return co_await send_impl<func>(control_->socket_ , id,
894
+ config.request_attachment ,
847
895
std::forward<Args>(args)...);
848
896
#ifdef YLT_ENABLE_SSL
849
897
}
@@ -873,6 +921,14 @@ class coro_rpc_client {
873
921
<< " . close the socket.value=" << ret.first .value ();
874
922
break ;
875
923
}
924
+ auto iter = controller->response_handler_table_ .find (header.seq_num );
925
+ if (iter == controller->response_handler_table_ .end ()) {
926
+ ELOG_ERROR << " unexists request ID:" << header.seq_num
927
+ << " . close the socket." ;
928
+ break ;
929
+ }
930
+ ELOG_TRACE << " find request ID:" << header.seq_num
931
+ << " . start notify response handler" ;
876
932
uint32_t body_len = header.length ;
877
933
struct_pack::detail::resize (
878
934
controller->resp_buffer_ .read_buf_ ,
@@ -889,15 +945,24 @@ class coro_rpc_client {
889
945
controller->resp_buffer_ .resp_attachment_buf_ .clear ();
890
946
}
891
947
else {
892
- struct_pack::detail::resize (
893
- controller->resp_buffer_ .resp_attachment_buf_ ,
894
- header.attach_length );
948
+ std::span<char > &attachment_buffer = iter->second .get_buffer ();
949
+ if (attachment_buffer.size () < header.attach_length ) {
950
+ // allocate attachment buffer
951
+ if (attachment_buffer.size ()) [[unlikely]] {
952
+ ELOG_TRACE << " user's attachment buffer size is too small, instead "
953
+ " by inner allocated buffer" ;
954
+ }
955
+ struct_pack::detail::resize (
956
+ controller->resp_buffer_ .resp_attachment_buf_ ,
957
+ std::max<uint64_t >(header.attach_length , sizeof (std::string)));
958
+ attachment_buffer = controller->resp_buffer_ .resp_attachment_buf_ ;
959
+ }
960
+ attachment_buffer = attachment_buffer.subspan (0 , header.attach_length );
895
961
std::array<asio::mutable_buffer, 2 > iov{
896
962
asio::mutable_buffer{controller->resp_buffer_ .read_buf_ .data (),
897
963
body_len},
898
- asio::mutable_buffer{
899
- controller->resp_buffer_ .resp_attachment_buf_ .data (),
900
- controller->resp_buffer_ .resp_attachment_buf_ .size ()}};
964
+ asio::mutable_buffer{attachment_buffer.data (),
965
+ attachment_buffer.size ()}};
901
966
ret = co_await coro_io::async_read (socket, iov);
902
967
}
903
968
if (ret.first ) {
@@ -915,20 +980,10 @@ class coro_rpc_client {
915
980
file.close ();
916
981
#endif
917
982
--controller->recving_cnt_ ;
918
- if (auto iter = controller->response_handler_table_ .find (header.seq_num );
919
- iter != controller->response_handler_table_ .end ()) {
920
- ELOG_TRACE << " find request ID:" << header.seq_num
921
- << " . start notify response handler" ;
922
- iter->second (std::move (controller->resp_buffer_ ), header.err_code );
923
- controller->response_handler_table_ .erase (iter);
924
- if (controller->response_handler_table_ .empty ()) {
925
- co_return ;
926
- }
927
- }
928
- else {
929
- ELOG_ERROR << " unexists request ID:" << header.seq_num
930
- << " . close the socket." ;
931
- break ;
983
+ iter->second (std::move (controller->resp_buffer_ ), header.err_code );
984
+ controller->response_handler_table_ .erase (iter);
985
+ if (controller->response_handler_table_ .empty ()) {
986
+ co_return ;
932
987
}
933
988
} while (true );
934
989
close_socket_async (controller);
@@ -966,12 +1021,12 @@ class coro_rpc_client {
966
1021
}
967
1022
if (result) {
968
1023
if constexpr (std::is_same_v<T, void >) {
969
- co_return async_rpc_result<T>{
970
- async_rpc_result_value_t <T>{ std::move (ret.buffer_ )}};
1024
+ co_return async_rpc_result<T>{async_rpc_result_value_t <T>{
1025
+ std::move (ret.buffer_ ), ret. attachment }};
971
1026
}
972
1027
else {
973
1028
co_return async_rpc_result<T>{async_rpc_result_value_t <T>{
974
- std::move (result.value ()), std::move (ret.buffer_ )}};
1029
+ std::move (result.value ()), std::move (ret.buffer_ ), ret. attachment }};
975
1030
}
976
1031
}
977
1032
else {
@@ -984,27 +1039,25 @@ class coro_rpc_client {
984
1039
async_simple::coro::Lazy<async_simple::coro::Lazy<
985
1040
async_rpc_result<decltype (get_return_type<func>())>>>
986
1041
send_request (Args &&...args ) {
987
- return send_request_for_with_attachment<func>(
988
- config_.request_timeout_duration , {}, std::forward<Args>(args)...);
1042
+ return send_request<func>(request_config_t {}, std::forward<Args>(args)...);
989
1043
}
990
1044
991
1045
template <auto func, typename ... Args>
992
1046
async_simple::coro::Lazy<async_simple::coro::Lazy<
993
1047
async_rpc_result<decltype (get_return_type<func>())>>>
994
1048
send_request_with_attachment (std::string_view request_attachment,
995
1049
Args &&...args ) {
996
- return send_request_for_with_attachment <func>(
997
- config_. request_timeout_duration , request_attachment,
1050
+ return send_request <func>(
1051
+ request_config_t {. request_attachment = request_attachment} ,
998
1052
std::forward<Args>(args)...);
999
1053
}
1000
1054
1001
- template <auto func, typename ... Args>
1055
+ template <auto func, typename Duration, typename ... Args>
1002
1056
async_simple::coro::Lazy<async_simple::coro::Lazy<
1003
1057
async_rpc_result<decltype (get_return_type<func>())>>>
1004
- send_request_for (Args &&...args ) {
1005
- return send_request_for_with_attachment<func>(
1006
- config_.request_timeout_duration , std::string_view{},
1007
- std::forward<Args>(args)...);
1058
+ send_request_for (Duration request_timeout_duration, Args &&...args ) {
1059
+ return send_request<func>(request_config_t {request_timeout_duration},
1060
+ std::string_view{}, std::forward<Args>(args)...);
1008
1061
}
1009
1062
1010
1063
struct recving_guard {
@@ -1029,25 +1082,26 @@ class coro_rpc_client {
1029
1082
template <auto func, typename ... Args>
1030
1083
async_simple::coro::Lazy<async_simple::coro::Lazy<
1031
1084
async_rpc_result<decltype (get_return_type<func>())>>>
1032
- send_request_for_with_attachment (auto request_timeout_duration,
1033
- std::string_view request_attachment,
1034
- Args &&...args ) {
1085
+ send_request (request_config_t config, Args &&...args ) {
1035
1086
using rpc_return_t = decltype (get_return_type<func>());
1036
1087
recving_guard guard (control_.get ());
1037
1088
uint32_t id;
1089
+ if (!config.request_timeout_duration ) {
1090
+ config.request_timeout_duration = config_.request_timeout_duration ;
1091
+ }
1092
+ assert (config.request_timeout_duration .has_value ());
1038
1093
1039
1094
auto timer = std::make_unique<coro_io::period_timer>(
1040
1095
control_->executor_ .get_asio_executor ());
1041
1096
auto result = co_await send_request_for_impl<func>(
1042
- request_timeout_duration, id, *timer, request_attachment,
1043
- std::forward<Args>(args)...);
1097
+ config, id, *timer, std::forward<Args>(args)...);
1044
1098
auto &control = *control_;
1045
1099
if (!result) {
1046
1100
async_simple::Promise<async_rpc_raw_result> promise;
1047
1101
auto future = promise.getFuture ();
1048
1102
bool is_empty = control.response_handler_table_ .empty ();
1049
1103
auto &&[_, is_ok] = control.response_handler_table_ .try_emplace (
1050
- id, std::move (timer), std::move (promise));
1104
+ id, std::move (timer), std::move (promise), config. resp_attachment_buf );
1051
1105
if (!is_ok) [[unlikely]] {
1052
1106
close ();
1053
1107
co_return build_failed_rpc_result<rpc_return_t >(
@@ -1196,8 +1250,10 @@ class coro_rpc_client {
1196
1250
std::atomic<uint32_t > request_id_{0 };
1197
1251
std::unique_ptr<coro_io::period_timer> timer_;
1198
1252
std::shared_ptr<control_t > control_;
1199
- std::string_view req_attachment_;
1200
1253
std::vector<asio::ip::tcp::endpoint> endpoints_;
1254
+ std::string_view req_attachment_;
1255
+ std::span<char > resp_attachment_buffer_;
1256
+ std::string_view resp_attachment_;
1201
1257
config config_;
1202
1258
constexpr static std::size_t default_read_buf_size_ = 256 ;
1203
1259
#ifdef YLT_ENABLE_SSL
0 commit comments