From 05625491ba54f0217d179983592921c1b3d9092d Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 8 Aug 2022 00:55:22 +0300 Subject: [PATCH] Cache found stickers in database. --- td/telegram/StickersManager.cpp | 105 ++++++++++++++++++++++++++------ td/telegram/StickersManager.h | 25 ++++++-- 2 files changed, 107 insertions(+), 23 deletions(-) diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 8cc586c2a..28e75d9ba 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -1273,6 +1273,29 @@ class SendAnimatedEmojiClicksQuery final : public Td::ResultHandler { } }; +template +void StickersManager::FoundStickers::store(StorerT &storer) const { + StickersManager *stickers_manager = storer.context()->td().get_actor_unsafe()->stickers_manager_.get(); + td::store(narrow_cast(sticker_ids_.size()), storer); + for (auto sticker_id : sticker_ids_) { + stickers_manager->store_sticker(sticker_id, false, storer, "FoundStickers"); + } + td::store(cache_time_, storer); + store_time(next_reload_time_, storer); +} + +template +void StickersManager::FoundStickers::parse(ParserT &parser) { + StickersManager *stickers_manager = parser.context()->td().get_actor_unsafe()->stickers_manager_.get(); + int32 size = parser.fetch_int(); + sticker_ids_.resize(size); + for (auto &sticker_id : sticker_ids_) { + sticker_id = stickers_manager->parse_sticker(false, parser); + } + td::parse(cache_time_, parser); + parse_time(next_reload_time_, parser); +} + class StickersManager::StickerListLogEvent { public: vector sticker_ids; @@ -4134,6 +4157,10 @@ vector StickersManager::get_stickers(StickerType sticker_type, string em return result; } +string StickersManager::get_found_stickers_database_key(const string &emoji) { + return PSTRING() << "found_stickers" << emoji; +} + void StickersManager::search_stickers(string emoji, int32 limit, Promise> &&promise) { if (limit == 0) { @@ -4167,8 +4194,59 @@ void StickersManager::search_stickers(string emoji, int32 limit, int64 hash = 0; if (it != found_stickers_.end()) { hash = get_recent_stickers_hash(it->second.sticker_ids_); + td_->create_handler()->send(std::move(emoji), hash); + return; } - td_->create_handler()->send(std::move(emoji), hash); + + if (G()->parameters().use_file_db) { + LOG(INFO) << "Trying to load stickers for " << emoji << " from database"; + G()->td_db()->get_sqlite_pmc()->get( + get_found_stickers_database_key(emoji), PromiseCreator::lambda([emoji](string value) mutable { + send_closure(G()->stickers_manager(), &StickersManager::on_load_found_stickers_from_database, + std::move(emoji), std::move(value)); + })); + } else { + td_->create_handler()->send(std::move(emoji), 0); + } + } +} + +void StickersManager::on_load_found_stickers_from_database(string emoji, string value) { + if (G()->close_flag()) { + return; + } + if (value.empty()) { + LOG(INFO) << "Stickers for " << emoji << " aren't found in database"; + td_->create_handler()->send(std::move(emoji), 0); + return; + } + + LOG(INFO) << "Successfully loaded stickers for " << emoji << " from database"; + + auto &found_stickers = found_stickers_[emoji]; + CHECK(found_stickers.next_reload_time_ == 0); + auto status = log_event_parse(found_stickers, value); + if (status.is_error()) { + LOG(ERROR) << "Can't load stickers for emoji: " << status << ' ' << format::as_hex_dump<4>(Slice(value)); + found_stickers_.erase(emoji); + td_->create_handler()->send(std::move(emoji), 0); + return; + } + + on_search_stickers_finished(emoji, found_stickers); +} + +void StickersManager::on_search_stickers_finished(const string &emoji, const FoundStickers &found_stickers) { + auto it = search_stickers_queries_.find(emoji); + CHECK(it != search_stickers_queries_.end()); + CHECK(!it->second.empty()); + auto queries = std::move(it->second); + search_stickers_queries_.erase(it); + + const auto &sticker_ids = found_stickers.sticker_ids_; + for (auto &query : queries) { + auto result_size = min(static_cast(query.first), sticker_ids.size()); + query.second.set_value(get_stickers_object({sticker_ids.begin(), sticker_ids.begin() + result_size})); } } @@ -4183,7 +4261,7 @@ void StickersManager::on_find_stickers_success(const string &emoji, } auto &found_stickers = it->second; found_stickers.next_reload_time_ = Time::now() + found_stickers.cache_time_; - break; + return on_search_stickers_finished(emoji, found_stickers); } case telegram_api::messages_stickers::ID: { auto received_stickers = move_tl_object_as(stickers); @@ -4199,25 +4277,18 @@ void StickersManager::on_find_stickers_success(const string &emoji, found_stickers.sticker_ids_.push_back(sticker_id); } } - break; + + if (G()->parameters().use_file_db && !G()->close_flag()) { + LOG(INFO) << "Save stickers for " << emoji << " to database"; + G()->td_db()->get_sqlite_pmc()->set(get_found_stickers_database_key(emoji), + log_event_store(found_stickers).as_slice().str(), Auto()); + } + + return on_search_stickers_finished(emoji, found_stickers); } default: UNREACHABLE(); } - - auto it = search_stickers_queries_.find(emoji); - CHECK(it != search_stickers_queries_.end()); - CHECK(!it->second.empty()); - auto queries = std::move(it->second); - search_stickers_queries_.erase(it); - - auto result_it = found_stickers_.find(emoji); - CHECK(result_it != found_stickers_.end()); - const auto &sticker_ids = result_it->second.sticker_ids_; - for (auto &query : queries) { - auto result_size = min(static_cast(query.first), sticker_ids.size()); - query.second.set_value(get_stickers_object({sticker_ids.begin(), sticker_ids.begin() + result_size})); - } } void StickersManager::on_find_stickers_fail(const string &emoji, Status &&error) { diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index 01148141b..cbabe1b28 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -486,6 +486,18 @@ class StickersManager final : public Actor { bool is_being_reloaded_ = false; }; + struct FoundStickers { + vector sticker_ids_; + int32 cache_time_ = 300; + double next_reload_time_ = 0; + + template + void store(StorerT &storer) const; + + template + void parse(ParserT &parser); + }; + struct Reaction { string reaction_; string title_; @@ -547,7 +559,13 @@ class StickersManager final : public Actor { Sticker *get_sticker(FileId file_id); const Sticker *get_sticker(FileId file_id) const; - string get_custom_emoji_database_key(int64 custom_emoji_id); + static string get_found_stickers_database_key(const string &emoji); + + void on_load_found_stickers_from_database(string emoji, string value); + + void on_search_stickers_finished(const string &emoji, const FoundStickers &found_stickers); + + static string get_custom_emoji_database_key(int64 custom_emoji_id); void load_custom_emoji_sticker_from_database(int64 custom_emoji_id, Promise &&promise); @@ -914,11 +932,6 @@ class StickersManager final : public Actor { Hints installed_sticker_sets_hints_[MAX_STICKER_TYPE]; // search installed sticker sets by their title and name - struct FoundStickers { - vector sticker_ids_; - int32 cache_time_ = 300; - double next_reload_time_ = 0; - }; FlatHashMap found_stickers_; FlatHashMap>>>> search_stickers_queries_;