diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index 515d42b..025fce3 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -3760,7 +3760,7 @@ void Client::check_chat_access(int64 chat_id, AccessRights access_rights, const CHECK(group_info != nullptr); if (!group_info->is_active && need_write_access) { if (group_info->upgraded_to_supergroup_id != 0) { - std::unordered_map> parameters; + td::FlatHashMap> parameters; auto updagraded_to_chat_id = get_supergroup_chat_id(group_info->upgraded_to_supergroup_id); parameters.emplace("migrate_to_chat_id", std::make_unique(updagraded_to_chat_id)); return fail_query(400, "Bad Request: group chat was upgraded to a supergroup chat", std::move(query), @@ -4398,7 +4398,8 @@ void Client::on_update(object_ptr result) { } case td_api::updateUser::ID: { auto update = move_object_as(result); - add_user(users_, std::move(update->user_)); + auto *user_info = add_user_info(update->user_->id_); + add_user(user_info, std::move(update->user_)); break; } case td_api::updateUserFullInfo::ID: { @@ -4410,7 +4411,8 @@ void Client::on_update(object_ptr result) { } case td_api::updateBasicGroup::ID: { auto update = move_object_as(result); - add_group(groups_, std::move(update->basic_group_)); + auto *group_info = add_group_info(update->basic_group_->id_); + add_group(group_info, std::move(update->basic_group_)); break; } case td_api::updateBasicGroupFullInfo::ID: { @@ -4425,7 +4427,8 @@ void Client::on_update(object_ptr result) { } case td_api::updateSupergroup::ID: { auto update = move_object_as(result); - add_supergroup(supergroups_, std::move(update->supergroup_)); + auto *supergroup_info = add_supergroup_info(update->supergroup_->id_); + add_supergroup(supergroup_info, std::move(update->supergroup_)); break; } case td_api::updateSupergroupFullInfo::ID: { @@ -6392,7 +6395,7 @@ void Client::on_message_send_succeeded(object_ptr &&message, in auto query_id = extract_yet_unsent_message_query_id(chat_id, old_message_id, &message_info->is_reply_to_message_deleted); - auto &query = pending_send_message_queries_[query_id]; + auto &query = *pending_send_message_queries_[query_id]; if (query.is_multisend) { query.messages.push_back(td::json_encode(JsonMessage(message_info, true, "sent message", this))); query.awaited_message_count--; @@ -6420,7 +6423,7 @@ void Client::on_message_send_failed(int64 chat_id, int64 old_message_id, int64 n auto error = make_object(result.code(), result.message().str()); auto query_id = extract_yet_unsent_message_query_id(chat_id, old_message_id, nullptr); - auto &query = pending_send_message_queries_[query_id]; + auto &query = *pending_send_message_queries_[query_id]; if (query.is_multisend) { if (query.error == nullptr) { query.error = std::move(error); @@ -8253,8 +8256,10 @@ void Client::do_send_message(object_ptr input_messa td::int64 Client::get_send_message_query_id(PromisedQueryPtr query, bool is_multisend) { auto query_id = current_send_message_query_id_++; auto &pending_query = pending_send_message_queries_[query_id]; - pending_query.query = std::move(query); - pending_query.is_multisend = is_multisend; + CHECK(pending_query == nullptr); + pending_query = td::make_unique(); + pending_query->query = std::move(query); + pending_query->is_multisend = is_multisend; return query_id; } @@ -8276,7 +8281,7 @@ void Client::on_sent_message(object_ptr &&message, int64 query_ auto emplace_result = yet_unsent_messages_.emplace(yet_unsent_message_id, yet_unsent_message); CHECK(emplace_result.second); yet_unsent_message_count_[chat_id]++; - pending_send_message_queries_[query_id].awaited_message_count++; + pending_send_message_queries_[query_id]->awaited_message_count++; } void Client::abort_long_poll(bool from_set_webhook) { @@ -8442,8 +8447,7 @@ void Client::long_poll_wakeup(bool force_flag) { } } -void Client::add_user(std::unordered_map &users, object_ptr &&user) { - auto user_info = &users[user->id_]; +void Client::add_user(UserInfo *user_info, object_ptr &&user) { user_info->first_name = std::move(user->first_name_); user_info->last_name = std::move(user->last_name_); user_info->username = std::move(user->username_); @@ -8475,23 +8479,31 @@ void Client::add_user(std::unordered_map &users, object_ptrsecond; + if (emplace_result.second) { + user_info = td::make_unique(); + } else { + CHECK(user_info != nullptr); + } + return user_info.get(); +} + const Client::UserInfo *Client::get_user_info(int64 user_id) const { auto it = users_.find(user_id); - return it == users_.end() ? nullptr : &it->second; + return it == users_.end() ? nullptr : it->second.get(); } void Client::set_user_bio(int64 user_id, td::string &&bio) { - auto user_info = &users_[user_id]; - user_info->bio = std::move(bio); + add_user_info(user_id)->bio = std::move(bio); } void Client::set_user_has_private_forwards(int64 user_id, bool has_private_forwards) { - auto user_info = &users_[user_id]; - user_info->has_private_forwards = has_private_forwards; + add_user_info(user_id)->has_private_forwards = has_private_forwards; } -void Client::add_group(std::unordered_map &groups, object_ptr &&group) { - auto group_info = &groups[group->id_]; +void Client::add_group(GroupInfo *group_info, object_ptr &&group) { group_info->member_count = group->member_count_; group_info->left = group->status_->get_id() == td_api::chatMemberStatusLeft::ID; group_info->kicked = group->status_->get_id() == td_api::chatMemberStatusBanned::ID; @@ -8502,24 +8514,31 @@ void Client::add_group(std::unordered_map &groups, object_ptr< } } +Client::GroupInfo *Client::add_group_info(int64 group_id) { + auto emplace_result = groups_.emplace(group_id, nullptr); + auto &group_info = emplace_result.first->second; + if (emplace_result.second) { + group_info = td::make_unique(); + } else { + CHECK(group_info != nullptr); + } + return group_info.get(); +} + const Client::GroupInfo *Client::get_group_info(int64 group_id) const { auto it = groups_.find(group_id); - return it == groups_.end() ? nullptr : &it->second; + return it == groups_.end() ? nullptr : it->second.get(); } void Client::set_group_description(int64 group_id, td::string &&descripton) { - auto group_info = &groups_[group_id]; - group_info->description = std::move(descripton); + add_group_info(group_id)->description = std::move(descripton); } void Client::set_group_invite_link(int64 group_id, td::string &&invite_link) { - auto group_info = &groups_[group_id]; - group_info->invite_link = std::move(invite_link); + add_group_info(group_id)->invite_link = std::move(invite_link); } -void Client::add_supergroup(std::unordered_map &supergroups, - object_ptr &&supergroup) { - auto supergroup_info = &supergroups[supergroup->id_]; +void Client::add_supergroup(SupergroupInfo *supergroup_info, object_ptr &&supergroup) { supergroup_info->username = std::move(supergroup->username_); supergroup_info->date = supergroup->date_; supergroup_info->status = std::move(supergroup->status_); @@ -8528,48 +8547,59 @@ void Client::add_supergroup(std::unordered_map &supergrou } void Client::set_supergroup_description(int64 supergroup_id, td::string &&descripton) { - auto supergroup_info = &supergroups_[supergroup_id]; - supergroup_info->description = std::move(descripton); + add_supergroup_info(supergroup_id)->description = std::move(descripton); } void Client::set_supergroup_invite_link(int64 supergroup_id, td::string &&invite_link) { - auto supergroup_info = &supergroups_[supergroup_id]; - supergroup_info->invite_link = std::move(invite_link); + add_supergroup_info(supergroup_id)->invite_link = std::move(invite_link); } void Client::set_supergroup_sticker_set_id(int64 supergroup_id, int64 sticker_set_id) { - auto supergroup_info = &supergroups_[supergroup_id]; - supergroup_info->sticker_set_id = sticker_set_id; + add_supergroup_info(supergroup_id)->sticker_set_id = sticker_set_id; } void Client::set_supergroup_can_set_sticker_set(int64 supergroup_id, bool can_set_sticker_set) { - auto supergroup_info = &supergroups_[supergroup_id]; - supergroup_info->can_set_sticker_set = can_set_sticker_set; + add_supergroup_info(supergroup_id)->can_set_sticker_set = can_set_sticker_set; } void Client::set_supergroup_slow_mode_delay(int64 supergroup_id, int32 slow_mode_delay) { - auto supergroup_info = &supergroups_[supergroup_id]; - supergroup_info->slow_mode_delay = slow_mode_delay; + add_supergroup_info(supergroup_id)->slow_mode_delay = slow_mode_delay; } void Client::set_supergroup_linked_chat_id(int64 supergroup_id, int64 linked_chat_id) { - auto supergroup_info = &supergroups_[supergroup_id]; - supergroup_info->linked_chat_id = linked_chat_id; + add_supergroup_info(supergroup_id)->linked_chat_id = linked_chat_id; } void Client::set_supergroup_location(int64 supergroup_id, object_ptr location) { - auto supergroup_info = &supergroups_[supergroup_id]; - supergroup_info->location = std::move(location); + add_supergroup_info(supergroup_id)->location = std::move(location); +} + +Client::SupergroupInfo *Client::add_supergroup_info(int64 supergroup_id) { + auto emplace_result = supergroups_.emplace(supergroup_id, nullptr); + auto &supergroup_info = emplace_result.first->second; + if (emplace_result.second) { + supergroup_info = td::make_unique(); + } else { + CHECK(supergroup_info != nullptr); + } + return supergroup_info.get(); } const Client::SupergroupInfo *Client::get_supergroup_info(int64 supergroup_id) const { auto it = supergroups_.find(supergroup_id); - return it == supergroups_.end() ? nullptr : &it->second; + return it == supergroups_.end() ? nullptr : it->second.get(); } Client::ChatInfo *Client::add_chat(int64 chat_id) { LOG(DEBUG) << "Update chat " << chat_id; - return &chats_[chat_id]; + auto emplace_result = chats_.emplace(chat_id, nullptr); + auto &chat_info = emplace_result.first->second; + if (emplace_result.second) { + chat_info = td::make_unique(); + } else { + CHECK(chat_info != nullptr); + } + return chat_info.get(); } const Client::ChatInfo *Client::get_chat(int64 chat_id) const { @@ -8577,7 +8607,7 @@ const Client::ChatInfo *Client::get_chat(int64 chat_id) const { if (it == chats_.end()) { return nullptr; } - return &it->second; + return it->second.get(); } Client::ChatType Client::get_chat_type(int64 chat_id) const { @@ -8879,10 +8909,7 @@ void Client::add_new_message(object_ptr &&message, bool is_edit } auto chat_id = message->chat_id_; - if (chat_id == 0) { - LOG(ERROR) << "Receive invalid chat in " << to_string(message); - return; - } + CHECK(chat_id != 0); new_message_queues_[chat_id].queue_.emplace(std::move(message), is_edited); process_new_message_queue(chat_id); } @@ -8916,10 +8943,7 @@ void Client::add_new_chosen_inline_result(int64 sender_user_id, object_ptr &&query) { CHECK(query != nullptr); auto user_id = query->sender_user_id_; - if (user_id == 0) { - LOG(ERROR) << "Receive invalid sender in " << to_string(query); - return; - } + CHECK(user_id != 0); new_callback_query_queues_[user_id].queue_.push(std::move(query)); process_new_callback_query_queue(user_id, 0); } @@ -9806,6 +9830,6 @@ constexpr Client::Slice Client::API_ID_INVALID_ERROR_DESCRIPTION; constexpr int Client::CLOSING_ERROR_CODE; constexpr Client::Slice Client::CLOSING_ERROR_DESCRIPTION; -std::unordered_map Client::methods_; +td::FlatHashMap Client::methods_; } // namespace telegram_bot_api diff --git a/telegram-bot-api/Client.h b/telegram-bot-api/Client.h index caefd33..0e8c116 100644 --- a/telegram-bot-api/Client.h +++ b/telegram-bot-api/Client.h @@ -19,6 +19,8 @@ #include "td/utils/common.h" #include "td/utils/Container.h" +#include "td/utils/FlatHashMap.h" +#include "td/utils/FlatHashSet.h" #include "td/utils/JsonBuilder.h" #include "td/utils/Slice.h" #include "td/utils/Status.h" @@ -27,8 +29,6 @@ #include #include #include -#include -#include namespace telegram_bot_api { @@ -588,9 +588,10 @@ class Client final : public WebhookActor::Callback { bool is_inline_bot = false; bool has_private_forwards = false; }; - static void add_user(std::unordered_map &users, object_ptr &&user); + static void add_user(UserInfo *user_info, object_ptr &&user); void set_user_bio(int64 user_id, td::string &&bio); void set_user_has_private_forwards(int64 user_id, bool has_private_forwards); + UserInfo *add_user_info(int64 user_id); const UserInfo *get_user_info(int64 user_id) const; struct GroupInfo { @@ -602,9 +603,10 @@ class Client final : public WebhookActor::Callback { bool is_active = false; int64 upgraded_to_supergroup_id = 0; }; - static void add_group(std::unordered_map &groups, object_ptr &&group); + static void add_group(GroupInfo *group_info, object_ptr &&group); void set_group_description(int64 group_id, td::string &&descripton); void set_group_invite_link(int64 group_id, td::string &&invite_link); + GroupInfo *add_group_info(int64 group_id); const GroupInfo *get_group_info(int64 group_id) const; struct SupergroupInfo { @@ -621,8 +623,7 @@ class Client final : public WebhookActor::Callback { bool can_set_sticker_set = false; bool has_location = false; }; - static void add_supergroup(std::unordered_map &supergroups, - object_ptr &&supergroup); + static void add_supergroup(SupergroupInfo *supergroup_info, object_ptr &&supergroup); void set_supergroup_description(int64 supergroup_id, td::string &&descripton); void set_supergroup_invite_link(int64 supergroup_id, td::string &&invite_link); void set_supergroup_sticker_set_id(int64 supergroup_id, int64 sticker_set_id); @@ -630,6 +631,7 @@ class Client final : public WebhookActor::Callback { void set_supergroup_slow_mode_delay(int64 supergroup_id, int32 slow_mode_delay); void set_supergroup_linked_chat_id(int64 supergroup_id, int64 linked_chat_id); void set_supergroup_location(int64 supergroup_id, object_ptr location); + SupergroupInfo *add_supergroup_info(int64 supergroup_id); const SupergroupInfo *get_supergroup_info(int64 supergroup_id) const; struct ChatInfo { @@ -861,30 +863,30 @@ class Client final : public WebhookActor::Callback { int64 channel_bot_user_id_ = 0; int64 service_notifications_user_id_ = 0; - static std::unordered_map methods_; + static td::FlatHashMap methods_; - std::unordered_map, FullMessageIdHash> messages_; // message cache - std::unordered_map users_; // user info cache - std::unordered_map groups_; // group info cache - std::unordered_map supergroups_; // supergroup info cache - std::unordered_map chats_; // chat info cache + td::FlatHashMap, FullMessageIdHash> messages_; // message cache + td::FlatHashMap> users_; // user info cache + td::FlatHashMap> groups_; // group info cache + td::FlatHashMap> supergroups_; // supergroup info cache + td::FlatHashMap> chats_; // chat info cache - std::unordered_map, FullMessageIdHash> + td::FlatHashMap, FullMessageIdHash> reply_message_ids_; // message -> replies to it - std::unordered_map, FullMessageIdHash> + td::FlatHashMap, FullMessageIdHash> yet_unsent_reply_message_ids_; // message -> replies to it - std::unordered_map> file_download_listeners_; - std::unordered_set download_started_file_ids_; + td::FlatHashMap> file_download_listeners_; + td::FlatHashSet download_started_file_ids_; struct YetUnsentMessage { int64 reply_to_message_id = 0; bool is_reply_to_message_deleted = false; int64 send_message_query_id = 0; }; - std::unordered_map yet_unsent_messages_; + td::FlatHashMap yet_unsent_messages_; - std::unordered_map yet_unsent_message_count_; + td::FlatHashMap yet_unsent_message_count_; // chat_id -> count struct PendingSendMessageQuery { PromisedQueryPtr query; @@ -893,7 +895,7 @@ class Client final : public WebhookActor::Callback { td::vector messages; object_ptr error; }; - std::unordered_map + td::FlatHashMap> pending_send_message_queries_; // query_id -> PendingSendMessageQuery int64 current_send_message_query_id_ = 1; @@ -909,28 +911,28 @@ class Client final : public WebhookActor::Callback { std::queue queue_; bool has_active_request_ = false; }; - std::unordered_map new_message_queues_; // chat_id -> queue + td::FlatHashMap new_message_queues_; // chat_id -> queue struct NewCallbackQueryQueue { std::queue> queue_; bool has_active_request_ = false; }; - std::unordered_map new_callback_query_queues_; // sender_user_id -> queue + td::FlatHashMap new_callback_query_queues_; // sender_user_id -> queue - std::unordered_map sticker_set_names_; + td::FlatHashMap sticker_set_names_; int64 cur_temp_bot_user_id_ = 1; - std::unordered_map bot_user_ids_; - std::unordered_set unresolved_bot_usernames_; - std::unordered_map temp_to_real_bot_user_id_; - std::unordered_map> awaiting_bot_resolve_queries_; + td::FlatHashMap bot_user_ids_; + td::FlatHashSet unresolved_bot_usernames_; + td::FlatHashMap temp_to_real_bot_user_id_; + td::FlatHashMap> awaiting_bot_resolve_queries_; struct PendingBotResolveQuery { std::size_t pending_resolve_count = 0; PromisedQueryPtr query; td::Promise on_success; }; - std::unordered_map pending_bot_resolve_queries_; + td::FlatHashMap pending_bot_resolve_queries_; int64 current_bot_resolve_query_id_ = 1; td::string dir_; diff --git a/telegram-bot-api/ClientManager.cpp b/telegram-bot-api/ClientManager.cpp index f0f023d..0630f21 100644 --- a/telegram-bot-api/ClientManager.cpp +++ b/telegram-bot-api/ClientManager.cpp @@ -71,9 +71,13 @@ void ClientManager::send(PromisedQueryPtr query) { return fail_query(401, "Unauthorized: invalid token specified", std::move(query)); } auto r_user_id = td::to_integer_safe(query->token().substr(0, token.find(':'))); - if (r_user_id.is_error() || r_user_id.ok() < 0 || !token_range_(r_user_id.ok())) { + if (r_user_id.is_error() || !token_range_(r_user_id.ok())) { return fail_query(421, "Misdirected Request: unallowed token specified", std::move(query)); } + auto user_id = r_user_id.ok(); + if (user_id <= 0 || user_id >= (static_cast(1) << 54)) { + return fail_query(401, "Unauthorized: invalid token specified", std::move(query)); + } if (query->is_test_dc()) { token += "/test"; @@ -113,7 +117,7 @@ void ClientManager::send(PromisedQueryPtr query) { } flood_control.add_event(static_cast(now)); } - auto tqueue_id = get_tqueue_id(r_user_id.ok(), query->is_test_dc()); + auto tqueue_id = get_tqueue_id(user_id, query->is_test_dc()); if (active_client_count_.find(tqueue_id) != active_client_count_.end()) { // return query->set_retry_after_error(1); } @@ -392,6 +396,7 @@ void ClientManager::raw_event(const td::Event::Raw &event) { auto id = get_link_token(); auto *info = clients_.get(id); CHECK(info != nullptr); + CHECK(info->tqueue_id_ != 0); auto &value = active_client_count_[info->tqueue_id_]; if (event.ptr != nullptr) { value++; diff --git a/telegram-bot-api/ClientManager.h b/telegram-bot-api/ClientManager.h index 5720d98..1dcc093 100644 --- a/telegram-bot-api/ClientManager.h +++ b/telegram-bot-api/ClientManager.h @@ -16,11 +16,11 @@ #include "td/utils/buffer.h" #include "td/utils/common.h" #include "td/utils/Container.h" +#include "td/utils/FlatHashMap.h" #include "td/utils/FloodControlFast.h" #include "td/utils/Slice.h" #include -#include #include namespace telegram_bot_api { @@ -61,9 +61,9 @@ class ClientManager final : public td::Actor { std::shared_ptr parameters_; TokenRange token_range_; - std::unordered_map token_to_id_; - std::unordered_map flood_controls_; - std::unordered_map active_client_count_; + td::FlatHashMap token_to_id_; + td::FlatHashMap flood_controls_; + td::FlatHashMap active_client_count_; bool close_flag_ = false; td::vector> close_promises_; diff --git a/telegram-bot-api/Query.cpp b/telegram-bot-api/Query.cpp index 41c66dd..d8fb3b9 100644 --- a/telegram-bot-api/Query.cpp +++ b/telegram-bot-api/Query.cpp @@ -21,7 +21,7 @@ namespace telegram_bot_api { -std::unordered_map> empty_parameters; +td::FlatHashMap> empty_parameters; Query::Query(td::vector &&container, td::Slice token, bool is_test_dc, td::MutableSlice method, td::vector> &&args, @@ -96,7 +96,7 @@ void Query::set_error(int http_status_code, td::BufferSlice result) { void Query::set_retry_after_error(int retry_after) { retry_after_ = retry_after; - std::unordered_map> parameters; + td::FlatHashMap> parameters; parameters.emplace("retry_after", std::make_unique(retry_after)); set_error(429, td::json_encode( JsonQueryError(429, PSLICE() << "Too Many Requests: retry after " << retry_after, parameters))); diff --git a/telegram-bot-api/Query.h b/telegram-bot-api/Query.h index f5d15f8..ed40911 100644 --- a/telegram-bot-api/Query.h +++ b/telegram-bot-api/Query.h @@ -15,6 +15,7 @@ #include "td/utils/buffer.h" #include "td/utils/common.h" +#include "td/utils/FlatHashMap.h" #include "td/utils/JsonBuilder.h" #include "td/utils/List.h" #include "td/utils/port/IPAddress.h" @@ -23,7 +24,6 @@ #include #include -#include #include namespace telegram_bot_api { @@ -164,11 +164,11 @@ td::StringBuilder &operator<<(td::StringBuilder &sb, const Query &query); // fix for outdated C++14 libraries // https://stackoverflow.com/questions/26947704/implicit-conversion-failure-from-initializer-list -extern std::unordered_map> empty_parameters; +extern td::FlatHashMap> empty_parameters; class JsonParameters final : public td::Jsonable { public: - explicit JsonParameters(const std::unordered_map> ¶meters) + explicit JsonParameters(const td::FlatHashMap> ¶meters) : parameters_(parameters) { } void store(td::JsonValueScope *scope) const { @@ -180,7 +180,7 @@ class JsonParameters final : public td::Jsonable { } private: - const std::unordered_map> ¶meters_; + const td::FlatHashMap> ¶meters_; }; template @@ -206,7 +206,7 @@ class JsonQueryError final : public td::Jsonable { public: JsonQueryError( int error_code, td::Slice description, - const std::unordered_map> ¶meters = empty_parameters) + const td::FlatHashMap> ¶meters = empty_parameters) : error_code_(error_code), description_(description), parameters_(parameters) { } void store(td::JsonValueScope *scope) const { @@ -222,7 +222,7 @@ class JsonQueryError final : public td::Jsonable { private: int error_code_; td::Slice description_; - const std::unordered_map> ¶meters_; + const td::FlatHashMap> ¶meters_; }; class PromiseDeleter { @@ -261,7 +261,7 @@ void answer_query(const Jsonable &result, PromisedQueryPtr query, td::Slice desc inline void fail_query( int http_status_code, td::Slice description, PromisedQueryPtr query, - const std::unordered_map> ¶meters = empty_parameters) { + const td::FlatHashMap> ¶meters = empty_parameters) { query->set_error(http_status_code, td::json_encode(JsonQueryError(http_status_code, description, parameters))); query.reset(); // send query into promise explicitly diff --git a/telegram-bot-api/WebhookActor.cpp b/telegram-bot-api/WebhookActor.cpp index bfab715..14df122 100644 --- a/telegram-bot-api/WebhookActor.cpp +++ b/telegram-bot-api/WebhookActor.cpp @@ -379,11 +379,14 @@ void WebhookActor::load_updates() { for (auto &update : updates) { VLOG(webhook) << "Load update " << update.id; - if (update_map_.find(update.id) != update_map_.end()) { - LOG(ERROR) << "Receive duplicated event " << update.id << " from tqueue"; + CHECK(update.id.is_valid()); + auto &dest_ptr = update_map_[update.id]; + if (dest_ptr != nullptr) { + LOG(ERROR) << "Receive duplicated event " << update.id << " from TQueue"; continue; } - auto &dest = update_map_[update.id]; + dest_ptr = td::make_unique(); + auto &dest = *dest_ptr; dest.id_ = update.id; dest.json_ = update.data.str(); dest.delay_ = 1; @@ -437,7 +440,7 @@ void WebhookActor::load_updates() { void WebhookActor::drop_event(td::TQueue::EventId event_id) { auto it = update_map_.find(event_id); CHECK(it != update_map_.end()); - auto queue_id = it->second.queue_id_; + auto queue_id = it->second->queue_id_; update_map_.erase(it); auto queue_updates_it = queue_updates_.find(queue_id); @@ -448,8 +451,10 @@ void WebhookActor::drop_event(td::TQueue::EventId event_id) { if (queue_updates_it->second.event_ids.empty()) { queue_updates_.erase(queue_updates_it); } else { - auto &update = update_map_[queue_updates_it->second.event_ids.front()]; - queues_.emplace(update.wakeup_at_, update.queue_id_); + auto update_id = queue_updates_it->second.event_ids.front(); + CHECK(update_id.is_valid()); + auto &update = update_map_[update_id]; + queues_.emplace(update->wakeup_at_, update->queue_id_); } parameters_->shared_data_->tqueue_->forget(tqueue_id_, event_id); @@ -462,7 +467,7 @@ void WebhookActor::on_update_ok(td::TQueue::EventId event_id) { auto it = update_map_.find(event_id); CHECK(it != update_map_.end()); - VLOG(webhook) << "Receive ok for update " << event_id << " in " << (last_success_time_ - it->second.last_send_time_) + VLOG(webhook) << "Receive ok for update " << event_id << " in " << (last_success_time_ - it->second->last_send_time_) << " seconds"; drop_event(event_id); @@ -474,21 +479,22 @@ void WebhookActor::on_update_error(td::TQueue::EventId event_id, td::Slice error auto it = update_map_.find(event_id); CHECK(it != update_map_.end()); + CHECK(it->second != nullptr); + auto &update = *it->second; const int MAX_RETRY_AFTER = 3600; retry_after = td::clamp(retry_after, 0, MAX_RETRY_AFTER); - int next_delay = it->second.delay_; + int next_delay = update.delay_; int next_effective_delay = retry_after; - if (retry_after == 0 && it->second.fail_count_ > 0) { + if (retry_after == 0 && update.fail_count_ > 0) { next_delay = td::min(WEBHOOK_MAX_RESEND_TIMEOUT, next_delay * 2); next_effective_delay = next_delay; } - if (parameters_->shared_data_->get_unix_time(now) + next_effective_delay > it->second.expires_at_) { + if (parameters_->shared_data_->get_unix_time(now) + next_effective_delay > update.expires_at_) { LOG(WARNING) << "Drop update " << event_id << ": " << error; drop_event(event_id); return; } - auto &update = it->second; update.delay_ = next_delay; update.wakeup_at_ = now + next_effective_delay; update.fail_count_++; @@ -514,10 +520,15 @@ td::Status WebhookActor::send_update() { } auto queue_id = it->id; + CHECK(queue_id != 0); queues_.erase(it); auto event_id = queue_updates_[queue_id].event_ids.front(); + CHECK(event_id.is_valid()); - auto &update = update_map_[event_id]; + auto update_map_it = update_map_.find(event_id); + CHECK(update_map_it != update_map_.end()); + CHECK(update_map_it->second != nullptr); + auto &update = *update_map_it->second; update.last_send_time_ = now; auto body = td::json_encode(JsonUpdate(update.id_.value(), update.json_)); diff --git a/telegram-bot-api/WebhookActor.h b/telegram-bot-api/WebhookActor.h index 6067d73..71d702e 100644 --- a/telegram-bot-api/WebhookActor.h +++ b/telegram-bot-api/WebhookActor.h @@ -20,6 +20,7 @@ #include "td/utils/BufferedFd.h" #include "td/utils/common.h" #include "td/utils/Container.h" +#include "td/utils/FlatHashMap.h" #include "td/utils/FloodControlFast.h" #include "td/utils/HttpUrl.h" #include "td/utils/JsonBuilder.h" @@ -35,7 +36,6 @@ #include #include #include -#include namespace telegram_bot_api { @@ -127,8 +127,8 @@ class WebhookActor final : public td::HttpOutboundConnection::Callback { return std::hash()(event_id.value()); } }; - std::unordered_map update_map_; - std::unordered_map queue_updates_; + td::FlatHashMap, EventIdHash> update_map_; + td::FlatHashMap queue_updates_; std::set queues_; td::int64 unique_queue_id_ = static_cast(1) << 60;