Don't always restart connection on config change.

This commit is contained in:
John Preston 2019-11-27 13:41:17 +03:00
parent e6c86b19db
commit 06f5f7f7d9
7 changed files with 50 additions and 36 deletions

View File

@ -399,14 +399,18 @@ void Application::badMtprotoConfigurationError() {
void Application::startLocalStorage() {
Local::start();
subscribe(_dcOptions->changed(), [this](const MTP::DcOptions::Ids &ids) {
Local::writeSettings();
if (const auto instance = activeAccount().mtp()) {
for (const auto id : ids) {
instance->restart(id);
}
}
});
const auto writing = _lifetime.make_state<bool>(false);
_dcOptions->changed(
) | rpl::filter([=] {
return !*writing;
}) | rpl::start_with_next([=] {
*writing = true;
Ui::PostponeCall(this, [=] {
Local::writeSettings();
});
}, _lifetime);
_saveSettingsTimer.setCallback([=] { Local::writeSettings(); });
}

View File

@ -126,7 +126,9 @@ Connection::~Connection() {
}
}
void Connection::start(std::shared_ptr<SessionData> sessionData, ShiftedDcId shiftedDcId) {
void Connection::start(
std::shared_ptr<SessionData> sessionData,
ShiftedDcId shiftedDcId) {
Expects(_thread == nullptr && _private == nullptr);
_thread = std::make_unique<QThread>();
@ -137,6 +139,16 @@ void Connection::start(std::shared_ptr<SessionData> sessionData, ShiftedDcId shi
std::move(sessionData),
shiftedDcId);
_instance->dcOptions()->changed(
) | rpl::filter([=](DcId dcId) {
return (BareDcId(shiftedDcId) == dcId) && (_private != nullptr);
}) | rpl::start_with_next([=] {
const auto raw = _private;
InvokeQueued(raw, [=] {
raw->dcOptionsChanged();
});
}, _lifetime);
// will be deleted in the thread::finished signal
_private = newData.release();
_thread->start();
@ -329,10 +341,6 @@ ConnectionPrivate::~ConnectionPrivate() {
Expects(_testConnections.empty());
}
void ConnectionPrivate::onConfigLoaded() {
connectToServer(true);
}
void ConnectionPrivate::onCDNConfigLoaded() {
restart();
}
@ -341,6 +349,11 @@ int32 ConnectionPrivate::getShiftedDcId() const {
return _shiftedDcId;
}
void ConnectionPrivate::dcOptionsChanged() {
_retryTimeout = 1;
connectToServer(true);
}
int32 ConnectionPrivate::getState() const {
QReadLocker lock(&_stateMutex);
int32 result = _state;
@ -1004,7 +1017,6 @@ void ConnectionPrivate::connectToServer(bool afterConfig) {
return restart();
}
DEBUG_LOG(("MTP Info: DC %1 options not found, waiting for config").arg(_shiftedDcId));
connect(_instance, SIGNAL(configLoaded()), this, SLOT(onConfigLoaded()), Qt::UniqueConnection);
InvokeQueued(_instance, [instance = _instance] {
instance->requestConfig();
});

View File

@ -58,6 +58,7 @@ private:
not_null<Instance*> _instance;
std::unique_ptr<QThread> _thread;
ConnectionPrivate *_private = nullptr;
rpl::lifetime _lifetime;
};
@ -76,6 +77,7 @@ public:
void stop();
int32 getShiftedDcId() const;
void dcOptionsChanged();
int32 getState() const;
QString transport() const;
@ -90,7 +92,6 @@ public slots:
void updateAuthKey();
void onConfigLoaded();
void onCDNConfigLoaded();
private:

View File

@ -170,7 +170,7 @@ void DcOptions::processFromList(
ApplyOneOption(data, dcId, flags, ip, port, secret);
}
auto difference = [&] {
const auto difference = [&] {
WriteLocker lock(this);
auto result = CountOptionsDifference(_data, data);
if (!result.empty()) {
@ -178,8 +178,8 @@ void DcOptions::processFromList(
}
return result;
}();
if (!difference.empty()) {
_changed.notify(std::move(difference));
for (const auto dcId : difference) {
_changed.fire_copy(dcId);
}
}
@ -232,9 +232,8 @@ void DcOptions::addFromOther(DcOptions &&options) {
}
}
}
if (!idsChanged.empty()) {
_changed.notify(std::move(idsChanged));
for (const auto dcId : idsChanged) {
_changed.fire_copy(dcId);
}
}
@ -280,10 +279,10 @@ bool DcOptions::ApplyOneOption(
return true;
}
auto DcOptions::CountOptionsDifference(
std::vector<DcId> DcOptions::CountOptionsDifference(
const std::map<DcId, std::vector<Endpoint>> &a,
const std::map<DcId, std::vector<Endpoint>> &b) -> Ids {
auto result = Ids();
const std::map<DcId, std::vector<Endpoint>> &b) {
auto result = std::vector<DcId>();
const auto find = [](
const std::vector<Endpoint> &where,
const Endpoint &what) {
@ -514,8 +513,12 @@ void DcOptions::constructFromSerialized(const QByteArray &serialized) {
}
}
DcOptions::Ids DcOptions::configEnumDcIds() const {
auto result = Ids();
rpl::producer<DcId> DcOptions::changed() const {
return _changed.events();
}
std::vector<DcId> DcOptions::configEnumDcIds() const {
auto result = std::vector<DcId>();
{
ReadLocker lock(this);
result.reserve(_data.size());

View File

@ -66,15 +66,12 @@ public:
const bytes::vector &secret);
QByteArray serialize() const;
using Ids = std::vector<DcId>;
base::Observable<Ids> &changed() const {
return _changed;
}
[[nodiscard]] rpl::producer<DcId> changed() const;
void setFromList(const MTPVector<MTPDcOption> &options);
void addFromList(const MTPVector<MTPDcOption> &options);
void addFromOther(DcOptions &&options);
Ids configEnumDcIds() const;
[[nodiscard]] std::vector<DcId> configEnumDcIds() const;
struct Variants {
enum Address {
@ -119,7 +116,7 @@ private:
const std::string &ip,
int port,
const bytes::vector &secret);
static Ids CountOptionsDifference(
static std::vector<DcId> CountOptionsDifference(
const std::map<DcId, std::vector<Endpoint>> &a,
const std::map<DcId, std::vector<Endpoint>> &b);
static void FilterIfHasWithFlag(Variants &variants, Flag flag);
@ -143,7 +140,7 @@ private:
std::map<DcId, std::map<uint64, internal::RSAPublicKey>> _cdnPublicKeys;
mutable QReadWriteLock _useThroughLockers;
mutable base::Observable<Ids> _changed;
rpl::event_stream<DcId> _changed;
// True when we have overriden options from a .tdesktop-endpoints file.
bool _immutable = false;

View File

@ -860,8 +860,6 @@ void Instance::Private::configLoadDone(const MTPConfig &result) {
_configExpiresAt = crl::now()
+ (data.vexpires().v - base::unixtime::now()) * crl::time(1000);
requestConfigIfExpired();
emit _instance->configLoaded();
}
bool Instance::Private::configLoadFail(const RPCError &error) {

View File

@ -199,7 +199,6 @@ public:
}
signals:
void configLoaded();
void cdnConfigLoaded();
void allKeysDestroyed();
void proxyDomainResolved(