Unload unused for some time polls.

This commit is contained in:
levlam 2022-05-09 01:46:46 +03:00
parent 3d796860d2
commit 77019caf61
2 changed files with 96 additions and 5 deletions

View File

@ -238,6 +238,9 @@ PollManager::PollManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::m
close_poll_timeout_.set_callback(on_close_poll_timeout_callback);
close_poll_timeout_.set_callback_data(static_cast<void *>(this));
unload_poll_timeout_.set_callback(on_unload_poll_timeout_callback);
unload_poll_timeout_.set_callback_data(static_cast<void *>(this));
}
void PollManager::start_up() {
@ -282,6 +285,15 @@ void PollManager::on_close_poll_timeout_callback(void *poll_manager_ptr, int64 p
send_closure_later(poll_manager->actor_id(poll_manager), &PollManager::on_close_poll_timeout, PollId(poll_id_int));
}
void PollManager::on_unload_poll_timeout_callback(void *poll_manager_ptr, int64 poll_id_int) {
if (G()->close_flag()) {
return;
}
auto poll_manager = static_cast<PollManager *>(poll_manager_ptr);
send_closure_later(poll_manager->actor_id(poll_manager), &PollManager::on_unload_poll_timeout, PollId(poll_id_int));
}
bool PollManager::is_local_poll_id(PollId poll_id) {
return poll_id.get() < 0 && poll_id.get() > std::numeric_limits<int32>::min();
}
@ -295,11 +307,22 @@ const PollManager::Poll *PollManager::get_poll(PollId poll_id) const {
}
}
const PollManager::Poll *PollManager::get_poll(PollId poll_id) {
auto p = polls_.find(poll_id);
if (p == polls_.end()) {
return nullptr;
} else {
schedule_poll_unload(poll_id);
return p->second.get();
}
}
PollManager::Poll *PollManager::get_poll_editable(PollId poll_id) {
auto p = polls_.find(poll_id);
if (p == polls_.end()) {
return nullptr;
} else {
schedule_poll_unload(poll_id);
return p->second.get();
}
}
@ -637,6 +660,7 @@ void PollManager::register_poll(PollId poll_id, FullMessageId full_message_id, c
!(poll->is_closed && poll->is_updated_after_close)) {
update_poll_timeout_.add_timeout_in(poll_id.get(), 0);
}
unload_poll_timeout_.cancel_timeout(poll_id.get());
}
void PollManager::unregister_poll(PollId poll_id, FullMessageId full_message_id, const char *source) {
@ -654,6 +678,32 @@ void PollManager::unregister_poll(PollId poll_id, FullMessageId full_message_id,
if (message_ids.empty()) {
poll_messages_.erase(poll_id);
update_poll_timeout_.cancel_timeout(poll_id.get());
schedule_poll_unload(poll_id);
}
}
bool PollManager::can_unload_poll(PollId poll_id) {
if (is_local_poll_id(poll_id) || poll_messages_.count(poll_id) != 0 || pending_answers_.count(poll_id) != 0 ||
being_closed_polls_.count(poll_id) != 0) {
return false;
}
auto it = poll_voters_.find(poll_id);
if (it != poll_voters_.end() && !it->second.empty()) {
for (auto &voters : it->second) {
if (!voters.pending_queries.empty()) {
return false;
}
}
}
return true;
}
void PollManager::schedule_poll_unload(PollId poll_id) {
if (can_unload_poll(poll_id)) {
unload_poll_timeout_.set_timeout_in(poll_id.get(), UNLOAD_POLL_DELAY);
}
}
@ -763,6 +813,7 @@ void PollManager::do_set_poll_answer(PollId poll_id, FullMessageId full_message_
binlog_erase(G()->td_db()->get_binlog(), log_event_id);
return;
}
unload_poll_timeout_.cancel_timeout(poll_id.get());
auto &pending_answer = pending_answers_[poll_id];
if (!pending_answer.promises_.empty() && pending_answer.options_ == options) {
@ -986,6 +1037,8 @@ void PollManager::get_poll_voters(PollId poll_id, FullMessageId full_message_id,
return;
}
unload_poll_timeout_.cancel_timeout(poll_id.get());
auto query_promise =
PromiseCreator::lambda([actor_id = actor_id(this), poll_id, option_id, offset = voters.next_offset,
limit](Result<tl_object_ptr<telegram_api::messages_votesList>> &&result) mutable {
@ -1135,6 +1188,8 @@ void PollManager::do_stop_poll(PollId poll_id, FullMessageId full_message_id, un
binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::StopPoll, get_log_event_storer(log_event));
}
unload_poll_timeout_.cancel_timeout(poll_id.get());
bool is_inserted = being_closed_polls_.insert(poll_id).second;
CHECK(is_inserted);
auto new_promise = get_erase_log_event_promise(log_event_id, std::move(promise));
@ -1167,8 +1222,7 @@ void PollManager::on_update_poll_timeout(PollId poll_id) {
CHECK(!is_local_poll_id(poll_id));
auto poll = get_poll(poll_id);
CHECK(poll != nullptr);
if (poll->is_closed && poll->is_updated_after_close) {
if (poll == nullptr || (poll->is_closed && poll->is_updated_after_close)) {
return;
}
if (pending_answers_.count(poll_id) > 0) {
@ -1197,8 +1251,7 @@ void PollManager::on_close_poll_timeout(PollId poll_id) {
CHECK(!is_local_poll_id(poll_id));
auto poll = get_poll_editable(poll_id);
CHECK(poll != nullptr);
if (poll->is_closed || poll->close_date == 0) {
if (poll == nullptr || poll->is_closed || poll->close_date == 0) {
return;
}
@ -1218,10 +1271,34 @@ void PollManager::on_close_poll_timeout(PollId poll_id) {
}
}
void PollManager::on_unload_poll_timeout(PollId poll_id) {
if (G()->close_flag()) {
return;
}
CHECK(!is_local_poll_id(poll_id));
if (!can_unload_poll(poll_id)) {
return;
}
LOG(INFO) << "Unload " << poll_id;
update_poll_timeout_.cancel_timeout(poll_id.get());
close_poll_timeout_.cancel_timeout(poll_id.get());
auto is_deleted = polls_.erase(poll_id) > 0;
CHECK(is_deleted);
poll_voters_.erase(poll_id);
loaded_from_database_polls_.erase(poll_id);
}
void PollManager::on_get_poll_results(PollId poll_id, uint64 generation,
Result<tl_object_ptr<telegram_api::Updates>> result) {
auto poll = get_poll(poll_id);
CHECK(poll != nullptr);
if (poll == nullptr) {
return;
}
if (result.is_error()) {
if (!(poll->is_closed && poll->is_updated_after_close) && !G()->close_flag() && !td_->auth_manager_->is_bot()) {
auto timeout = get_polling_timeout();
@ -1642,6 +1719,8 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
}
if (need_update_poll && (is_changed || (poll->is_closed && being_closed_polls_.erase(poll_id) != 0))) {
send_closure(G()->td(), &Td::send_update, td_api::make_object<td_api::updatePoll>(get_poll_object(poll_id, poll)));
schedule_poll_unload(poll_id);
}
return poll_id;
}

View File

@ -136,6 +136,7 @@ class PollManager final : public Actor {
};
static constexpr int32 MAX_GET_POLL_VOTERS = 50; // server side limit
static constexpr int32 UNLOAD_POLL_DELAY = 600; // some reasonable value
class SetPollAnswerLogEvent;
class StopPollLogEvent;
@ -147,6 +148,8 @@ class PollManager final : public Actor {
static void on_close_poll_timeout_callback(void *poll_manager_ptr, int64 poll_id_int);
static void on_unload_poll_timeout_callback(void *poll_manager_ptr, int64 poll_id_int);
static td_api::object_ptr<td_api::pollOption> get_poll_option_object(const PollOption &poll_option);
static telegram_api::object_ptr<telegram_api::pollAnswer> get_input_poll_option(const PollOption &poll_option);
@ -159,8 +162,14 @@ class PollManager final : public Actor {
const Poll *get_poll(PollId poll_id) const;
const Poll *get_poll(PollId poll_id);
Poll *get_poll_editable(PollId poll_id);
bool can_unload_poll(PollId poll_id);
void schedule_poll_unload(PollId poll_id);
void notify_on_poll_update(PollId poll_id);
static string get_poll_database_key(PollId poll_id);
@ -175,6 +184,8 @@ class PollManager final : public Actor {
void on_close_poll_timeout(PollId poll_id);
void on_unload_poll_timeout(PollId poll_id);
void on_online();
Poll *get_poll_force(PollId poll_id);
@ -204,6 +215,7 @@ class PollManager final : public Actor {
MultiTimeout update_poll_timeout_{"UpdatePollTimeout"};
MultiTimeout close_poll_timeout_{"ClosePollTimeout"};
MultiTimeout unload_poll_timeout_{"UnloadPollTimeout"};
Td *td_;
ActorShared<> parent_;