From d5af2f6ceddf84ae488cf5a05ff5fff9511d67e6 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 19 Feb 2024 22:30:07 +0300 Subject: [PATCH] Save time zones to binlog. --- td/telegram/TimeZoneManager.cpp | 63 +++++++++++++++++++++++++++++++++ td/telegram/TimeZoneManager.h | 19 ++++++++++ 2 files changed, 82 insertions(+) diff --git a/td/telegram/TimeZoneManager.cpp b/td/telegram/TimeZoneManager.cpp index c9d2c9301..7df9693fa 100644 --- a/td/telegram/TimeZoneManager.cpp +++ b/td/telegram/TimeZoneManager.cpp @@ -7,11 +7,13 @@ #include "td/telegram/TimeZoneManager.h" #include "td/telegram/Global.h" +#include "td/telegram/logevent/LogEvent.h" #include "td/telegram/Td.h" #include "td/telegram/telegram_api.h" #include "td/utils/algorithm.h" #include "td/utils/buffer.h" +#include "td/utils/tl_helpers.h" namespace td { @@ -60,11 +62,42 @@ bool operator!=(const TimeZoneManager::TimeZone &lhs, const TimeZoneManager::Tim return !(lhs == rhs); } +template +void TimeZoneManager::TimeZone::store(StorerT &storer) const { + BEGIN_STORE_FLAGS(); + END_STORE_FLAGS(); + td::store(id_, storer); + td::store(name_, storer); + td::store(utc_offset_, storer); +} + +template +void TimeZoneManager::TimeZone::parse(ParserT &parser) { + BEGIN_PARSE_FLAGS(); + END_PARSE_FLAGS(); + td::parse(id_, parser); + td::parse(name_, parser); + td::parse(utc_offset_, parser); +} + td_api::object_ptr TimeZoneManager::TimeZoneList::get_time_zones_object() const { return td_api::make_object( transform(time_zones_, [](const TimeZone &time_zone) { return time_zone.get_time_zone_object(); })); } +template +void TimeZoneManager::TimeZoneList::store(StorerT &storer) const { + td::store(time_zones_, storer); + td::store(hash_, storer); +} + +template +void TimeZoneManager::TimeZoneList::parse(ParserT &parser) { + td::parse(time_zones_, parser); + td::parse(hash_, parser); + is_loaded_ = true; +} + TimeZoneManager::TimeZoneManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) { } @@ -75,6 +108,7 @@ void TimeZoneManager::tear_down() { } void TimeZoneManager::get_time_zones(Promise> &&promise) { + load_time_zones(); if (time_zones_.hash_ != 0) { return promise.set_value(time_zones_.get_time_zones_object()); } @@ -82,6 +116,7 @@ void TimeZoneManager::get_time_zones(Promise> &&promise) { + load_time_zones(); get_time_zones_queries_.push_back(std::move(promise)); if (get_time_zones_queries_.size() == 1) { auto query_promise = PromiseCreator::lambda( @@ -112,12 +147,15 @@ void TimeZoneManager::on_get_time_zones( if (time_zones_.time_zones_ != time_zones || time_zones_.hash_ != zone_list->hash_) { time_zones_.time_zones_ = std::move(time_zones); time_zones_.hash_ = zone_list->hash_; + save_time_zones(); } break; } default: UNREACHABLE(); } + time_zones_.is_loaded_ = true; + auto promises = std::move(get_time_zones_queries_); reset_to_empty(get_time_zones_queries_); for (auto &promise : promises) { @@ -127,4 +165,29 @@ void TimeZoneManager::on_get_time_zones( } } +string TimeZoneManager::get_time_zones_database_key() { + return "time_zones"; +} + +void TimeZoneManager::load_time_zones() { + if (time_zones_.is_loaded_) { + return; + } + time_zones_.is_loaded_ = true; + + auto log_event_string = G()->td_db()->get_binlog_pmc()->get(get_time_zones_database_key()); + if (log_event_string.empty()) { + return; + } + auto status = log_event_parse(time_zones_, log_event_string); + if (status.is_error()) { + LOG(ERROR) << "Failed to parse time zones from binlog: " << status; + time_zones_ = TimeZoneList(); + } +} + +void TimeZoneManager::save_time_zones() { + G()->td_db()->get_binlog_pmc()->set(get_time_zones_database_key(), log_event_store(time_zones_).as_slice().str()); +} + } // namespace td diff --git a/td/telegram/TimeZoneManager.h b/td/telegram/TimeZoneManager.h index 65c1c3962..1758543f1 100644 --- a/td/telegram/TimeZoneManager.h +++ b/td/telegram/TimeZoneManager.h @@ -43,13 +43,26 @@ class TimeZoneManager final : public Actor { TimeZone(string &&id, string &&name, int32 utc_offset); td_api::object_ptr get_time_zone_object() const; + + template + void store(StorerT &storer) const; + + template + void parse(ParserT &parser); }; struct TimeZoneList { vector time_zones_; int32 hash_ = 0; + bool is_loaded_ = false; td_api::object_ptr get_time_zones_object() const; + + template + void store(StorerT &storer) const; + + template + void parse(ParserT &parser); }; friend bool operator==(const TimeZone &lhs, const TimeZone &rhs); @@ -58,6 +71,12 @@ class TimeZoneManager final : public Actor { void on_get_time_zones(Result> &&r_time_zones); + static string get_time_zones_database_key(); + + void load_time_zones(); + + void save_time_zones(); + vector>> get_time_zones_queries_; TimeZoneList time_zones_;