Merge pull request #84 from a5r0n/official-upstream-update

Official upstream update
This commit is contained in:
Andrea Cavalli 2023-12-17 19:49:10 +01:00 committed by GitHub
commit 8990b79e9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 942 additions and 774 deletions

View File

@ -6,7 +6,7 @@ if (POLICY CMP0065)
cmake_policy(SET CMP0065 NEW)
endif()
project(TelegramBotApi VERSION 6.7.1 LANGUAGES CXX)
project(TelegramBotApi VERSION 6.9.2 LANGUAGES CXX)
if (POLICY CMP0069)
option(TELEGRAM_BOT_API_ENABLE_LTO "Use \"ON\" to enable Link Time Optimization.")

2
td

@ -1 +1 @@
Subproject commit 328b8649d859c5ed4088a875cbb059db6029dc0d
Subproject commit 9184b3e62de59663a59d3500528aee7e5f0d83fa

File diff suppressed because it is too large Load Diff

View File

@ -277,6 +277,7 @@ class Client final : public WebhookActor::Callback {
struct UserInfo;
struct ChatInfo;
struct BotCommandScope;
struct BotUserIds;
enum class AccessRights { Read, ReadMembers, Edit, Write };
@ -375,13 +376,16 @@ class Client final : public WebhookActor::Callback {
static bool to_bool(td::MutableSlice value);
static object_ptr<td_api::InputMessageReplyTo> get_input_message_reply_to(int64 reply_to_message_id);
static td::Result<object_ptr<td_api::keyboardButton>> get_keyboard_button(td::JsonValue &button);
td::Result<object_ptr<td_api::inlineKeyboardButton>> get_inline_keyboard_button(td::JsonValue &button);
static td::Result<object_ptr<td_api::inlineKeyboardButton>> get_inline_keyboard_button(td::JsonValue &button,
BotUserIds &bot_user_ids);
td::Result<object_ptr<td_api::ReplyMarkup>> get_reply_markup(const Query *query);
static td::Result<object_ptr<td_api::ReplyMarkup>> get_reply_markup(const Query *query, BotUserIds &bot_user_ids);
td::Result<object_ptr<td_api::ReplyMarkup>> get_reply_markup(td::JsonValue &&value);
static td::Result<object_ptr<td_api::ReplyMarkup>> get_reply_markup(td::JsonValue &&value, BotUserIds &bot_user_ids);
static td::Result<object_ptr<td_api::labeledPricePart>> get_labeled_price_part(td::JsonValue &value);
@ -415,13 +419,17 @@ class Client final : public WebhookActor::Callback {
static td::Result<td_api::object_ptr<td_api::inlineQueryResultsButton>> get_inline_query_results_button(
td::MutableSlice value);
td::Result<object_ptr<td_api::InputInlineQueryResult>> get_inline_query_result(const Query *query);
static td::Result<object_ptr<td_api::InputInlineQueryResult>> get_inline_query_result(const Query *query,
BotUserIds &bot_user_ids);
td::Result<object_ptr<td_api::InputInlineQueryResult>> get_inline_query_result(td::JsonValue &&value);
static td::Result<object_ptr<td_api::InputInlineQueryResult>> get_inline_query_result(td::JsonValue &&value,
BotUserIds &bot_user_ids);
td::Result<td::vector<object_ptr<td_api::InputInlineQueryResult>>> get_inline_query_results(const Query *query);
static td::Result<td::vector<object_ptr<td_api::InputInlineQueryResult>>> get_inline_query_results(
const Query *query, BotUserIds &bot_user_ids);
td::Result<td::vector<object_ptr<td_api::InputInlineQueryResult>>> get_inline_query_results(td::JsonValue &&value);
static td::Result<td::vector<object_ptr<td_api::InputInlineQueryResult>>> get_inline_query_results(
td::JsonValue &&value, BotUserIds &bot_user_ids);
struct BotCommandScope {
object_ptr<td_api::BotCommandScope> scope_;
@ -540,7 +548,7 @@ class Client final : public WebhookActor::Callback {
void decrease_yet_unsent_message_count(int64 chat_id, int32 count);
int64 extract_yet_unsent_message_query_id(int64 chat_id, int64 message_id, bool *is_reply_to_message_deleted);
int64 extract_yet_unsent_message_query_id(int64 chat_id, int64 message_id);
// start custom helper methods
@ -552,7 +560,7 @@ class Client final : public WebhookActor::Callback {
static int64 get_int64_arg(const Query *query, td::Slice field_name, int64 default_value,
int64 min_value = std::numeric_limits<int64>::min(),
int64 max_value = std::numeric_limits<int64>::max());
static td::Result<td_api::object_ptr<td_api::ChatReportReason>> get_report_reason(const Query *query,
static td::Result<td_api::object_ptr<td_api::ReportReason>> get_report_reason(const Query *query,
td::Slice field_name = td::Slice("reason"));
static td::Result<td_api::object_ptr<td_api::SearchMessagesFilter>> get_search_messages_filter(
@ -561,13 +569,15 @@ class Client final : public WebhookActor::Callback {
// end custom helper methods
void on_message_send_succeeded(object_ptr<td_api::message> &&message, int64 old_message_id);
void on_message_send_failed(int64 chat_id, int64 old_message_id, int64 new_message_id, td::Status result);
void on_message_send_failed(int64 chat_id, int64 old_message_id, int64 new_message_id,
object_ptr<td_api::error> &&error);
static bool init_methods();
static bool is_local_method(td::Slice method);
void on_cmd(PromisedQueryPtr query);
void on_cmd(PromisedQueryPtr query, bool force = false);
td::Status process_get_me_query(PromisedQueryPtr &query);
td::Status process_get_my_commands_query(PromisedQueryPtr &query);
@ -646,6 +656,7 @@ class Client final : public WebhookActor::Callback {
td::Status process_reopen_general_forum_topic_query(PromisedQueryPtr &query);
td::Status process_hide_general_forum_topic_query(PromisedQueryPtr &query);
td::Status process_unhide_general_forum_topic_query(PromisedQueryPtr &query);
td::Status process_unpin_all_general_forum_topic_messages_query(PromisedQueryPtr &query);
td::Status process_get_chat_member_query(PromisedQueryPtr &query);
td::Status process_get_chat_administrators_query(PromisedQueryPtr &query);
td::Status process_get_chat_member_count_query(PromisedQueryPtr &query);
@ -735,7 +746,10 @@ class Client final : public WebhookActor::Callback {
void on_webhook_closed(td::Status status);
void do_send_message(object_ptr<td_api::InputMessageContent> input_message_content, PromisedQueryPtr query);
void delete_last_send_message_time(td::int64 file_size, double max_delay);
void do_send_message(object_ptr<td_api::InputMessageContent> input_message_content, PromisedQueryPtr query,
bool force = false);
int64 get_send_message_query_id(PromisedQueryPtr query, bool is_multisend);
@ -800,6 +814,7 @@ class Client final : public WebhookActor::Callback {
td::string editable_username;
td::string language_code;
int64 emoji_status_custom_emoji_id;
int32 emoji_status_expiration_date;
object_ptr<td_api::chatPhoto> photo;
td::string bio;
@ -842,7 +857,7 @@ class Client final : public WebhookActor::Callback {
};
static void add_group(GroupInfo *group_info, object_ptr<td_api::basicGroup> &&group);
void set_group_photo(int64 group_id, object_ptr<td_api::chatPhoto> &&photo);
void set_group_description(int64 group_id, td::string &&descripton);
void set_group_description(int64 group_id, td::string &&description);
void set_group_invite_link(int64 group_id, td::string &&invite_link);
GroupInfo *add_group_info(int64 group_id);
const GroupInfo *get_group_info(int64 group_id) const;
@ -875,7 +890,7 @@ class Client final : public WebhookActor::Callback {
};
static void add_supergroup(SupergroupInfo *supergroup_info, object_ptr<td_api::supergroup> &&supergroup);
void set_supergroup_photo(int64 supergroup_id, object_ptr<td_api::chatPhoto> &&photo);
void set_supergroup_description(int64 supergroup_id, td::string &&descripton);
void set_supergroup_description(int64 supergroup_id, td::string &&description);
void set_supergroup_invite_link(int64 supergroup_id, td::string &&invite_link);
void set_supergroup_sticker_set_id(int64 supergroup_id, int64 sticker_set_id);
void set_supergroup_can_set_sticker_set(int64 supergroup_id, bool can_set_sticker_set);
@ -926,7 +941,7 @@ class Client final : public WebhookActor::Callback {
td::string initial_author_signature;
td::string initial_sender_name;
td::string author_signature;
int64 reply_to_message_id = 0;
object_ptr<td_api::messageReplyToMessage> reply_to_message;
int64 media_album_id = 0;
int64 via_bot_user_id = 0;
object_ptr<td_api::MessageContent> content;
@ -943,13 +958,18 @@ class Client final : public WebhookActor::Callback {
bool can_be_saved = false;
bool is_automatic_forward = false;
bool is_topic_message = false;
mutable bool is_reply_to_message_deleted = false;
mutable bool is_content_changed = false;
};
static int64 &get_reply_to_message_id(object_ptr<td_api::message> &message);
static int64 get_same_chat_reply_to_message_id(const td_api::messageReplyToMessage *reply_to,
int64 message_thread_id);
void set_message_reply_to_message_id(MessageInfo *message_info, int64 reply_to_message_id);
static int64 get_same_chat_reply_to_message_id(const object_ptr<td_api::MessageReplyTo> &reply_to,
int64 message_thread_id);
static int64 get_same_chat_reply_to_message_id(const object_ptr<td_api::message> &message);
static void drop_internal_reply_to_message_in_another_chat(object_ptr<td_api::message> &message);
static td::Slice get_sticker_type(const object_ptr<td_api::StickerType> &type);
@ -1155,17 +1175,10 @@ class Client final : public WebhookActor::Callback {
td::WaitFreeHashMap<int64, td::unique_ptr<SupergroupInfo>> supergroups_;
td::WaitFreeHashMap<int64, td::unique_ptr<ChatInfo>> chats_;
td::FlatHashMap<FullMessageId, td::FlatHashSet<int64>, FullMessageIdHash>
reply_message_ids_; // message -> replies to it
td::FlatHashMap<FullMessageId, td::FlatHashSet<int64>, FullMessageIdHash>
yet_unsent_reply_message_ids_; // message -> replies to it
td::FlatHashMap<int32, td::vector<PromisedQueryPtr>> file_download_listeners_;
td::FlatHashSet<int32> download_started_file_ids_;
struct YetUnsentMessage {
int64 reply_to_message_id = 0;
bool is_reply_to_message_deleted = false;
int64 send_message_query_id = 0;
};
td::FlatHashMap<FullMessageId, YetUnsentMessage, FullMessageIdHash> yet_unsent_messages_;
@ -1206,11 +1219,15 @@ class Client final : public WebhookActor::Callback {
td::WaitFreeHashMap<int64, td::string> sticker_set_names_;
int64 cur_temp_bot_user_id_ = 1;
td::FlatHashMap<td::string, int64> bot_user_ids_;
td::FlatHashSet<td::string> unresolved_bot_usernames_;
td::FlatHashMap<int64, int64> temp_to_real_bot_user_id_;
td::FlatHashMap<td::string, td::vector<int64>> awaiting_bot_resolve_queries_;
td::WaitFreeHashMap<int64, double> last_send_message_time_;
struct BotUserIds {
int64 default_bot_user_id_ = 0;
int64 cur_temp_bot_user_id_ = 1;
td::FlatHashMap<td::string, int64> bot_user_ids_;
td::FlatHashSet<td::string> unresolved_bot_usernames_;
};
BotUserIds bot_user_ids_;
struct PendingBotResolveQuery {
std::size_t pending_resolve_count = 0;
@ -1220,6 +1237,9 @@ class Client final : public WebhookActor::Callback {
td::FlatHashMap<int64, PendingBotResolveQuery> pending_bot_resolve_queries_;
int64 current_bot_resolve_query_id_ = 1;
td::FlatHashMap<td::string, td::vector<int64>> awaiting_bot_resolve_queries_;
td::FlatHashMap<int64, int64> temp_to_real_bot_user_id_;
td::string dir_;
td::ActorOwn<td::ClientActor> td_client_;
td::ActorContext context_;
@ -1273,6 +1293,8 @@ class Client final : public WebhookActor::Callback {
double previous_get_updates_finish_time_ = 0;
double next_get_updates_conflict_time_ = 0;
int32 log_in_date_ = 0;
int32 flood_limited_query_count_ = 0;
double next_flood_limit_warning_time_ = 0;

View File

@ -296,7 +296,7 @@ void ClientManager::get_stats(td::Promise<td::BufferSlice> promise,
auto top_clients = get_top_clients(50, id_filter);
if(!as_json) {
sb << stat_.get_description() << '\n';
sb << BotStatActor::get_description() << '\n';
}
if (id_filter.empty()) {
if(as_json) {
@ -448,9 +448,6 @@ td::int64 ClientManager::get_tqueue_id(td::int64 user_id, bool is_test_dc) {
}
void ClientManager::start_up() {
//NB: the same scheduler as for database in Td
auto scheduler_id = 1;
// init tqueue
{
auto load_start_time = td::Time::now();
@ -478,7 +475,8 @@ void ClientManager::start_up() {
}
}
auto concurrent_binlog = std::make_shared<td::ConcurrentBinlog>(std::move(binlog), scheduler_id);
auto concurrent_binlog =
std::make_shared<td::ConcurrentBinlog>(std::move(binlog), SharedData::get_binlog_scheduler_id());
auto concurrent_tqueue_binlog = td::make_unique<td::TQueueBinlog<td::BinlogInterface>>();
concurrent_tqueue_binlog->set_binlog(std::move(concurrent_binlog));
tqueue->set_callback(std::move(concurrent_tqueue_binlog));
@ -493,18 +491,18 @@ void ClientManager::start_up() {
// init webhook_db and user_db
auto concurrent_webhook_db = td::make_unique<td::BinlogKeyValue<td::ConcurrentBinlog>>();
auto status = concurrent_webhook_db->init(parameters_->working_directory_ + "webhooks_db.binlog", td::DbKey::empty(),
scheduler_id);
SharedData::get_binlog_scheduler_id());
LOG_IF(FATAL, status.is_error()) << "Can't open webhooks_db.binlog " << status;
parameters_->shared_data_->webhook_db_ = std::move(concurrent_webhook_db);
auto concurrent_user_db = td::make_unique<td::BinlogKeyValue<td::ConcurrentBinlog>>();
status = concurrent_user_db->init(parameters_->working_directory_ + "user_db.binlog", td::DbKey::empty(), scheduler_id);
status = concurrent_user_db->init(parameters_->working_directory_ + "user_db.binlog", td::DbKey::empty(), SharedData::get_binlog_scheduler_id());
LOG_IF(FATAL, status.is_error()) << "Can't open user_db.binlog " << status.error();
parameters_->shared_data_->user_db_ = std::move(concurrent_user_db);
auto &webhook_db = *parameters_->shared_data_->webhook_db_;
auto &user_db = *parameters_->shared_data_->user_db_;
for (auto key_value : webhook_db.get_all()) {
for (const auto &key_value : webhook_db.get_all()) {
if (!token_range_(td::to_integer<td::uint64>(key_value.first))) {
LOG(WARNING) << "DROP WEBHOOK: " << key_value.first << " ---> " << key_value.second;
webhook_db.erase(key_value.first);
@ -516,8 +514,8 @@ void ClientManager::start_up() {
}
// launch watchdog
watchdog_id_ = td::create_actor_on_scheduler<Watchdog>(
"ManagerWatchdog", td::Scheduler::instance()->sched_count() - 3, td::this_thread::get_id(), WATCHDOG_TIMEOUT);
watchdog_id_ = td::create_actor_on_scheduler<Watchdog>("ManagerWatchdog", SharedData::get_watchdog_scheduler_id(),
td::this_thread::get_id(), WATCHDOG_TIMEOUT);
set_timeout_in(600.0);
}
@ -684,7 +682,7 @@ void ClientManager::raw_event(const td::Event::Raw &event) {
void ClientManager::timeout_expired() {
send_closure(watchdog_id_, &Watchdog::kick);
set_timeout_in(WATCHDOG_TIMEOUT / 2);
set_timeout_in(WATCHDOG_TIMEOUT / 10);
double now = td::Time::now();
if (now > next_tqueue_gc_time_) {

View File

@ -54,15 +54,54 @@ struct SharedData {
return static_cast<td::int32>(result);
}
static td::int32 get_database_scheduler_id() {
// the same scheduler as for database in Td
return 1;
}
static td::int32 get_file_gc_scheduler_id() {
// the same scheduler as for file GC in Td
return 2;
}
static td::int32 get_client_scheduler_id() {
// the thread for ClientManager and all Clients
return 4;
}
static td::int32 get_watchdog_scheduler_id() {
// the thread for watchdogs
return 5;
}
static td::int32 get_slow_incoming_http_scheduler_id() {
// the thread for slow incoming HTTP connections
return 6;
}
static td::int32 get_slow_outgoing_http_scheduler_id() {
// the thread for slow outgoing HTTP connections
return 7;
}
static td::int32 get_dns_resolver_scheduler_id() {
// the thread for DNS resolving
return 8;
}
static td::int32 get_binlog_scheduler_id() {
// the thread for TQueue and webhook binlogs
return 9;
}
static td::int32 get_webhook_certificate_scheduler_id() {
// the thread for webhook certificate processing
return 10;
}
static td::int32 get_statistics_thread_id() {
// the thread for CPU usage updating
return 11;
}
static td::int32 get_thread_count() {
return 12;
}
};
struct ClientParameters {

View File

@ -6,6 +6,8 @@
//
#pragma once
#include "telegram-bot-api/ClientParameters.h"
#include "td/net/HttpInboundConnection.h"
#include "td/net/TcpListener.h"
@ -61,13 +63,8 @@ class HttpServer final : public td::TcpListener::Callback {
}
void accept(td::SocketFd fd) final {
auto scheduler_count = td::Scheduler::instance()->sched_count();
auto scheduler_id = scheduler_count - 1;
if (scheduler_id > 0) {
scheduler_id--;
}
td::create_actor<td::HttpInboundConnection>("HttpInboundConnection", td::BufferedFd<td::SocketFd>(std::move(fd)), 0,
50, 500, creator_(), scheduler_id)
50, 500, creator_(), SharedData::get_slow_incoming_http_scheduler_id())
.release();
}

View File

@ -44,7 +44,7 @@ Query::Query(td::vector<td::BufferSlice> &&container, td::Slice token, bool is_u
}
td::to_lower_inplace(method_);
start_timestamp_ = td::Time::now();
LOG(INFO) << "QUERY: create " << td::tag("ptr", this) << *this;
LOG(INFO) << "Query " << this << ": " << *this;
if (shared_data_) {
shared_data_->query_count_.fetch_add(1, std::memory_order_relaxed);
if (method_ != "getupdates") {
@ -86,7 +86,7 @@ void Query::set_stat_actor(td::ActorId<BotStatActor> stat_actor) {
void Query::set_ok(td::BufferSlice result) {
CHECK(state_ == State::Query);
LOG(INFO) << "QUERY: got ok " << td::tag("ptr", this) << td::tag("text", result.as_slice());
LOG(INFO) << "Query " << this << ": " << td::tag("method", method_) << td::tag("text", result.as_slice());
answer_ = std::move(result);
state_ = State::OK;
http_status_code_ = 200;
@ -94,7 +94,7 @@ void Query::set_ok(td::BufferSlice result) {
}
void Query::set_error(int http_status_code, td::BufferSlice result) {
LOG(INFO) << "QUERY: got error " << td::tag("ptr", this) << td::tag("code", http_status_code)
LOG(INFO) << "Query " << this << ": " << td::tag("method", method_) << td::tag("code", http_status_code)
<< td::tag("text", result.as_slice());
CHECK(state_ == State::Query);
answer_ = std::move(result);
@ -116,9 +116,25 @@ td::StringBuilder &operator<<(td::StringBuilder &sb, const Query &query) {
auto padded_time =
td::lpad(PSTRING() << td::format::as_time(td::Time::now_cached() - query.start_timestamp()), 10, ' ');
sb << "[bot" << td::rpad(query.token().str(), 46, ' ') << "][time:" << padded_time << ']'
<< td::tag("method", td::lpad(query.method().str(), 20, ' '));
<< td::tag("method", td::lpad(query.method().str(), 25, ' '));
if (!query.args().empty()) {
sb << td::oneline(PSLICE() << query.args());
sb << '{';
for (const auto &arg : query.args()) {
sb << '[';
if (arg.first.size() > 128) {
sb << '<' << arg.first.size() << '>' << td::oneline(arg.first.substr(0, 128)) << "...";
} else {
sb << td::oneline(arg.first);
}
sb << ':';
if (arg.second.size() > 4096) {
sb << '<' << arg.second.size() << '>' << td::oneline(arg.second.substr(0, 4096)) << "...";
} else {
sb << td::oneline(arg.second);
}
sb << ']';
}
sb << '}';
}
if (!query.files().empty()) {
sb << query.files();

View File

@ -38,41 +38,52 @@ class Query final : public td::ListNode {
td::Slice token() const {
return token_;
}
bool is_user() const {
return is_user_;
}
bool is_test_dc() const {
return is_test_dc_;
}
td::Slice method() const {
return method_;
}
bool has_arg(td::Slice key) const {
auto it = std::find_if(args_.begin(), args_.end(),
[&key](const std::pair<td::MutableSlice, td::MutableSlice> &s) { return s.first == key; });
return it != args_.end();
}
td::MutableSlice arg(td::Slice key) const {
auto it = std::find_if(args_.begin(), args_.end(),
[&key](const std::pair<td::MutableSlice, td::MutableSlice> &s) { return s.first == key; });
return it == args_.end() ? td::MutableSlice() : it->second;
}
const td::vector<std::pair<td::MutableSlice, td::MutableSlice>> &args() const {
return args_;
}
td::Slice get_header(td::Slice key) const {
auto it = std::find_if(headers_.begin(), headers_.end(),
[&key](const std::pair<td::MutableSlice, td::MutableSlice> &s) { return s.first == key; });
return it == headers_.end() ? td::Slice() : it->second;
}
const td::HttpFile *file(td::Slice key) const {
auto it = std::find_if(files_.begin(), files_.end(), [&key](const td::HttpFile &f) { return f.field_name == key; });
return it == files_.end() ? nullptr : &*it;
}
const td::vector<td::HttpFile> &files() const {
return files_;
}
td::int64 files_size() const;
td::string get_peer_ip_address() const;
td::BufferSlice &answer() {
@ -156,8 +167,6 @@ class Query final : public td::ListNode {
td::int64 query_size() const;
td::int64 files_size() const;
td::int64 files_max_size() const;
void send_request_stat() const;

View File

@ -7,6 +7,7 @@
#include "telegram-bot-api/Stats.h"
#include "td/utils/common.h"
#include "td/utils/logging.h"
#include "td/utils/port/thread.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/StringBuilder.h"
@ -19,17 +20,24 @@ ServerCpuStat::ServerCpuStat() {
}
}
void ServerCpuStat::add_event(const td::CpuStat &cpu_stat, double now) {
std::lock_guard<std::mutex> guard(mutex_);
for (auto &stat : stat_) {
stat.add_event(cpu_stat, now);
void ServerCpuStat::update(double now) {
auto r_cpu_stat = td::cpu_stat();
if (r_cpu_stat.is_error()) {
return;
}
auto &cpu_stat = instance();
std::lock_guard<std::mutex> guard(cpu_stat.mutex_);
for (auto &stat : cpu_stat.stat_) {
stat.add_event(r_cpu_stat.ok(), now);
}
LOG(WARNING) << "CPU usage: " << cpu_stat.stat_[1].get_stat(now).as_vector()[0].value_;
}
td::string ServerCpuStat::get_description() const {
td::string ServerCpuStat::get_description() {
td::string res = "DURATION";
for (auto &descr : DESCR) {
res += "\t";
res += '\t';
res += descr;
}
return res;
@ -37,7 +45,7 @@ td::string ServerCpuStat::get_description() const {
static td::string to_percentage(td::uint64 ticks, td::uint64 total_ticks) {
static double multiplier = 100.0 * (td::thread::hardware_concurrency() ? td::thread::hardware_concurrency() : 1);
return PSTRING() << (static_cast<double>(ticks) / static_cast<double>(total_ticks) * multiplier) << "%";
return PSTRING() << (static_cast<double>(ticks) / static_cast<double>(total_ticks) * multiplier) << '%';
}
td::vector<StatItem> CpuStat::as_vector() const {
@ -167,7 +175,7 @@ td::vector<ServerBotStat> BotStatActor::as_json_ready_vector(double now) {
return res;
}
td::string BotStatActor::get_description() const {
td::string BotStatActor::get_description() {
td::string res = "DURATION";
for (auto &descr : DESCR) {
res += "\t";

View File

@ -9,7 +9,6 @@
#include "td/actor/actor.h"
#include "td/utils/common.h"
#include "td/utils/logging.h"
#include "td/utils/port/Stat.h"
#include "td/utils/Time.h"
#include "td/utils/TimedStat.h"
@ -49,16 +48,10 @@ class ServerCpuStat {
static ServerCpuStat stat;
return stat;
}
static void update(double now) {
auto r_event = td::cpu_stat();
if (r_event.is_error()) {
return;
}
instance().add_event(r_event.ok(), now);
LOG(WARNING) << "CPU usage: " << instance().stat_[1].get_stat(now).as_vector()[0].value_;
}
td::string get_description() const;
static void update(double now);
static td::string get_description();
td::vector<StatItem> as_vector(double now);
td::vector<td::vector<StatItem>> as_json_ready_vector(double now);
@ -72,8 +65,6 @@ class ServerCpuStat {
td::TimedStat<CpuStat> stat_[SIZE];
ServerCpuStat();
void add_event(const td::CpuStat &stat, double now);
};
class ServerBotInfo {
@ -157,7 +148,7 @@ class BotStatActor final : public td::Actor {
}
BotStatActor(const BotStatActor &) = delete;
BotStatActor &operator=(const BotStatActor &other) = delete;
BotStatActor &operator=(const BotStatActor &) = delete;
BotStatActor(BotStatActor &&) = default;
BotStatActor &operator=(BotStatActor &&other) noexcept {
if (!empty()) {
@ -185,8 +176,8 @@ class BotStatActor final : public td::Actor {
td::vector<StatItem> as_vector(double now);
td::vector<ServerBotStat> as_json_ready_vector(double now);
td::string get_description() const;
td::vector<td::string> get_jsonable_description() const;
static td::string get_description();
double get_score(double now);

View File

@ -47,10 +47,8 @@ WebhookActor::WebhookActor(td::ActorShared<Callback> callback, td::int64 tqueue_
, fix_ip_address_(fix_ip_address)
, from_db_flag_(from_db_flag)
, max_connections_(max_connections)
, secret_token_(std::move(secret_token))
, slow_scheduler_id_(td::Scheduler::instance()->sched_count() - 2) {
, secret_token_(std::move(secret_token)) {
CHECK(max_connections_ > 0);
CHECK(slow_scheduler_id_ > 0);
if (!cached_ip_address.empty()) {
auto r_ip_address = td::IPAddress::get_ip_address(cached_ip_address);
@ -73,7 +71,7 @@ WebhookActor::WebhookActor(td::ActorShared<Callback> callback, td::int64 tqueue_
WebhookActor::~WebhookActor() {
td::Scheduler::instance()->destroy_on_scheduler(SharedData::get_file_gc_scheduler_id(), update_map_, queue_updates_,
queues_);
queues_, ssl_ctx_);
}
void WebhookActor::relax_wakeup_at(double wakeup_at, const char *source) {
@ -230,7 +228,8 @@ td::Status WebhookActor::create_connection(td::BufferedFd<td::SocketFd> fd) {
auto *conn = connections_.get(id);
conn->actor_id_ = td::create_actor<td::HttpOutboundConnection>(
PSLICE() << "Connect:" << id, std::move(fd), std::move(ssl_stream), 0, 50, 60,
td::ActorShared<td::HttpOutboundConnection::Callback>(actor_id(this), id), slow_scheduler_id_);
td::ActorShared<td::HttpOutboundConnection::Callback>(actor_id(this), id),
SharedData::get_slow_outgoing_http_scheduler_id());
conn->ip_generation_ = ip_generation_;
conn->event_id_ = {};
conn->id_ = id;
@ -623,10 +622,12 @@ void WebhookActor::handle(td::unique_ptr<td::HttpQuery> response) {
if (!method.empty() && method != "deletewebhook" && method != "setwebhook" && method != "close" &&
method != "logout" && !td::begins_with(method, "get")) {
VLOG(webhook) << "Receive request " << method << " in response to webhook";
auto query = td::make_unique<Query>(std::move(response->container_), td::MutableSlice(), false, false,
td::MutableSlice(), std::move(response->args_),
std::move(response->headers_), std::move(response->files_),
parameters_->shared_data_, response->peer_address_, false);
response->container_.emplace_back(PSLICE() << (tqueue_id_ & ((static_cast<td::int64>(1) << 54) - 1)));
auto token = response->container_.back().as_slice();
auto query = td::make_unique<Query>(
std::move(response->container_), token, tqueue_id_ >= (static_cast<td::int64>(1) << 54), false,
td::MutableSlice(), std::move(response->args_), std::move(response->headers_),
std::move(response->files_), parameters_->shared_data_, response->peer_address_, false);
auto promised_query = PromisedQueryPtr(query.release(), PromiseDeleter(td::Promise<td::unique_ptr<Query>>()));
send_closure(callback_, &Callback::send, std::move(promised_query));
}
@ -690,7 +691,12 @@ void WebhookActor::handle(td::unique_ptr<td::HttpQuery> response) {
void WebhookActor::start_up() {
max_loaded_updates_ = max_connections_ * 2;
next_ip_address_resolve_time_ = last_success_time_ = td::Time::now() - 3600;
last_success_time_ = td::Time::now() - 2 * IP_ADDRESS_CACHE_TIME;
if (from_db_flag_) {
next_ip_address_resolve_time_ = td::Time::now() + td::Random::fast(0, IP_ADDRESS_CACHE_TIME);
} else {
next_ip_address_resolve_time_ = last_success_time_;
}
active_new_connection_flood_.add_limit(0.5, 10);
@ -723,11 +729,12 @@ void WebhookActor::start_up() {
if (url_.protocol_ != td::HttpUrl::Protocol::Http && !stop_flag_) {
// asynchronously create SSL context
td::Scheduler::instance()->run_on_scheduler(
SharedData::get_database_scheduler_id(), [actor_id = actor_id(this), cert_path = cert_path_](td::Unit) mutable {
send_closure(actor_id, &WebhookActor::on_ssl_context_created,
td::SslCtx::create(cert_path, td::SslCtx::VerifyPeer::On));
});
td::Scheduler::instance()->run_on_scheduler(SharedData::get_webhook_certificate_scheduler_id(),
[actor_id = actor_id(this), cert_path = cert_path_](td::Unit) mutable {
send_closure(
actor_id, &WebhookActor::on_ssl_context_created,
td::SslCtx::create(cert_path, td::SslCtx::VerifyPeer::On));
});
}
yield();

View File

@ -177,7 +177,6 @@ class WebhookActor final : public td::HttpOutboundConnection::Callback {
double last_success_time_ = 0;
double wakeup_at_ = 0;
bool last_update_was_successful_ = true;
td::int32 slow_scheduler_id_ = -1;
void relax_wakeup_at(double wakeup_at, const char *source);

View File

@ -165,7 +165,7 @@ int main(int argc, char *argv[]) {
auto start_time = td::Time::now();
auto shared_data = std::make_shared<SharedData>();
auto parameters = std::make_unique<ClientParameters>();
parameters->version_ = "6.7.1";
parameters->version_ = "6.9.2";
parameters->shared_data_ = shared_data;
parameters->start_time_ = start_time;
auto net_query_stats = td::create_net_query_stats();
@ -476,27 +476,22 @@ int main(int argc, char *argv[]) {
// << (td::GitInfo::is_dirty() ? "(dirty)" : "") << " started";
LOG(WARNING) << "TDLight Bot API " << parameters->version_ << " server started";
// +3 threads for Td
// one thread for ClientManager and all Clients
// one thread for watchdogs
// one thread for slow HTTP connections
// one thread for DNS resolving
const int thread_count = 7;
td::ConcurrentScheduler sched(thread_count, cpu_affinity);
td::ConcurrentScheduler sched(SharedData::get_thread_count() - 1, cpu_affinity);
td::GetHostByNameActor::Options get_host_by_name_options;
get_host_by_name_options.scheduler_id = thread_count;
get_host_by_name_options.scheduler_id = SharedData::get_dns_resolver_scheduler_id();
parameters->get_host_by_name_actor_id_ =
sched.create_actor_unsafe<td::GetHostByNameActor>(0, "GetHostByName", std::move(get_host_by_name_options))
.release();
auto client_manager =
sched.create_actor_unsafe<ClientManager>(thread_count - 3, "ClientManager", std::move(parameters), token_range)
.release();
auto client_manager = sched
.create_actor_unsafe<ClientManager>(SharedData::get_client_scheduler_id(), "ClientManager",
std::move(parameters), token_range)
.release();
sched
.create_actor_unsafe<HttpServer>(
thread_count - 3, "HttpServer", http_ip_address, http_port,
SharedData::get_client_scheduler_id(), "HttpServer", http_ip_address, http_port,
[client_manager, shared_data] {
return td::ActorOwn<td::HttpInboundConnection::Callback>(
td::create_actor<HttpConnection>("HttpConnection", client_manager, shared_data));
@ -506,7 +501,7 @@ int main(int argc, char *argv[]) {
if (http_stat_port != 0) {
sched
.create_actor_unsafe<HttpServer>(
thread_count - 3, "HttpStatsServer", http_stat_ip_address, http_stat_port,
SharedData::get_client_scheduler_id(), "HttpStatsServer", http_stat_ip_address, http_stat_port,
[client_manager] {
return td::ActorOwn<td::HttpInboundConnection::Callback>(
td::create_actor<HttpStatConnection>("HttpStatConnection", client_manager));
@ -515,8 +510,8 @@ int main(int argc, char *argv[]) {
}
constexpr double WATCHDOG_TIMEOUT = 0.25;
auto watchdog_id =
sched.create_actor_unsafe<Watchdog>(thread_count - 2, "Watchdog", td::this_thread::get_id(), WATCHDOG_TIMEOUT);
auto watchdog_id = sched.create_actor_unsafe<Watchdog>(SharedData::get_watchdog_scheduler_id(), "Watchdog",
td::this_thread::get_id(), WATCHDOG_TIMEOUT);
sched.start();
@ -578,13 +573,15 @@ int main(int argc, char *argv[]) {
next_cron_time = now;
}
next_cron_time += 1.0;
ServerCpuStat::update(now);
auto guard = sched.get_main_guard();
td::Scheduler::instance()->run_on_scheduler(SharedData::get_statistics_thread_id(),
[](td::Unit) { ServerCpuStat::update(td::Time::now()); });
}
if (now >= start_time + 600) {
auto guard = sched.get_main_guard();
send_closure(watchdog_id, &Watchdog::kick);
next_watchdog_kick_time = now + WATCHDOG_TIMEOUT / 2;
next_watchdog_kick_time = now + WATCHDOG_TIMEOUT / 10;
}
if (!need_dump_statistics.test_and_set() || now > last_dump_time + 300.0) {