Invalidate cache of getGroupsInCommon when count is changed or in 1 hour.

GitOrigin-RevId: e57edb01d3fe3a21e208e8247ca666284a755bcb
This commit is contained in:
levlam 2019-04-01 22:38:17 +03:00
parent 8b174198d9
commit 606b427673
5 changed files with 98 additions and 32 deletions

View File

@ -2756,7 +2756,7 @@ checkChatUsername chat_id:int53 username:string = CheckChatUsernameResult;
getCreatedPublicChats = Chats;
//@description Returns a list of common chats with a given user. Chats are sorted by their type and creation date @user_id User identifier @offset_chat_id Chat identifier starting from which to return chats; use 0 for the first request @limit Maximum number of chats to be returned; up to 100
//@description Returns a list of common group chats with a given user. Chats are sorted by their type and creation date @user_id User identifier @offset_chat_id Chat identifier starting from which to return chats; use 0 for the first request @limit Maximum number of chats to be returned; up to 100
getGroupsInCommon user_id:int32 offset_chat_id:int53 limit:int32 = Chats;

View File

@ -6404,6 +6404,10 @@ void ContactsManager::update_secret_chat(SecretChat *c, SecretChatId secret_chat
void ContactsManager::update_user_full(UserFull *user_full, UserId user_id) {
CHECK(user_full != nullptr);
if (user_full->is_common_chat_count_changed) {
td_->messages_manager_->drop_common_dialogs_cache(user_id);
user_full->is_common_chat_count_changed = false;
}
if (user_full->is_changed) {
user_full->is_changed = false;
if (user_full->is_inited) {
@ -6487,15 +6491,15 @@ void ContactsManager::on_get_user_full(tl_object_ptr<telegram_api::userFull> &&u
user->is_inited = true;
on_update_user_full_is_blocked(user, user_id, (user_full->flags_ & USER_FULL_FLAG_IS_BLOCKED) != 0);
on_update_user_full_common_chat_count(user, user_id, user_full->common_chats_count_);
bool can_be_called = user_full->phone_calls_available_ && !user_full->phone_calls_private_;
bool has_private_calls = user_full->phone_calls_private_;
if (user->can_be_called != can_be_called || user->has_private_calls != has_private_calls ||
user->about != user_full->about_ || user->common_chat_count != user_full->common_chats_count_) {
user->about != user_full->about_) {
user->can_be_called = can_be_called;
user->has_private_calls = has_private_calls;
user->about = std::move(user_full->about_);
user->common_chat_count = user_full->common_chats_count_;
user->is_changed = true;
}
@ -7091,6 +7095,31 @@ void ContactsManager::on_update_user_full_is_blocked(UserFull *user_full, UserId
}
}
void ContactsManager::on_update_user_common_chat_count(UserId user_id, int32 common_chat_count) {
LOG(INFO) << "Receive " << common_chat_count << " common chat count with " << user_id;
if (!user_id.is_valid()) {
LOG(ERROR) << "Receive invalid " << user_id;
return;
}
UserFull *user_full = get_user_full(user_id);
if (user_full == nullptr) {
return;
}
on_update_user_full_common_chat_count(user_full, user_id, common_chat_count);
update_user_full(user_full, user_id);
}
void ContactsManager::on_update_user_full_common_chat_count(UserFull *user_full, UserId user_id,
int32 common_chat_count) {
CHECK(user_full != nullptr);
if (user_full->is_inited && user_full->common_chat_count != common_chat_count) {
user_full->common_chat_count = common_chat_count;
user_full->is_common_chat_count_changed = true;
user_full->is_changed = true;
}
}
void ContactsManager::on_delete_profile_photo(int64 profile_photo_id, Promise<Unit> promise) {
UserId my_id = get_my_id();

View File

@ -157,6 +157,7 @@ class ContactsManager : public Actor {
void on_update_user_links(UserId user_id, tl_object_ptr<telegram_api::ContactLink> &&outbound,
tl_object_ptr<telegram_api::ContactLink> &&inbound);
void on_update_user_blocked(UserId user_id, bool is_blocked);
void on_update_user_common_chat_count(UserId user_id, int32 common_chat_count);
void on_delete_profile_photo(int64 profile_photo_id, Promise<Unit> promise);
@ -547,6 +548,7 @@ class ContactsManager : public Actor {
bool can_be_called = false;
bool has_private_calls = false;
bool is_common_chat_count_changed = true;
bool is_changed = true;
double expires_at = 0.0;
@ -873,6 +875,7 @@ class ContactsManager : public Actor {
void add_user_photo_id(User *u, UserId user_id, int64 photo_id, const vector<FileId> &photo_file_ids);
void on_update_user_full_is_blocked(UserFull *user_full, UserId user_id, bool is_blocked);
void on_update_user_full_common_chat_count(UserFull *user_full, UserId user_id, int32 common_chat_count);
bool on_update_user_full_bot_info(UserFull *user_full, UserId user_id, int32 bot_info_version,
tl_object_ptr<telegram_api::botInfo> &&bot_info);
void invalidate_user_full(UserId user_id);

View File

@ -484,6 +484,7 @@ class SearchPublicDialogsQuery : public Td::ResultHandler {
class GetCommonDialogsQuery : public Td::ResultHandler {
Promise<Unit> promise_;
UserId user_id_;
int32 offset_chat_id_ = 0;
public:
explicit GetCommonDialogsQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
@ -491,6 +492,7 @@ class GetCommonDialogsQuery : public Td::ResultHandler {
void send(UserId user_id, int32 offset_chat_id, int32 limit) {
user_id_ = user_id;
offset_chat_id_ = offset_chat_id;
LOG(INFO) << "Get common dialogs with " << user_id << " from " << offset_chat_id << " with limit " << limit;
auto input_user = td->contacts_manager_->get_input_user(user_id);
@ -512,13 +514,14 @@ class GetCommonDialogsQuery : public Td::ResultHandler {
switch (constructor_id) {
case telegram_api::messages_chats::ID: {
auto chats = move_tl_object_as<telegram_api::messages_chats>(chats_ptr);
td->messages_manager_->on_get_common_dialogs(user_id_, std::move(chats->chats_),
td->messages_manager_->on_get_common_dialogs(user_id_, offset_chat_id_, std::move(chats->chats_),
narrow_cast<int32>(chats->chats_.size()));
break;
}
case telegram_api::messages_chatsSlice::ID: {
auto chats = move_tl_object_as<telegram_api::messages_chatsSlice>(chats_ptr);
td->messages_manager_->on_get_common_dialogs(user_id_, std::move(chats->chats_), chats->count_);
td->messages_manager_->on_get_common_dialogs(user_id_, offset_chat_id_, std::move(chats->chats_),
chats->count_);
break;
}
default:
@ -11681,6 +11684,13 @@ vector<DialogId> MessagesManager::search_dialogs_on_server(const string &query,
return vector<DialogId>();
}
void MessagesManager::drop_common_dialogs_cache(UserId user_id) {
auto it = found_common_dialogs_.find(user_id);
if (it != found_common_dialogs_.end()) {
it->second.is_outdated = true;
}
}
vector<DialogId> MessagesManager::get_common_dialogs(UserId user_id, DialogId offset_dialog_id, int32 limit, bool force,
Promise<Unit> &&promise) {
if (!td_->contacts_manager_->have_input_user(user_id)) {
@ -11723,42 +11733,58 @@ vector<DialogId> MessagesManager::get_common_dialogs(UserId user_id, DialogId of
}
auto it = found_common_dialogs_.find(user_id);
if (it != found_common_dialogs_.end() && !it->second.empty()) {
vector<DialogId> &common_dialog_ids = it->second;
auto offset_it = common_dialog_ids.begin();
if (offset_dialog_id != DialogId()) {
offset_it = std::find(common_dialog_ids.begin(), common_dialog_ids.end(), offset_dialog_id);
if (offset_it == common_dialog_ids.end()) {
promise.set_error(Status::Error(6, "Wrong offset_chat_id"));
return vector<DialogId>();
if (it != found_common_dialogs_.end() && !it->second.dialog_ids.empty()) {
vector<DialogId> &common_dialog_ids = it->second.dialog_ids;
bool use_cache = (!it->second.is_outdated && it->second.received_date >= Time::now() - 3600) || force ||
offset_chat_id != 0 || common_dialog_ids.size() >= static_cast<size_t>(MAX_GET_DIALOGS);
// use cache if it's up to date, or we required to use it or we can't update it
if (use_cache) {
auto offset_it = common_dialog_ids.begin();
if (offset_dialog_id != DialogId()) {
offset_it = std::find(common_dialog_ids.begin(), common_dialog_ids.end(), offset_dialog_id);
if (offset_it == common_dialog_ids.end()) {
promise.set_error(Status::Error(6, "Wrong offset_chat_id"));
return vector<DialogId>();
}
++offset_it;
}
++offset_it;
}
vector<DialogId> result;
while (result.size() < static_cast<size_t>(limit)) {
if (offset_it == common_dialog_ids.end()) {
break;
vector<DialogId> result;
while (result.size() < static_cast<size_t>(limit)) {
if (offset_it == common_dialog_ids.end()) {
break;
}
auto dialog_id = *offset_it++;
if (dialog_id == DialogId()) { // end of the list
promise.set_value(Unit());
return result;
}
result.push_back(dialog_id);
}
auto dialog_id = *offset_it++;
if (dialog_id == DialogId()) { // end of the list
if (result.size() == static_cast<size_t>(limit) || force) {
promise.set_value(Unit());
return result;
}
result.push_back(dialog_id);
}
if (result.size() == static_cast<size_t>(limit) || force) {
promise.set_value(Unit());
return result;
}
}
td_->create_handler<GetCommonDialogsQuery>(std::move(promise))->send(user_id, offset_chat_id, limit);
td_->create_handler<GetCommonDialogsQuery>(std::move(promise))->send(user_id, offset_chat_id, MAX_GET_DIALOGS);
return vector<DialogId>();
}
void MessagesManager::on_get_common_dialogs(UserId user_id, vector<tl_object_ptr<telegram_api::Chat>> &&chats,
int32 total_count) {
auto &result = found_common_dialogs_[user_id];
void MessagesManager::on_get_common_dialogs(UserId user_id, int32 offset_chat_id,
vector<tl_object_ptr<telegram_api::Chat>> &&chats, int32 total_count) {
td_->contacts_manager_->on_update_user_common_chat_count(user_id, total_count);
auto &common_dialogs = found_common_dialogs_[user_id];
if (common_dialogs.is_outdated && offset_chat_id == 0 && common_dialogs.dialog_ids.size() < static_cast<size_t>(MAX_GET_DIALOGS)) {
// drop outdated cache if possible
common_dialogs = CommonDialogs();
}
if (common_dialogs.received_date == 0) {
common_dialogs.received_date = Time::now();
}
common_dialogs.is_outdated = false;
auto &result = common_dialogs.dialog_ids;
if (!result.empty() && result.back() == DialogId()) {
return;
}

View File

@ -266,7 +266,8 @@ class MessagesManager : public Actor {
void on_get_dialogs(vector<tl_object_ptr<telegram_api::dialog>> &&dialogs, int32 total_count,
vector<tl_object_ptr<telegram_api::Message>> &&messages, Promise<Unit> &&promise);
void on_get_common_dialogs(UserId user_id, vector<tl_object_ptr<telegram_api::Chat>> &&chats, int32 total_count);
void on_get_common_dialogs(UserId user_id, int32 offset_chat_id, vector<tl_object_ptr<telegram_api::Chat>> &&chats,
int32 total_count);
bool on_update_message_id(int64 random_id, MessageId new_message_id, const string &source);
@ -465,6 +466,8 @@ class MessagesManager : public Actor {
vector<DialogId> search_dialogs_on_server(const string &query, int32 limit, Promise<Unit> &&promise);
void drop_common_dialogs_cache(UserId user_id);
vector<DialogId> get_common_dialogs(UserId user_id, DialogId offset_dialog_id, int32 limit, bool force,
Promise<Unit> &&promise);
@ -2239,7 +2242,12 @@ class MessagesManager : public Actor {
std::unordered_map<string, vector<DialogId>> found_public_dialogs_; // TODO time bound cache
std::unordered_map<string, vector<DialogId>> found_on_server_dialogs_; // TODO time bound cache
std::unordered_map<UserId, vector<DialogId>, UserIdHash> found_common_dialogs_; // TODO time bound cache
struct CommonDialogs {
vector<DialogId> dialog_ids;
double received_date = 0;
bool is_outdated = false;
};
std::unordered_map<UserId, CommonDialogs, UserIdHash> found_common_dialogs_;
std::unordered_map<int64, FullMessageId> get_dialog_message_by_date_results_;