Add disable_top_chats option.

GitOrigin-RevId: 732ba115f67d19585b4e2f4aae024194c6e65174
This commit is contained in:
levlam 2018-06-26 22:51:00 +03:00
parent 46535703e0
commit 7150cfc8b2
5 changed files with 192 additions and 66 deletions

View File

@ -5,6 +5,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
#pragma once #pragma once
#include "td/mtproto/utils.h" #include "td/mtproto/utils.h"
#include "td/utils/common.h" #include "td/utils/common.h"
@ -234,5 +235,6 @@ class Transport {
static void write_crypto_impl(int X, const Storer &storer, const AuthKey &auth_key, PacketInfo *info, HeaderT *header, static void write_crypto_impl(int X, const Storer &storer, const AuthKey &auth_key, PacketInfo *info, HeaderT *header,
size_t data_size); size_t data_size);
}; };
} // namespace mtproto } // namespace mtproto
} // namespace td } // namespace td

View File

@ -4262,9 +4262,13 @@ void Td::on_config_option_updated(const string &name) {
send_closure(storage_manager_, &StorageManager::update_use_storage_optimizer); send_closure(storage_manager_, &StorageManager::update_use_storage_optimizer);
} else if (name == "rating_e_decay") { } else if (name == "rating_e_decay") {
return send_closure(top_dialog_manager_, &TopDialogManager::update_rating_e_decay); return send_closure(top_dialog_manager_, &TopDialogManager::update_rating_e_decay);
} else if (name == "disable_top_chats") {
send_closure(top_dialog_manager_, &TopDialogManager::update_is_enabled,
!G()->shared_config().get_option_boolean(name));
} else if (is_internal_config_option(name)) { } else if (is_internal_config_option(name)) {
return; return;
} }
// send_closure was already used in the callback // send_closure was already used in the callback
send_update(make_tl_object<td_api::updateOption>(name, G()->shared_config().get_option_value(name))); send_update(make_tl_object<td_api::updateOption>(name, G()->shared_config().get_option_value(name)));
} }
@ -6682,6 +6686,9 @@ void Td::on_request(uint64 id, td_api::setOption &request) {
if (set_boolean_option("disable_contact_registered_notifications")) { if (set_boolean_option("disable_contact_registered_notifications")) {
return; return;
} }
if (set_boolean_option("disable_top_chats")) {
return;
}
break; break;
case 'i': case 'i':
if (set_boolean_option("ignore_inline_thumbnails")) { if (set_boolean_option("ignore_inline_thumbnails")) {

View File

@ -90,8 +90,42 @@ static tl_object_ptr<telegram_api::TopPeerCategory> top_dialog_category_as_teleg
} }
} }
void TopDialogManager::update_is_enabled(bool is_enabled) {
if (set_is_enabled(is_enabled)) {
G()->td_db()->get_binlog_pmc()->set("top_peers_enabled", is_enabled ? "1" : "0");
send_toggle_top_peers(is_enabled);
loop();
}
}
bool TopDialogManager::set_is_enabled(bool is_enabled) {
if (is_enabled_ == is_enabled) {
return false;
}
LOG(DEBUG) << "Change top chats is_enabled to " << is_enabled;
is_enabled_ = is_enabled;
init();
return true;
}
void TopDialogManager::send_toggle_top_peers(bool is_enabled) {
if (have_toggle_top_peers_query_) {
have_pending_toggle_top_peers_query_ = true;
pending_toggle_top_peers_query_ = is_enabled;
return;
}
LOG(DEBUG) << "Send toggle top peers query to " << is_enabled;
have_toggle_top_peers_query_ = true;
toggle_top_peers_query_is_enabled_ = is_enabled;
auto net_query = G()->net_query_creator().create(create_storer(telegram_api::contacts_toggleTopPeers(is_enabled)));
G()->net_query_dispatcher().dispatch_with_callback(std::move(net_query), actor_shared(this, 2));
}
void TopDialogManager::on_dialog_used(TopDialogCategory category, DialogId dialog_id, int32 date) { void TopDialogManager::on_dialog_used(TopDialogCategory category, DialogId dialog_id, int32 date) {
if (!is_active_) { if (!is_active_ || !is_enabled_) {
return; return;
} }
auto pos = static_cast<size_t>(category); auto pos = static_cast<size_t>(category);
@ -129,7 +163,7 @@ void TopDialogManager::on_dialog_used(TopDialogCategory category, DialogId dialo
void TopDialogManager::remove_dialog(TopDialogCategory category, DialogId dialog_id, void TopDialogManager::remove_dialog(TopDialogCategory category, DialogId dialog_id,
tl_object_ptr<telegram_api::InputPeer> input_peer) { tl_object_ptr<telegram_api::InputPeer> input_peer) {
if (!is_active_) { if (!is_active_ || !is_enabled_) {
return; return;
} }
@ -165,6 +199,11 @@ void TopDialogManager::get_top_dialogs(TopDialogCategory category, size_t limit,
promise.set_error(Status::Error(400, "Not supported without chat info database")); promise.set_error(Status::Error(400, "Not supported without chat info database"));
return; return;
} }
if (!is_enabled_) {
promise.set_error(Status::Error(400, "Top chats computation is disabled"));
return;
}
GetTopDialogsQuery query; GetTopDialogsQuery query;
query.category = category; query.category = category;
query.limit = limit; query.limit = limit;
@ -302,33 +341,66 @@ void TopDialogManager::do_get_top_peers() {
} }
void TopDialogManager::on_result(NetQueryPtr net_query) { void TopDialogManager::on_result(NetQueryPtr net_query) {
if (get_link_token() == 1) { auto query_type = get_link_token();
if (query_type == 2) { // toggleTopPeers
CHECK(have_toggle_top_peers_query_);
have_toggle_top_peers_query_ = false;
if (have_pending_toggle_top_peers_query_) {
have_pending_toggle_top_peers_query_ = false;
if (pending_toggle_top_peers_query_ != toggle_top_peers_query_is_enabled_) {
send_toggle_top_peers(pending_toggle_top_peers_query_);
return;
}
}
auto r_result = fetch_result<telegram_api::contacts_toggleTopPeers>(std::move(net_query));
if (r_result.is_ok()) {
// everything is synchronized
G()->td_db()->get_binlog_pmc()->erase("top_peers_enabled");
} else {
// let's resend the query forever
if (!G()->close_flag()) {
send_toggle_top_peers(toggle_top_peers_query_is_enabled_);
}
}
return;
}
if (query_type == 1) { // resetTopPeerRating
// ignore result
return; return;
} }
SCOPE_EXIT { SCOPE_EXIT {
loop(); loop();
}; };
normalize_rating(); // once a day too normalize_rating(); // once a day too
last_server_sync_ = Timestamp::now();
server_sync_state_ = SyncState::Ok;
G()->td_db()->get_binlog_pmc()->set("top_dialogs_ts", to_string(static_cast<uint32>(Clocks::system())));
auto r_top_peers = fetch_result<telegram_api::contacts_getTopPeers>(std::move(net_query)); auto r_top_peers = fetch_result<telegram_api::contacts_getTopPeers>(std::move(net_query));
if (r_top_peers.is_error()) { if (r_top_peers.is_error()) {
LOG(ERROR) << "contacts_getTopPeers failed: " << r_top_peers.error(); last_server_sync_ = Timestamp::in(SERVER_SYNC_RESEND_DELAY - SERVER_SYNC_DELAY);
return;
}
auto top_peers_parent = r_top_peers.move_as_ok();
LOG(INFO) << "contacts_getTopPeers returned " << to_string(top_peers_parent);
if (top_peers_parent->get_id() == telegram_api::contacts_topPeersNotModified::ID) {
return;
}
if (top_peers_parent->get_id() == telegram_api::contacts_topPeersDisabled::ID) {
// FIXME
return; return;
} }
CHECK(top_peers_parent->get_id() == telegram_api::contacts_topPeers::ID); last_server_sync_ = Timestamp::now();
server_sync_state_ = SyncState::Ok;
SCOPE_EXIT {
G()->td_db()->get_binlog_pmc()->set("top_dialogs_ts", to_string(static_cast<uint32>(Clocks::system())));
};
auto top_peers_parent = r_top_peers.move_as_ok();
LOG(DEBUG) << "contacts_getTopPeers returned " << to_string(top_peers_parent);
switch (top_peers_parent->get_id()) {
case telegram_api::contacts_topPeersNotModified::ID:
// nothing to do
return;
case telegram_api::contacts_topPeersDisabled::ID:
G()->shared_config().set_option_boolean("disable_top_chats", true);
set_is_enabled(false); // apply immediately
return;
case telegram_api::contacts_topPeers::ID: {
G()->shared_config().set_option_empty("disable_top_chats");
set_is_enabled(true); // apply immediately
auto top_peers = move_tl_object_as<telegram_api::contacts_topPeers>(std::move(top_peers_parent)); auto top_peers = move_tl_object_as<telegram_api::contacts_topPeers>(std::move(top_peers_parent));
send_closure(G()->contacts_manager(), &ContactsManager::on_get_users, std::move(top_peers->users_)); send_closure(G()->contacts_manager(), &ContactsManager::on_get_users, std::move(top_peers->users_));
@ -349,6 +421,11 @@ void TopDialogManager::on_result(NetQueryPtr net_query) {
} }
} }
db_sync_state_ = SyncState::None; db_sync_state_ = SyncState::None;
break;
}
default:
UNREACHABLE();
}
} }
void TopDialogManager::do_save_top_dialogs() { void TopDialogManager::do_save_top_dialogs() {
@ -370,12 +447,31 @@ void TopDialogManager::do_save_top_dialogs() {
} }
void TopDialogManager::start_up() { void TopDialogManager::start_up() {
if (!G()->parameters().use_chat_info_db) { is_active_ = G()->parameters().use_chat_info_db;
is_enabled_ = !G()->shared_config().get_option_boolean("disable_top_chats");
update_rating_e_decay();
string need_update_top_peers = G()->td_db()->get_binlog_pmc()->get("top_peers_enabled");
if (!need_update_top_peers.empty()) {
send_toggle_top_peers(need_update_top_peers[0] == '1');
}
init();
loop();
}
void TopDialogManager::init() {
was_first_sync_ = false;
first_unsync_change_ = Timestamp();
server_sync_state_ = SyncState::None;
last_server_sync_ = Timestamp();
CHECK(pending_get_top_dialogs_.empty());
LOG(DEBUG) << "Init is enabled: " << is_enabled_;
if (!is_active_) {
G()->td_db()->get_binlog_pmc()->erase_by_prefix("top_dialogs"); G()->td_db()->get_binlog_pmc()->erase_by_prefix("top_dialogs");
is_active_ = false;
return; return;
} }
is_active_ = true;
auto di_top_dialogs_ts = G()->td_db()->get_binlog_pmc()->get("top_dialogs_ts"); auto di_top_dialogs_ts = G()->td_db()->get_binlog_pmc()->get("top_dialogs_ts");
if (!di_top_dialogs_ts.empty()) { if (!di_top_dialogs_ts.empty()) {
@ -384,8 +480,8 @@ void TopDialogManager::start_up() {
server_sync_state_ = SyncState::Ok; server_sync_state_ = SyncState::Ok;
} }
} }
update_rating_e_decay();
if (is_enabled_) {
for (size_t top_dialog_category_i = 0; top_dialog_category_i < by_category_.size(); top_dialog_category_i++) { for (size_t top_dialog_category_i = 0; top_dialog_category_i < by_category_.size(); top_dialog_category_i++) {
auto top_dialog_category = TopDialogCategory(top_dialog_category_i); auto top_dialog_category = TopDialogCategory(top_dialog_category_i);
auto key = PSTRING() << "top_dialogs#" << top_dialog_category_name(top_dialog_category); auto key = PSTRING() << "top_dialogs#" << top_dialog_category_name(top_dialog_category);
@ -399,12 +495,18 @@ void TopDialogManager::start_up() {
log_event_parse(top_dialogs, value).ensure(); log_event_parse(top_dialogs, value).ensure();
} }
normalize_rating(); normalize_rating();
} else {
G()->td_db()->get_binlog_pmc()->erase_by_prefix("top_dialogs#");
for (auto &top_dialogs : by_category_) {
top_dialogs.is_dirty = false;
top_dialogs.rating_timestamp = 0;
top_dialogs.dialogs.clear();
}
}
db_sync_state_ = SyncState::Ok; db_sync_state_ = SyncState::Ok;
send_closure(G()->state_manager(), &StateManager::wait_first_sync, send_closure(G()->state_manager(), &StateManager::wait_first_sync,
PromiseCreator::event(self_closure(this, &TopDialogManager::on_first_sync))); PromiseCreator::event(self_closure(this, &TopDialogManager::on_first_sync)));
loop();
} }
void TopDialogManager::on_first_sync() { void TopDialogManager::on_first_sync() {
@ -441,6 +543,7 @@ void TopDialogManager::loop() {
do_get_top_peers(); do_get_top_peers();
} }
if (is_enabled_) {
// db sync // db sync
Timestamp db_sync_timeout; Timestamp db_sync_timeout;
if (db_sync_state_ == SyncState::Ok) { if (db_sync_state_ == SyncState::Ok) {
@ -459,6 +562,7 @@ void TopDialogManager::loop() {
do_save_top_dialogs(); do_save_top_dialogs();
} }
} }
}
if (wakeup_timeout) { if (wakeup_timeout) {
LOG(INFO) << "Wakeup in: " << wakeup_timeout.in(); LOG(INFO) << "Wakeup in: " << wakeup_timeout.in();

View File

@ -57,13 +57,23 @@ class TopDialogManager : public NetQueryCallback {
void update_rating_e_decay(); void update_rating_e_decay();
void update_is_enabled(bool is_enabled);
private: private:
static constexpr size_t MAX_TOP_DIALOGS_LIMIT = 30; static constexpr size_t MAX_TOP_DIALOGS_LIMIT = 30;
static constexpr int32 SERVER_SYNC_DELAY = 86400; // seconds static constexpr int32 SERVER_SYNC_DELAY = 86400; // seconds
static constexpr int32 SERVER_SYNC_RESEND_DELAY = 60; // seconds
static constexpr int32 DB_SYNC_DELAY = 5; // seconds static constexpr int32 DB_SYNC_DELAY = 5; // seconds
ActorShared<> parent_; ActorShared<> parent_;
bool is_active_{false}; bool is_active_{false};
bool is_enabled_{true};
int32 rating_e_decay_ = 241920;
bool have_toggle_top_peers_query_ = false;
bool toggle_top_peers_query_is_enabled_ = false;
bool have_pending_toggle_top_peers_query_ = false;
bool pending_toggle_top_peers_query_ = false;
bool was_first_sync_{false}; bool was_first_sync_{false};
enum class SyncState : int32 { None, Pending, Ok }; enum class SyncState : int32 { None, Pending, Ok };
SyncState db_sync_state_ = SyncState::None; SyncState db_sync_state_ = SyncState::None;
@ -106,7 +116,8 @@ class TopDialogManager : public NetQueryCallback {
double current_rating_add(double rating_timestamp) const; double current_rating_add(double rating_timestamp) const;
void normalize_rating(); void normalize_rating();
int32 rating_e_decay_ = 241920; bool set_is_enabled(bool is_enabled);
void send_toggle_top_peers(bool is_enabled);
void do_get_top_dialogs(GetTopDialogsQuery &&query); void do_get_top_dialogs(GetTopDialogsQuery &&query);
@ -117,6 +128,8 @@ class TopDialogManager : public NetQueryCallback {
void on_result(NetQueryPtr net_query) override; void on_result(NetQueryPtr net_query) override;
void init();
void start_up() override; void start_up() override;
void loop() override; void loop() override;
}; };

View File

@ -176,7 +176,7 @@ class Status {
void ensure_impl(CSlice file_name, int line) const { void ensure_impl(CSlice file_name, int line) const {
if (!is_ok()) { if (!is_ok()) {
LOG(FATAL) << "Unexpexted Status " << to_string() << " in file " << file_name << " at line " << line; LOG(FATAL) << "Unexpected Status " << to_string() << " in file " << file_name << " at line " << line;
} }
} }
void ensure_error_impl(CSlice file_name, int line) const { void ensure_error_impl(CSlice file_name, int line) const {