45 auto track(
const std::string &event_id,
47 std::chrono::milliseconds timeout) ->
void
49 auto timer = std::make_shared<boost::asio::steady_timer>(*io_context_, timeout);
51 timer->async_wait([
this, event_id](
const boost::system::error_code &error) {
52 if (not error) { handle_timeout(event_id); }
55 pending_[event_id] = pending_request{ .callback =
56 [callback = std::move(callback)](
const std::any &response_any) {
57 callback(std::any_cast<const protocol::ok &>(response_any));
86 template<
typename ResponseType>
auto resolve(
const std::string &event_id,
const ResponseType &response) ->
void
88 auto iter = pending_.find(event_id);
89 if (iter != pending_.end()) {
90 iter->second.timer->cancel();
91 iter->second.callback(response);
106 [[nodiscard]]
auto async_track(std::string event_id, std::chrono::milliseconds timeout)
107 -> boost::asio::awaitable<ResponseType>
109 auto executor =
co_await boost::asio::this_coro::executor;
110 boost::asio::cancellation_signal cancel_signal;
111 auto result = std::make_shared<ResponseType>();
112 auto event_done = std::make_shared<bool>(
false);
114 static constexpr int hours_per_day = 24;
115 auto dummy_timer = std::make_shared<boost::asio::steady_timer>(*io_context_, std::chrono::hours(hours_per_day));
116 pending_[event_id] = pending_request{ [&cancel_signal, result, event_done](
const std::any &response_any) {
117 *result = std::any_cast<ResponseType>(response_any);
119 cancel_signal.emit(boost::asio::cancellation_type::all);
123 boost::asio::steady_timer timeout_timer(executor, timeout);
125 boost::system::error_code error_code;
126 co_await timeout_timer.async_wait(boost::asio::bind_cancellation_slot(
127 cancel_signal.slot(), boost::asio::redirect_error(boost::asio::use_awaitable, error_code)));
129 pending_.erase(event_id);
131 if (error_code == boost::asio::error::operation_aborted and *event_done) {
co_return *result; }
133 throw std::runtime_error(
"Request timeout");