Limit scheduled requests for one per minute.

This commit is contained in:
John Preston 2019-08-29 20:16:37 +03:00
parent 2b656f7745
commit f199205592
2 changed files with 32 additions and 5 deletions

View File

@ -18,6 +18,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Data { namespace Data {
namespace { namespace {
constexpr auto kRequestTimeLimit = 60 * crl::time(1000);
[[nodiscard]] bool TooEarlyForRequest(crl::time received) {
return (received > 0) && (received + kRequestTimeLimit > crl::now());
}
MTPMessage PrepareMessage(const MTPMessage &message, MsgId id) { MTPMessage PrepareMessage(const MTPMessage &message, MsgId id) {
return message.match([&](const MTPDmessageEmpty &) { return message.match([&](const MTPDmessageEmpty &) {
return MTP_messageEmpty(MTP_int(id)); return MTP_messageEmpty(MTP_int(id));
@ -62,7 +68,8 @@ MTPMessage PrepareMessage(const MTPMessage &message, MsgId id) {
} // namespace } // namespace
ScheduledMessages::ScheduledMessages(not_null<Session*> owner) ScheduledMessages::ScheduledMessages(not_null<Session*> owner)
: _session(&owner->session()) { : _session(&owner->session())
, _clearTimer([=] { clearOldRequests(); }) {
owner->itemRemoved( owner->itemRemoved(
) | rpl::filter([](not_null<const HistoryItem*> item) { ) | rpl::filter([](not_null<const HistoryItem*> item) {
return item->isScheduled(); return item->isScheduled();
@ -77,6 +84,21 @@ ScheduledMessages::~ScheduledMessages() {
} }
} }
void ScheduledMessages::clearOldRequests() {
const auto now = crl::now();
while (true) {
const auto i = ranges::find_if(_requests, [&](const auto &value) {
const auto &request = value.second;
return !request.requestId
&& (request.lastReceived + kRequestTimeLimit <= now);
});
if (i == end(_requests)) {
break;
}
_requests.erase(i);
}
}
MsgId ScheduledMessages::lookupId(not_null<HistoryItem*> item) const { MsgId ScheduledMessages::lookupId(not_null<HistoryItem*> item) const {
Expects(item->isScheduled()); Expects(item->isScheduled());
@ -215,7 +237,7 @@ Data::MessagesSlice ScheduledMessages::list(not_null<History*> history) {
void ScheduledMessages::request(not_null<History*> history) { void ScheduledMessages::request(not_null<History*> history) {
auto &request = _requests[history]; auto &request = _requests[history];
if (request.requestId) { if (request.requestId || TooEarlyForRequest(request.lastReceived)) {
return; return;
} }
const auto i = _data.find(history); const auto i = _data.find(history);
@ -235,7 +257,11 @@ void ScheduledMessages::parse(
not_null<History*> history, not_null<History*> history,
const MTPmessages_Messages &list) { const MTPmessages_Messages &list) {
auto &request = _requests[history]; auto &request = _requests[history];
request.lastReceived = crl::now();
request.requestId = 0; request.requestId = 0;
if (!_clearTimer.isActive()) {
_clearTimer.callOnce(kRequestTimeLimit * 2);
}
list.match([&](const MTPDmessages_messagesNotModified &data) { list.match([&](const MTPDmessages_messagesNotModified &data) {
}, [&](const auto &data) { }, [&](const auto &data) {
@ -263,9 +289,6 @@ void ScheduledMessages::parse(
} }
updated(history, received, clear); updated(history, received, clear);
}); });
if (!request.requestId) {
_requests.remove(history);
}
} }
HistoryItem *ScheduledMessages::append( HistoryItem *ScheduledMessages::append(

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once #pragma once
#include "history/history_item.h" #include "history/history_item.h"
#include "base/timer.h"
class History; class History;
@ -51,6 +52,7 @@ private:
}; };
struct Request { struct Request {
mtpRequestId requestId = 0; mtpRequestId requestId = 0;
crl::time lastReceived = 0;
}; };
void request(not_null<History*> history); void request(not_null<History*> history);
@ -69,9 +71,11 @@ private:
void sort(List &list); void sort(List &list);
void remove(not_null<const HistoryItem*> item); void remove(not_null<const HistoryItem*> item);
[[nodiscard]] int32 countListHash(const List &list) const; [[nodiscard]] int32 countListHash(const List &list) const;
void clearOldRequests();
const not_null<Main::Session*> _session; const not_null<Main::Session*> _session;
base::Timer _clearTimer;
base::flat_map<not_null<History*>, List> _data; base::flat_map<not_null<History*>, List> _data;
base::flat_map<not_null<History*>, Request> _requests; base::flat_map<not_null<History*>, Request> _requests;
rpl::event_stream<not_null<History*>> _updates; rpl::event_stream<not_null<History*>> _updates;