Unload unused for some time polls.
This commit is contained in:
parent
3d796860d2
commit
77019caf61
@ -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(on_close_poll_timeout_callback);
|
||||||
close_poll_timeout_.set_callback_data(static_cast<void *>(this));
|
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() {
|
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));
|
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) {
|
bool PollManager::is_local_poll_id(PollId poll_id) {
|
||||||
return poll_id.get() < 0 && poll_id.get() > std::numeric_limits<int32>::min();
|
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) {
|
PollManager::Poll *PollManager::get_poll_editable(PollId poll_id) {
|
||||||
auto p = polls_.find(poll_id);
|
auto p = polls_.find(poll_id);
|
||||||
if (p == polls_.end()) {
|
if (p == polls_.end()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else {
|
} else {
|
||||||
|
schedule_poll_unload(poll_id);
|
||||||
return p->second.get();
|
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)) {
|
!(poll->is_closed && poll->is_updated_after_close)) {
|
||||||
update_poll_timeout_.add_timeout_in(poll_id.get(), 0);
|
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) {
|
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()) {
|
if (message_ids.empty()) {
|
||||||
poll_messages_.erase(poll_id);
|
poll_messages_.erase(poll_id);
|
||||||
update_poll_timeout_.cancel_timeout(poll_id.get());
|
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);
|
binlog_erase(G()->td_db()->get_binlog(), log_event_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
unload_poll_timeout_.cancel_timeout(poll_id.get());
|
||||||
|
|
||||||
auto &pending_answer = pending_answers_[poll_id];
|
auto &pending_answer = pending_answers_[poll_id];
|
||||||
if (!pending_answer.promises_.empty() && pending_answer.options_ == options) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unload_poll_timeout_.cancel_timeout(poll_id.get());
|
||||||
|
|
||||||
auto query_promise =
|
auto query_promise =
|
||||||
PromiseCreator::lambda([actor_id = actor_id(this), poll_id, option_id, offset = voters.next_offset,
|
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 {
|
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));
|
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;
|
bool is_inserted = being_closed_polls_.insert(poll_id).second;
|
||||||
CHECK(is_inserted);
|
CHECK(is_inserted);
|
||||||
auto new_promise = get_erase_log_event_promise(log_event_id, std::move(promise));
|
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));
|
CHECK(!is_local_poll_id(poll_id));
|
||||||
|
|
||||||
auto poll = get_poll(poll_id);
|
auto poll = get_poll(poll_id);
|
||||||
CHECK(poll != nullptr);
|
if (poll == nullptr || (poll->is_closed && poll->is_updated_after_close)) {
|
||||||
if (poll->is_closed && poll->is_updated_after_close) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pending_answers_.count(poll_id) > 0) {
|
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));
|
CHECK(!is_local_poll_id(poll_id));
|
||||||
|
|
||||||
auto poll = get_poll_editable(poll_id);
|
auto poll = get_poll_editable(poll_id);
|
||||||
CHECK(poll != nullptr);
|
if (poll == nullptr || poll->is_closed || poll->close_date == 0) {
|
||||||
if (poll->is_closed || poll->close_date == 0) {
|
|
||||||
return;
|
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,
|
void PollManager::on_get_poll_results(PollId poll_id, uint64 generation,
|
||||||
Result<tl_object_ptr<telegram_api::Updates>> result) {
|
Result<tl_object_ptr<telegram_api::Updates>> result) {
|
||||||
auto poll = get_poll(poll_id);
|
auto poll = get_poll(poll_id);
|
||||||
CHECK(poll != nullptr);
|
if (poll == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (result.is_error()) {
|
if (result.is_error()) {
|
||||||
if (!(poll->is_closed && poll->is_updated_after_close) && !G()->close_flag() && !td_->auth_manager_->is_bot()) {
|
if (!(poll->is_closed && poll->is_updated_after_close) && !G()->close_flag() && !td_->auth_manager_->is_bot()) {
|
||||||
auto timeout = get_polling_timeout();
|
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))) {
|
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)));
|
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;
|
return poll_id;
|
||||||
}
|
}
|
||||||
|
@ -136,6 +136,7 @@ class PollManager final : public Actor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static constexpr int32 MAX_GET_POLL_VOTERS = 50; // server side limit
|
static constexpr int32 MAX_GET_POLL_VOTERS = 50; // server side limit
|
||||||
|
static constexpr int32 UNLOAD_POLL_DELAY = 600; // some reasonable value
|
||||||
|
|
||||||
class SetPollAnswerLogEvent;
|
class SetPollAnswerLogEvent;
|
||||||
class StopPollLogEvent;
|
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_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 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);
|
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) const;
|
||||||
|
|
||||||
|
const Poll *get_poll(PollId poll_id);
|
||||||
|
|
||||||
Poll *get_poll_editable(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);
|
void notify_on_poll_update(PollId poll_id);
|
||||||
|
|
||||||
static string get_poll_database_key(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_close_poll_timeout(PollId poll_id);
|
||||||
|
|
||||||
|
void on_unload_poll_timeout(PollId poll_id);
|
||||||
|
|
||||||
void on_online();
|
void on_online();
|
||||||
|
|
||||||
Poll *get_poll_force(PollId poll_id);
|
Poll *get_poll_force(PollId poll_id);
|
||||||
@ -204,6 +215,7 @@ class PollManager final : public Actor {
|
|||||||
|
|
||||||
MultiTimeout update_poll_timeout_{"UpdatePollTimeout"};
|
MultiTimeout update_poll_timeout_{"UpdatePollTimeout"};
|
||||||
MultiTimeout close_poll_timeout_{"ClosePollTimeout"};
|
MultiTimeout close_poll_timeout_{"ClosePollTimeout"};
|
||||||
|
MultiTimeout unload_poll_timeout_{"UnloadPollTimeout"};
|
||||||
|
|
||||||
Td *td_;
|
Td *td_;
|
||||||
ActorShared<> parent_;
|
ActorShared<> parent_;
|
||||||
|
Loading…
Reference in New Issue
Block a user