diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index ec0d1e44..d3991a4b 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -717,6 +717,10 @@ class MessagesManager : public Actor { void get_current_state(vector> &updates) const; + static void add_dialog_dependencies(Dependencies &dependencies, DialogId dialog_id); + + void resolve_dependencies_force(const Dependencies &dependencies); + ActorOwn sequence_dispatcher_; private: @@ -2027,10 +2031,6 @@ class MessagesManager : public Actor { static void add_message_dependencies(Dependencies &dependencies, DialogId dialog_id, const Message *m); - static void add_dialog_dependencies(Dependencies &dependencies, DialogId dialog_id); - - void resolve_dependencies_force(const Dependencies &dependencies); - void save_send_message_logevent(DialogId dialog_id, Message *m); uint64 save_change_dialog_report_spam_state_on_server_logevent(DialogId dialog_id, bool is_spam_dialog); diff --git a/td/telegram/PollManager.cpp b/td/telegram/PollManager.cpp index 001ff402..9488edcf 100644 --- a/td/telegram/PollManager.cpp +++ b/td/telegram/PollManager.cpp @@ -10,12 +10,16 @@ #include "td/telegram/logevent/LogEvent.h" #include "td/telegram/MessagesManager.h" #include "td/telegram/net/NetActor.h" +#include "td/telegram/PollId.hpp" #include "td/telegram/PollManager.hpp" #include "td/telegram/SequenceDispatcher.h" #include "td/telegram/TdDb.h" #include "td/telegram/Td.h" +#include "td/telegram/TdParameters.h" #include "td/telegram/UpdatesManager.h" +#include "td/db/binlog/BinlogEvent.h" +#include "td/db/binlog/BinlogHelper.h" #include "td/db/SqliteKeyValue.h" #include "td/db/SqliteKeyValueAsync.h" @@ -35,8 +39,7 @@ class SetPollAnswerQuery : public NetActorOnce { explicit SetPollAnswerQuery(Promise &&promise) : promise_(std::move(promise)) { } - void send(FullMessageId full_message_id, vector &&options, uint64 generation, - NetQueryRef *query_ref) { + void send(FullMessageId full_message_id, vector &&options, uint64 generation, NetQueryRef *query_ref) { dialog_id_ = full_message_id.get_dialog_id(); auto input_peer = td->messages_manager_->get_input_peer(dialog_id_, AccessRights::Read); if (input_peer == nullptr) { @@ -264,6 +267,27 @@ void PollManager::set_poll_answer(PollId poll_id, FullMessageId full_message_id, do_set_poll_answer(poll_id, full_message_id, std::move(options), 0, std::move(promise)); } +class PollManager::SetPollAnswerLogEvent { + public: + PollId poll_id_; + FullMessageId full_message_id_; + vector options_; + + template + void store(StorerT &storer) const { + td::store(poll_id_, storer); + td::store(full_message_id_, storer); + td::store(options_, storer); + } + + template + void parse(ParserT &parser) { + td::parse(poll_id_, parser); + td::parse(full_message_id_, parser); + td::parse(options_, parser); + } +}; + void PollManager::do_set_poll_answer(PollId poll_id, FullMessageId full_message_id, vector &&options, uint64 logevent_id, Promise &&promise) { auto &pending_answer = pending_answers_[poll_id]; @@ -272,8 +296,24 @@ void PollManager::do_set_poll_answer(PollId poll_id, FullMessageId full_message_ return; } + CHECK(pending_answer.logevent_id_ == 0 || logevent_id == 0); if (logevent_id == 0 && G()->parameters().use_message_db) { - // TODO add logevent or rewrite pending_answer.logevent_id_ + SetPollAnswerLogEvent logevent; + logevent.poll_id_ = poll_id; + logevent.full_message_id_ = full_message_id; + logevent.options_ = options; + auto storer = LogEventStorerImpl(logevent); + if (pending_answer.generation_ == 0) { + CHECK(pending_answer.logevent_id_ == 0); + logevent_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::SetPollAnswer, storer); + LOG(INFO) << "Add set poll answer logevent " << logevent_id; + } else { + CHECK(pending_answer.logevent_id_ != 0); + logevent_id = pending_answer.logevent_id_; + auto new_logevent_id = binlog_rewrite(G()->td_db()->get_binlog(), pending_answer.logevent_id_, + LogEvent::HandlerType::SetPollAnswer, storer); + LOG(INFO) << "Rewrite set poll answer logevent " << logevent_id << " with " << new_logevent_id; + } } if (!pending_answer.promises_.empty()) { @@ -328,13 +368,10 @@ void PollManager::on_set_poll_answer(PollId poll_id, uint64 generation, Resulttd_db()->get_binlog(), pending_answer.logevent_id_); } - CHECK(!pending_answer.query_ref_.empty()); - cancel_query(pending_answer.query_ref_); - pending_answer.query_ref_ = NetQueryRef(); - auto promises = std::move(pending_answer.promises_); for (auto &promise : promises) { if (result.is_ok()) { @@ -471,4 +508,32 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr &&events) { + for (auto &event : events) { + switch (event.type_) { + case LogEvent::HandlerType::SetPollAnswer: { + if (!G()->parameters().use_message_db) { + binlog_erase(G()->td_db()->get_binlog(), event.id_); + break; + } + + SetPollAnswerLogEvent log_event; + log_event_parse(log_event, event.data_).ensure(); + + auto dialog_id = log_event.full_message_id_.get_dialog_id(); + + Dependencies dependencies; + td_->messages_manager_->add_dialog_dependencies(dependencies, dialog_id); + td_->messages_manager_->resolve_dependencies_force(dependencies); + + do_set_poll_answer(log_event.poll_id_, log_event.full_message_id_, std::move(log_event.options_), event.id_, + Auto()); + break; + } + default: + LOG(FATAL) << "Unsupported logevent type " << event.type_; + } + } +} + } // namespace td diff --git a/td/telegram/PollManager.h b/td/telegram/PollManager.h index 90eda109..799a8183 100644 --- a/td/telegram/PollManager.h +++ b/td/telegram/PollManager.h @@ -22,6 +22,8 @@ namespace td { +struct BinlogEvent; + class Td; class PollManager : public Actor { @@ -52,6 +54,8 @@ class PollManager : public Actor { td_api::object_ptr get_poll_object(PollId poll_id) const; + void on_binlog_events(vector &&events); + template void store_poll(PollId poll_id, StorerT &storer) const; @@ -83,6 +87,8 @@ class PollManager : public Actor { void parse(ParserT &parser); }; + class SetPollAnswerLogEvent; + void tear_down() override; static bool is_local_poll_id(PollId poll_id); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 52efb3a1..99fe01f0 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -4280,6 +4280,8 @@ Status Td::init(DbKey key) { send_closure_later(secret_chats_manager_, &SecretChatsManager::replay_binlog_event, std::move(event)); } + send_closure_later(poll_manager_actor_, &PollManager::on_binlog_events, std::move(events.to_poll_manager)); + send_closure_later(messages_manager_actor_, &MessagesManager::on_binlog_events, std::move(events.to_messages_manager)); diff --git a/td/telegram/TdDb.cpp b/td/telegram/TdDb.cpp index 4c558440..c6c27f6a 100644 --- a/td/telegram/TdDb.cpp +++ b/td/telegram/TdDb.cpp @@ -75,6 +75,9 @@ Status init_binlog(Binlog &binlog, string path, BinlogKeyValue &binlog_p case LogEvent::HandlerType::WebPages: events.web_page_events.push_back(event.clone()); break; + case LogEvent::HandlerType::SetPollAnswer: + events.to_poll_manager.push_back(event.clone()); + break; case LogEvent::HandlerType::SendMessage: case LogEvent::HandlerType::DeleteMessage: case LogEvent::HandlerType::DeleteMessagesFromServer: diff --git a/td/telegram/TdDb.h b/td/telegram/TdDb.h index 3adf36df..991ea76d 100644 --- a/td/telegram/TdDb.h +++ b/td/telegram/TdDb.h @@ -55,6 +55,7 @@ class TdDb { vector channel_events; vector secret_chat_events; vector web_page_events; + vector to_poll_manager; vector to_messages_manager; }; static Result> open(int32 scheduler_id, const TdParameters ¶meters, DbKey key, Events &events); diff --git a/td/telegram/logevent/LogEvent.h b/td/telegram/logevent/LogEvent.h index cdb427cb..09caa040 100644 --- a/td/telegram/logevent/LogEvent.h +++ b/td/telegram/logevent/LogEvent.h @@ -69,6 +69,7 @@ class LogEvent { Channels = 4, SecretChatInfos = 5, WebPages = 0x10, + SetPollAnswer = 0x20, SendMessage = 0x100, DeleteMessage = 0x101, DeleteMessagesFromServer = 0x102, diff --git a/test/tdclient.cpp b/test/tdclient.cpp index 7a91113c..eda9fa0a 100644 --- a/test/tdclient.cpp +++ b/test/tdclient.cpp @@ -614,7 +614,7 @@ class CheckTestC : public Task { if (text.substr(0, tag_.size()) == tag_) { file_id_to_check_ = messageDocument->document_->document_->id_; LOG(ERROR) << "GOT FILE " << to_string(messageDocument->document_->document_); - this->send_query(make_tl_object(file_id_to_check_, 1, 0), + this->send_query(make_tl_object(file_id_to_check_, 1, 0, 0), [](auto res) { check_td_error(res); }); } }