Repair file_reference in SaveGifQuery.
GitOrigin-RevId: ae9fcc543795a659c51699af8ea0048a0b5f8fb5
This commit is contained in:
parent
6633b87d51
commit
0ac8c2d389
@ -64,13 +64,22 @@ class GetSavedGifsQuery : public Td::ResultHandler {
|
||||
};
|
||||
|
||||
class SaveGifQuery : public Td::ResultHandler {
|
||||
FileId file_id_;
|
||||
string file_reference_;
|
||||
bool unsave_ = false;
|
||||
|
||||
Promise<Unit> promise_;
|
||||
|
||||
public:
|
||||
explicit SaveGifQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(tl_object_ptr<telegram_api::InputDocument> &&input_document, bool unsave) {
|
||||
void send(FileId file_id, tl_object_ptr<telegram_api::inputDocument> &&input_document, bool unsave) {
|
||||
CHECK(input_document != nullptr);
|
||||
CHECK(file_id.is_valid());
|
||||
file_id_ = file_id;
|
||||
file_reference_ = input_document->file_reference_.as_slice().str();
|
||||
unsave_ = unsave;
|
||||
send_query(G()->net_query_creator().create(
|
||||
create_storer(telegram_api::messages_saveGif(std::move(input_document), unsave))));
|
||||
}
|
||||
@ -82,7 +91,7 @@ class SaveGifQuery : public Td::ResultHandler {
|
||||
}
|
||||
|
||||
bool result = result_ptr.move_as_ok();
|
||||
LOG(INFO) << "Receive result for save gif: " << result;
|
||||
LOG(INFO) << "Receive result for save GIF: " << result;
|
||||
if (!result) {
|
||||
td->animations_manager_->reload_saved_animations(true);
|
||||
}
|
||||
@ -91,7 +100,22 @@ class SaveGifQuery : public Td::ResultHandler {
|
||||
}
|
||||
|
||||
void on_error(uint64 id, Status status) override {
|
||||
LOG(ERROR) << "Receive error for save gif: " << status;
|
||||
if (FileReferenceManager::is_file_reference_error(status)) {
|
||||
td->file_manager_->delete_file_reference(file_id_, file_reference_);
|
||||
td->file_reference_manager_->repair_file_reference(
|
||||
file_id_, PromiseCreator::lambda([animation_id = file_id_, unsave = unsave_,
|
||||
promise = std::move(promise_)](Result<Unit> result) mutable {
|
||||
if (result.is_error()) {
|
||||
return promise.set_error(Status::Error(400, "Failed to find the animation"));
|
||||
}
|
||||
|
||||
send_closure(G()->animations_manager(), &AnimationsManager::send_save_gif_query, animation_id, unsave,
|
||||
std::move(promise));
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(ERROR) << "Receive error for save GIF: " << status;
|
||||
td->animations_manager_->reload_saved_animations(true);
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
@ -310,6 +334,7 @@ tl_object_ptr<telegram_api::InputMedia> AnimationsManager::get_input_media(
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SecretInputMedia AnimationsManager::get_secret_input_media(FileId animation_file_id,
|
||||
tl_object_ptr<telegram_api::InputEncryptedFile> input_file,
|
||||
const string &caption, BufferSlice thumbnail,
|
||||
@ -511,7 +536,7 @@ void AnimationsManager::on_get_saved_animations(
|
||||
for (auto &document_ptr : saved_animations->gifs_) {
|
||||
int32 document_constructor_id = document_ptr->get_id();
|
||||
if (document_constructor_id == telegram_api::documentEmpty::ID) {
|
||||
LOG(ERROR) << "Empty gif document received";
|
||||
LOG(ERROR) << "Empty saved animation document received";
|
||||
continue;
|
||||
}
|
||||
CHECK(document_constructor_id == telegram_api::document::ID);
|
||||
@ -588,11 +613,19 @@ void AnimationsManager::add_saved_animation(const tl_object_ptr<td_api::InputFil
|
||||
add_saved_animation_inner(r_file_id.ok(), std::move(promise));
|
||||
}
|
||||
|
||||
void AnimationsManager::send_save_gif_query(FileId animation_id, bool unsave, Promise<Unit> &&promise) {
|
||||
// TODO invokeAfter and log event
|
||||
auto file_view = td_->file_manager_->get_file_view(animation_id);
|
||||
CHECK(file_view.has_remote_location());
|
||||
CHECK(file_view.remote_location().is_document()) << file_view.remote_location();
|
||||
CHECK(!file_view.remote_location().is_web());
|
||||
td_->create_handler<SaveGifQuery>(std::move(promise))
|
||||
->send(animation_id, file_view.remote_location().as_input_document(), unsave);
|
||||
}
|
||||
|
||||
void AnimationsManager::add_saved_animation_inner(FileId animation_id, Promise<Unit> &&promise) {
|
||||
if (add_saved_animation_impl(animation_id, promise)) {
|
||||
// TODO invokeAfter and log event
|
||||
auto file_view = td_->file_manager_->get_file_view(animation_id);
|
||||
td_->create_handler<SaveGifQuery>(std::move(promise))->send(file_view.remote_location().as_input_document(), false);
|
||||
send_save_gif_query(animation_id, false, std::move(promise));
|
||||
}
|
||||
}
|
||||
|
||||
@ -697,12 +730,7 @@ void AnimationsManager::remove_saved_animation(const tl_object_ptr<td_api::Input
|
||||
return promise.set_error(Status::Error(7, "Animation not found"));
|
||||
}
|
||||
|
||||
// TODO invokeAfter
|
||||
auto file_view = td_->file_manager_->get_file_view(file_id);
|
||||
CHECK(file_view.has_remote_location());
|
||||
CHECK(file_view.remote_location().is_document()) << file_view.remote_location();
|
||||
CHECK(!file_view.remote_location().is_web());
|
||||
td_->create_handler<SaveGifQuery>(std::move(promise))->send(file_view.remote_location().as_input_document(), true);
|
||||
send_save_gif_query(file_id, true, std::move(promise));
|
||||
|
||||
saved_animation_ids_.erase(it);
|
||||
|
||||
@ -716,19 +744,22 @@ td_api::object_ptr<td_api::updateSavedAnimations> AnimationsManager::get_update_
|
||||
|
||||
void AnimationsManager::send_update_saved_animations(bool from_database) {
|
||||
if (are_saved_animations_loaded_) {
|
||||
if (!saved_animations_file_source_id_.is_valid() && !saved_animation_ids_.empty()) {
|
||||
saved_animations_file_source_id_ = td_->file_reference_manager_->create_saved_animations_file_source();
|
||||
}
|
||||
vector<FileId> new_saved_animation_file_ids = saved_animation_ids_;
|
||||
for (auto &animation_id : saved_animation_ids_) {
|
||||
td_->file_manager_->add_file_source(animation_id, saved_animations_file_source_id_);
|
||||
auto thumbnail_file_id = get_animation_thumbnail_file_id(animation_id);
|
||||
if (thumbnail_file_id.is_valid()) {
|
||||
td_->file_manager_->add_file_source(thumbnail_file_id, saved_animations_file_source_id_);
|
||||
new_saved_animation_file_ids.push_back(thumbnail_file_id);
|
||||
}
|
||||
}
|
||||
// there is no much reason to delete source from deleted saved animations,
|
||||
// it will be automatically deleted after unsuccessfull try of file reference repairing
|
||||
// moreover one thumbnail can belong to different animations, so removal should be careful
|
||||
std::sort(new_saved_animation_file_ids.begin(), new_saved_animation_file_ids.end());
|
||||
if (new_saved_animation_file_ids != saved_animation_file_ids_) {
|
||||
if (!saved_animations_file_source_id_.is_valid()) {
|
||||
saved_animations_file_source_id_ = td_->file_reference_manager_->create_saved_animations_file_source();
|
||||
}
|
||||
td_->file_manager_->change_files_source(saved_animations_file_source_id_, saved_animation_file_ids_,
|
||||
new_saved_animation_file_ids);
|
||||
saved_animation_file_ids_ = std::move(new_saved_animation_file_ids);
|
||||
}
|
||||
|
||||
send_closure(G()->td(), &Td::send_update, get_update_saved_animations_object());
|
||||
|
||||
|
@ -68,6 +68,8 @@ class AnimationsManager : public Actor {
|
||||
|
||||
vector<FileId> get_saved_animations(Promise<Unit> &&promise);
|
||||
|
||||
void send_save_gif_query(FileId animation_id, bool unsave, Promise<Unit> &&promise);
|
||||
|
||||
void add_saved_animation(const tl_object_ptr<td_api::InputFile> &input_file, Promise<Unit> &&promise);
|
||||
|
||||
void add_saved_animation_by_id(FileId animation_id);
|
||||
@ -133,6 +135,7 @@ class AnimationsManager : public Actor {
|
||||
|
||||
int32 saved_animations_limit_ = 200;
|
||||
vector<FileId> saved_animation_ids_;
|
||||
vector<FileId> saved_animation_file_ids_;
|
||||
double next_saved_animations_load_time_ = 0;
|
||||
bool are_saved_animations_loaded_ = false;
|
||||
vector<Promise<Unit>> load_saved_animations_queries_;
|
||||
|
@ -128,14 +128,19 @@ void FileReferenceManager::run_node(NodeId node_id) {
|
||||
if (node.query->active_queries != 0) {
|
||||
return;
|
||||
}
|
||||
VLOG(file_references) << "Run file references repair for file " << node_id;
|
||||
VLOG(file_references) << "Trying to repair file reference for file " << node_id;
|
||||
if (node.query->promises.empty()) {
|
||||
node.query = {};
|
||||
return;
|
||||
}
|
||||
if (!node.file_source_ids.has_next()) {
|
||||
VLOG(file_references) << "Have no more file sources to repair file reference for file " << node_id;
|
||||
for (auto &p : node.query->promises) {
|
||||
p.set_value(Unit());
|
||||
if (node.file_source_ids.empty()) {
|
||||
p.set_error(Status::Error(400, "File not found"));
|
||||
} else {
|
||||
p.set_error(Status::Error(429, "Too Many Requests: retry after 1"));
|
||||
}
|
||||
}
|
||||
node.query = {};
|
||||
return;
|
||||
@ -253,7 +258,7 @@ void FileReferenceManager::repair_file_reference(NodeId node_id, Promise<> promi
|
||||
node.query = make_unique<Query>();
|
||||
node.query->generation = ++query_generation_;
|
||||
node.file_source_ids.reset_position();
|
||||
VLOG(file_references) << "new query " << query_generation_;
|
||||
VLOG(file_references) << "Create new file reference repair query with " << query_generation_;
|
||||
}
|
||||
node.query->promises.push_back(std::move(promise));
|
||||
run_node(node_id);
|
||||
|
@ -42,8 +42,11 @@ class FileReferenceManager : public Actor {
|
||||
|
||||
using NodeId = FileId;
|
||||
void repair_file_reference(NodeId node_id, Promise<> promise);
|
||||
|
||||
void add_file_source(NodeId node_id, FileSourceId file_source_id);
|
||||
|
||||
void remove_file_source(NodeId node_id, FileSourceId file_source_id);
|
||||
|
||||
void merge(NodeId to_node_id, NodeId from_node_id);
|
||||
|
||||
private:
|
||||
|
@ -77,6 +77,10 @@ class FastSetWithPosition {
|
||||
return checked_.size() + not_checked_.size();
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<T> checked_;
|
||||
std::set<T> not_checked_;
|
||||
@ -168,6 +172,13 @@ class SetWithPosition {
|
||||
return static_cast<size_t>(has_value_);
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
if (fast_) {
|
||||
return false;
|
||||
}
|
||||
return !has_value_;
|
||||
}
|
||||
|
||||
private:
|
||||
T value_{};
|
||||
bool has_value_{false};
|
||||
|
@ -241,7 +241,7 @@ class SaveRecentStickerQuery : public Td::ResultHandler {
|
||||
explicit SaveRecentStickerQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(bool is_attached, tl_object_ptr<telegram_api::InputDocument> &&input_document, bool unsave) {
|
||||
void send(bool is_attached, tl_object_ptr<telegram_api::inputDocument> &&input_document, bool unsave) {
|
||||
is_attached_ = is_attached;
|
||||
|
||||
int32 flags = 0;
|
||||
@ -347,7 +347,7 @@ class FaveStickerQuery : public Td::ResultHandler {
|
||||
explicit FaveStickerQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(tl_object_ptr<telegram_api::InputDocument> &&input_document, bool unsave) {
|
||||
void send(tl_object_ptr<telegram_api::inputDocument> &&input_document, bool unsave) {
|
||||
send_query(G()->net_query_creator().create(
|
||||
create_storer(telegram_api::messages_faveSticker(std::move(input_document), unsave))));
|
||||
}
|
||||
@ -666,7 +666,7 @@ class SetStickerPositionQuery : public Td::ResultHandler {
|
||||
explicit SetStickerPositionQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(tl_object_ptr<telegram_api::InputDocument> &&input_document, int32 position) {
|
||||
void send(tl_object_ptr<telegram_api::inputDocument> &&input_document, int32 position) {
|
||||
send_query(G()->net_query_creator().create(
|
||||
create_storer(telegram_api::stickers_changeStickerPosition(std::move(input_document), position))));
|
||||
}
|
||||
@ -695,7 +695,7 @@ class DeleteStickerFromSetQuery : public Td::ResultHandler {
|
||||
explicit DeleteStickerFromSetQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(tl_object_ptr<telegram_api::InputDocument> &&input_document) {
|
||||
void send(tl_object_ptr<telegram_api::inputDocument> &&input_document) {
|
||||
send_query(G()->net_query_creator().create(
|
||||
create_storer(telegram_api::stickers_removeStickerFromSet(std::move(input_document)))));
|
||||
}
|
||||
|
@ -480,7 +480,7 @@ class FullRemoteFileLocation {
|
||||
}
|
||||
|
||||
#define as_input_document() as_input_document_impl(__FILE__, __LINE__)
|
||||
tl_object_ptr<telegram_api::InputDocument> as_input_document_impl(const char *file, int line) const {
|
||||
tl_object_ptr<telegram_api::inputDocument> as_input_document_impl(const char *file, int line) const {
|
||||
CHECK(is_common()) << file << ' ' << line;
|
||||
CHECK(is_document()) << file << ' ' << line;
|
||||
return make_tl_object<telegram_api::inputDocument>(common().id_, common().access_hash_,
|
||||
@ -488,18 +488,18 @@ class FullRemoteFileLocation {
|
||||
}
|
||||
|
||||
#define as_input_photo() as_input_photo_impl(__FILE__, __LINE__)
|
||||
tl_object_ptr<telegram_api::InputPhoto> as_input_photo_impl(const char *file, int line) const {
|
||||
tl_object_ptr<telegram_api::inputPhoto> as_input_photo_impl(const char *file, int line) const {
|
||||
CHECK(is_photo()) << file << ' ' << line;
|
||||
return make_tl_object<telegram_api::inputPhoto>(photo().id_, photo().access_hash_, BufferSlice(file_reference_));
|
||||
}
|
||||
|
||||
tl_object_ptr<telegram_api::InputEncryptedFile> as_input_encrypted_file() const {
|
||||
tl_object_ptr<telegram_api::inputEncryptedFile> as_input_encrypted_file() const {
|
||||
CHECK(is_encrypted_secret());
|
||||
return make_tl_object<telegram_api::inputEncryptedFile>(common().id_, common().access_hash_);
|
||||
}
|
||||
|
||||
#define as_input_secure_file() as_input_secure_file_impl(__FILE__, __LINE__)
|
||||
tl_object_ptr<telegram_api::InputSecureFile> as_input_secure_file_impl(const char *file, int line) const {
|
||||
tl_object_ptr<telegram_api::inputSecureFile> as_input_secure_file_impl(const char *file, int line) const {
|
||||
CHECK(is_secure()) << file << ' ' << line;
|
||||
return make_tl_object<telegram_api::inputSecureFile>(common().id_, common().access_hash_);
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ void FileNode::set_remote_location(const RemoteFileLocation &remote, FileLocatio
|
||||
|
||||
void FileNode::delete_file_reference(Slice file_reference) {
|
||||
if (remote_.type() == RemoteFileLocation::Type::Full && remote_.full().delete_file_reference(file_reference)) {
|
||||
VLOG(file_references) << "Delete file reference of file " << main_file_id_;
|
||||
VLOG(file_references) << "Do delete file reference of main file " << main_file_id_;
|
||||
upload_was_update_file_reference_ = false;
|
||||
download_was_update_file_reference_ = false;
|
||||
on_pmc_changed();
|
||||
@ -1915,7 +1915,7 @@ bool FileManager::delete_partial_remote_location(FileId file_id) {
|
||||
|
||||
void FileManager::delete_file_reference(FileId file_id, string file_reference) {
|
||||
VLOG(file_references) << "Delete file reference of file " << file_id << " "
|
||||
<< tag("reference", base64_encode(file_reference));
|
||||
<< tag("reference_base64", base64_encode(file_reference));
|
||||
auto node = get_sync_file_node(file_id);
|
||||
if (!node) {
|
||||
LOG(ERROR) << "Wrong file id " << file_id;
|
||||
|
Reference in New Issue
Block a user