Move RequestActor to RequestActor.h.

GitOrigin-RevId: 50b21b9832f0a9871f6c2fc54ab45818b04258b8
This commit is contained in:
levlam 2018-10-01 02:26:06 +03:00
parent ad81123d60
commit 4ab14b620a
3 changed files with 153 additions and 129 deletions

View File

@ -534,6 +534,7 @@ set(TDLIB_SOURCE
td/telegram/PrivacyManager.h
td/telegram/PtsManager.h
td/telegram/ReplyMarkup.h
td/telegram/RequestActor.h
td/telegram/SecretChatActor.h
td/telegram/SecretChatId.h
td/telegram/SecretChatDb.h

151
td/telegram/RequestActor.h Normal file
View File

@ -0,0 +1,151 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/actor/actor.h"
#include "td/actor/PromiseFuture.h"
#include "td/utils/common.h"
#include "td/utils/logging.h"
#include "td/utils/Status.h"
#include <type_traits>
namespace td {
class Td;
template <class T = Unit>
class RequestActor : public Actor {
public:
RequestActor(ActorShared<Td> td_id, uint64 request_id)
: td_id_(std::move(td_id)), td(td_id_.get().get_actor_unsafe()), request_id_(request_id) {
}
void loop() override {
PromiseActor<T> promise;
FutureActor<T> future;
init_promise_future(&promise, &future);
do_run(PromiseCreator::from_promise_actor(std::move(promise)));
if (future.is_ready()) {
if (future.is_error()) {
do_send_error(future.move_as_error());
} else {
do_set_result(future.move_as_ok());
do_send_result();
}
stop();
} else {
if (--tries_left_ == 0) {
future.close();
do_send_error(Status::Error(400, "Requested data is unaccessible"));
return stop();
}
future.set_event(EventCreator::raw(actor_id(), nullptr));
future_ = std::move(future);
}
}
void raw_event(const Event::Raw &event) override {
if (future_.is_error()) {
auto error = future_.move_as_error();
if (error == Status::Error<FutureActor<T>::Hangup>()) {
// dropping query due to lost authorization or lost promise
// td may be already closed, so we should check is auth_manager_ is empty
bool is_authorized = td->auth_manager_ && td->auth_manager_->is_authorized();
if (is_authorized) {
LOG(ERROR) << "Promise was lost";
do_send_error(Status::Error(500, "Query can't be answered due to bug in the TDLib"));
} else {
do_send_error(Status::Error(401, "Unauthorized"));
}
return stop();
}
do_send_error(std::move(error));
stop();
} else {
do_set_result(future_.move_as_ok());
loop();
}
}
void on_start_migrate(int32 /*sched_id*/) override {
UNREACHABLE();
}
void on_finish_migrate() override {
UNREACHABLE();
}
int get_tries() const {
return tries_left_;
}
void set_tries(int32 tries) {
tries_left_ = tries;
}
protected:
ActorShared<Td> td_id_;
Td *td;
void send_result(tl_object_ptr<td_api::Object> &&result) {
send_closure(td_id_, &Td::send_result, request_id_, std::move(result));
}
void send_error(Status &&status) {
LOG(INFO) << "Receive error for query: " << status;
send_closure(td_id_, &Td::send_error, request_id_, std::move(status));
}
private:
virtual void do_run(Promise<T> &&promise) = 0;
virtual void do_send_result() {
send_result(make_tl_object<td_api::ok>());
}
virtual void do_send_error(Status &&status) {
send_error(std::move(status));
}
virtual void do_set_result(T &&result) {
CHECK((std::is_same<T, Unit>::value)); // all other results should be implicitly handled by overriding this method
}
void hangup() override {
do_send_error(Status::Error(500, "Request aborted"));
stop();
}
friend class RequestOnceActor;
uint64 request_id_;
int tries_left_ = 2;
FutureActor<T> future_;
};
class RequestOnceActor : public RequestActor<> {
public:
RequestOnceActor(ActorShared<Td> td_id, uint64 request_id) : RequestActor(std::move(td_id), request_id) {
}
void loop() override {
if (get_tries() < 2) {
do_send_result();
stop();
return;
}
RequestActor::loop();
}
};
} // namespace td

View File

@ -48,6 +48,7 @@
#include "td/telegram/Payments.h"
#include "td/telegram/Photo.h"
#include "td/telegram/PrivacyManager.h"
#include "td/telegram/RequestActor.h"
#include "td/telegram/SecretChatId.h"
#include "td/telegram/SecretChatsManager.h"
#include "td/telegram/SecureManager.h"
@ -505,135 +506,6 @@ class GetDeepLinkInfoQuery : public Td::ResultHandler {
}
};
template <class T = Unit>
class RequestActor : public Actor {
public:
RequestActor(ActorShared<Td> td_id, uint64 request_id)
: td_id_(std::move(td_id)), td(td_id_.get().get_actor_unsafe()), request_id_(request_id) {
}
void loop() override {
PromiseActor<T> promise;
FutureActor<T> future;
init_promise_future(&promise, &future);
do_run(PromiseCreator::from_promise_actor(std::move(promise)));
if (future.is_ready()) {
if (future.is_error()) {
do_send_error(future.move_as_error());
} else {
do_set_result(future.move_as_ok());
do_send_result();
}
stop();
} else {
if (--tries_left_ == 0) {
future.close();
do_send_error(Status::Error(400, "Requested data is unaccessible"));
return stop();
}
future.set_event(EventCreator::raw(actor_id(), nullptr));
future_ = std::move(future);
}
}
void raw_event(const Event::Raw &event) override {
if (future_.is_error()) {
auto error = future_.move_as_error();
if (error == Status::Error<FutureActor<T>::Hangup>()) {
// dropping query due to lost authorization or lost promise
// td may be already closed, so we should check is auth_manager_ is empty
bool is_authorized = td->auth_manager_ && td->auth_manager_->is_authorized();
if (is_authorized) {
LOG(ERROR) << "Promise was lost";
do_send_error(Status::Error(500, "Query can't be answered due to bug in the TDLib"));
} else {
do_send_error(Status::Error(401, "Unauthorized"));
}
return stop();
}
do_send_error(std::move(error));
stop();
} else {
do_set_result(future_.move_as_ok());
loop();
}
}
void on_start_migrate(int32 /*sched_id*/) override {
UNREACHABLE();
}
void on_finish_migrate() override {
UNREACHABLE();
}
int get_tries() const {
return tries_left_;
}
void set_tries(int32 tries) {
tries_left_ = tries;
}
protected:
ActorShared<Td> td_id_;
Td *td;
void send_result(tl_object_ptr<td_api::Object> &&result) {
send_closure(td_id_, &Td::send_result, request_id_, std::move(result));
}
void send_error(Status &&status) {
LOG(INFO) << "Receive error for query: " << status;
send_closure(td_id_, &Td::send_error, request_id_, std::move(status));
}
private:
virtual void do_run(Promise<T> &&promise) = 0;
virtual void do_send_result() {
send_result(make_tl_object<td_api::ok>());
}
virtual void do_send_error(Status &&status) {
send_error(std::move(status));
}
virtual void do_set_result(T &&result) {
CHECK((std::is_same<T, Unit>::value)); // all other results should be implicitly handled by overriding this method
}
void hangup() override {
do_send_error(Status::Error(500, "Request aborted"));
stop();
}
friend class RequestOnceActor;
uint64 request_id_;
int tries_left_ = 2;
FutureActor<T> future_;
};
class RequestOnceActor : public RequestActor<> {
public:
RequestOnceActor(ActorShared<Td> td_id, uint64 request_id) : RequestActor(std::move(td_id), request_id) {
}
void loop() override {
if (get_tries() < 2) {
do_send_result();
stop();
return;
}
RequestActor::loop();
}
};
/*** Td ***/
/** Td queries **/
class TestQuery : public Td::ResultHandler {