Skip to content

Commit c8a00cb

Browse files
authored
refactor: [DC-324] decouple retrieving server settings and user info from connection validator routines (#12619)
* first pass for moving the FetchServerSettingsJob to AccountState it leaks at the moment as there are issues with deleting the job on finished signal. that needs to be fixed in the job by ensuring the "asyncUpdates" are finished before the finished signal is emitted. alternately can call those extra operations from the AccountState but I think having it all in the job is simpler. * this works but may have side effects committing it for discussion with cohort * works now but.. this is a very questionable impl. The core problem is not being able to simply delete the settings job, in tandem with questionable "need" to have that be null by the time the folders are enqueued. will discuss next week and clean it up * lots of cleanup also refined the caps/user info/avatar/appprovider retrieval to only happen on start and re-auth. needs a bit more testing then hoping it's done * final cleanup and refinement also renamed the very misleading FetchServerSettingsJob to FetchServerSettingsRunner. by unanimous decision we just killed the previous caps related tests in ConnectionValidator since it is no longer in play there. * added changelog * grrrr
1 parent e12c309 commit c8a00cb

10 files changed

Lines changed: 147 additions & 131 deletions

File tree

changelog/unreleased/12619.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Change: Eliminated excessive server checks
2+
3+
The server capabilities, user settings, avatar and app providers are now updated only on application start and after the user has re-authenticated during a running session.
4+
5+
https://github.com/owncloud/client/pull/12619

src/gui/accountstate.cpp

Lines changed: 92 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
#include "application.h"
1717
#include "configfile.h"
1818

19-
#include "fetchserversettings.h"
19+
// #include "fetchserversettings.h"
20+
#include "libsync/networkjobs/jsonjob.h"
2021

2122
#include "libsync/creds/abstractcredentials.h"
2223

@@ -56,6 +57,7 @@ AccountState::AccountState(Account *account)
5657
, _waitingForNewCredentials(false)
5758
, _connectionValidator(nullptr)
5859
, _maintenanceToConnectedDelay(1min + minutes(QRandomGenerator::global()->generate() % 4)) // 1-5min delay
60+
, _needsServerSettingsRefresh(true)
5961
{
6062
qRegisterMetaType<AccountState *>("AccountState*");
6163

@@ -187,29 +189,97 @@ void AccountState::setState(State state)
187189
}
188190
}
189191

190-
// might not have changed but the underlying _connectionErrors might have
192+
// only do this once when the state actually changes from something to connected
193+
// todo: need to investigate whether it's ever the case that we go from connected to connected.
194+
// so far it looks to me as if this happens when the connection validator confirms all is still well?
191195
if (_state == Connected) {
192-
QTimer::singleShot(0, this, [this, oldState] {
193-
// ensure the connection validator is done
194-
_queueGuard.unblock();
196+
if (_needsServerSettingsRefresh) {
195197
// update capabilities and fetch relevant settings
196-
_fetchCapabilitiesJob = new FetchServerSettingsJob(_account, this);
197-
connect(_fetchCapabilitiesJob.get(), &FetchServerSettingsJob::finishedSignal, this, [oldState, this] {
198-
// Lisa todo: I do not understand this logic at all - review it
199-
if (oldState == Connected || _state == Connected) {
200-
_fetchCapabilitiesJob.clear();
201-
Q_EMIT isConnectedChanged();
202-
}
203-
});
204-
_fetchCapabilitiesJob->start();
205-
});
198+
// in the code path we unblock the queue *after* the caps retrieval has succeeded
199+
fetchServerSettings();
200+
} else
201+
_queueGuard.unblock();
206202
}
207203

208204
if (oldState != _state) {
209205
Q_EMIT stateChanged(_state);
206+
// the old->new state is confirmed to be different and one of them is connected state so
207+
// isConnected did actually change
208+
if (oldState == Connected || _state == Connected)
209+
emit isConnectedChanged();
210+
}
211+
}
212+
213+
void AccountState::fetchServerSettings()
214+
{
215+
Q_ASSERT(_fetchServerSettingsRunner == nullptr);
216+
_fetchServerSettingsRunner = new FetchServerSettingsRunner(_account, this);
217+
218+
connect(_fetchServerSettingsRunner, &FetchServerSettingsRunner::finishedSignal, this, &AccountState::slotFetchServerSettingsResult);
219+
_fetchServerSettingsRunner->start();
220+
}
221+
222+
void AccountState::slotFetchServerSettingsResult(FetchServerSettingsRunner::Result result)
223+
{
224+
Q_ASSERT(_state == Connected);
225+
226+
_connectionErrors.clear();
227+
228+
State newState = _state;
229+
230+
switch (result) {
231+
case FetchServerSettingsRunner::Result::UnsupportedServer:
232+
_connectionErrors.append(tr("The server is not supported by this client."));
233+
newState = ConfigurationError;
234+
break;
235+
case FetchServerSettingsRunner::Result::InvalidCredentials:
236+
slotInvalidCredentials();
237+
break;
238+
case FetchServerSettingsRunner::Result::TimeOut:
239+
_connectionErrors.append(tr("Retrieving user settings and server capabilities timed out."));
240+
// hmmm...do we need to retry in this case? I'm guessing yes but needs discussion
241+
// actually no, we should not need to do it explicitly as the next round(s) of connection validator should
242+
// hopefully resolve it
243+
newState = NetworkError;
244+
break;
245+
case FetchServerSettingsRunner::Result::Undefined:
246+
_connectionErrors.append(tr("Unable to retrieve user settings and server capabilities."));
247+
newState = Disconnected;
248+
break;
249+
case FetchServerSettingsRunner::Result::Success:
250+
break;
251+
}
252+
253+
// this step is done, delete after this slot finishes else the self deleting jobs inside get munged up -> crash. TODO: evaluate whether there is any
254+
// value to use the parenting mechanism for the AbstractNetworkJobs inside the FetchServerSettingsJob - I find it really questionable to parent
255+
// self deleting objects but this needs deeper investigation.
256+
_fetchServerSettingsRunner->deleteLater();
257+
258+
if (newState != Connected) {
259+
setState(newState);
260+
return;
210261
}
262+
263+
// these are both self deleting.
264+
// they can finish whenever, everything else can carry on.
265+
if (_account->capabilities().avatarsAvailable()) {
266+
auto *avatarJob = new AvatarJob(_account, _account->davUser(), 128, nullptr);
267+
connect(avatarJob, &AvatarJob::avatarPixmap, this, [this](const QPixmap &img) { _account->setAvatar(AvatarJob::makeCircularAvatar(img)); });
268+
avatarJob->start();
269+
}
270+
271+
if (_account->capabilities().appProviders().enabled) {
272+
auto *jsonJob = new JsonJob(_account, _account->capabilities().appProviders().appsUrl, {}, "GET");
273+
connect(jsonJob, &JsonJob::finishedSignal, this, [jsonJob, this] { _account->setAppProvider(AppProvider{jsonJob->data()}); });
274+
jsonJob->start();
275+
}
276+
277+
_needsServerSettingsRefresh = false;
278+
_queueGuard.unblock();
279+
emit isConnectedChanged();
211280
}
212281

282+
213283
bool AccountState::isSignedOut() const
214284
{
215285
return _state == SignedOut;
@@ -489,8 +559,6 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta
489559
setState(Disconnected);
490560
break;
491561
case ConnectionValidator::ClientUnsupported:
492-
[[fallthrough]];
493-
case ConnectionValidator::ServerVersionMismatch:
494562
setState(ConfigurationError);
495563
break;
496564
case ConnectionValidator::StatusNotFound:
@@ -543,6 +611,7 @@ void AccountState::slotInvalidCredentials()
543611
qCInfo(lcAccountState) << "refreshing oauth failed";
544612
qCInfo(lcAccountState) << "asking user";
545613

614+
_needsServerSettingsRefresh = true;
546615
creds->askFromUser();
547616
setState(AskingCredentials);
548617
}
@@ -590,7 +659,12 @@ void AccountState::setSettingUp(bool settingUp)
590659
}
591660
bool AccountState::readyForSync() const
592661
{
593-
return !_fetchCapabilitiesJob && isConnected();
662+
// this is highly questionable.
663+
// first, this explains why the folders aren't ever syncing after refactoring the fetchServerSettings job. Folder::canSync calls this and
664+
// that is checked when trying to enqueue the folder
665+
// net is that because we can't cleanly get rid of the fetshServerSettingsJob (yet) this always returns false! or at least it does
666+
// on first folder load.
667+
return !_needsServerSettingsRefresh && isConnected();
594668
}
595669

596670
} // namespace OCC

src/gui/accountstate.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "gui/owncloudguilib.h"
2020

2121
#include "connectionvalidator.h"
22+
#include "fetchserversettings.h"
2223
#include "jobqueue.h"
2324

2425
#include "account.h"
@@ -38,7 +39,6 @@ namespace OCC {
3839

3940
class QuotaInfo;
4041
class TlsErrorDialog;
41-
class FetchServerSettingsJob;
4242

4343
/**
4444
* @brief Extra info about an ownCloud server account.
@@ -159,8 +159,8 @@ class OWNCLOUDGUI_EXPORT AccountState : public QObject
159159
void checkConnectivity(bool blockJobs = false);
160160

161161
private:
162-
163162
void setState(State state);
163+
void fetchServerSettings();
164164

165165
Q_SIGNALS:
166166
void stateChanged(State state);
@@ -169,6 +169,7 @@ class OWNCLOUDGUI_EXPORT AccountState : public QObject
169169

170170
protected Q_SLOTS:
171171
void slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList &errors);
172+
void slotFetchServerSettingsResult(OCC::FetchServerSettingsRunner::Result result);
172173
void slotInvalidCredentials();
173174
void slotCredentialsFetched();
174175

@@ -217,7 +218,8 @@ protected Q_SLOTS:
217218

218219
QuotaInfo *_quotaInfo = nullptr;
219220

220-
QPointer<FetchServerSettingsJob> _fetchCapabilitiesJob;
221+
QPointer<FetchServerSettingsRunner> _fetchServerSettingsRunner;
222+
bool _needsServerSettingsRefresh = false;
221223
};
222224
}
223225

src/gui/connectionvalidator.cpp

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include "libsync/creds/abstractcredentials.h"
2020
#include "libsync/networkjobs.h"
2121
#include "libsync/networkjobs/checkserverjobfactory.h"
22-
#include "libsync/theme.h"
2322

2423
#include <QJsonObject>
2524
#include <QLoggingCategory>
@@ -284,38 +283,38 @@ void ConnectionValidator::slotAuthSuccess()
284283
}
285284

286285
_errors.clear();
287-
if (_mode != ConnectionValidator::ValidationMode::ValidateAuth) {
288-
auto *fetchSetting = new FetchServerSettingsJob(_account, this);
289-
const auto unsupportedServerError = [this] {
290-
_errors.append({tr("The configured server for this client is too old."), tr("Please update to the latest server and restart the client.")});
291-
};
292-
connect(fetchSetting, &FetchServerSettingsJob::finishedSignal, this, [unsupportedServerError, this](FetchServerSettingsJob::Result result) {
293-
switch (result) {
294-
case FetchServerSettingsJob::Result::UnsupportedServer:
295-
unsupportedServerError();
296-
reportResult(ServerVersionMismatch);
297-
break;
298-
case FetchServerSettingsJob::Result::InvalidCredentials:
299-
reportResult(CredentialsWrong);
300-
break;
301-
case FetchServerSettingsJob::Result::TimeOut:
302-
reportResult(Timeout);
303-
break;
304-
case FetchServerSettingsJob::Result::Success:
305-
if (_account->serverSupportLevel() == Account::ServerSupportLevel::Unknown) {
306-
unsupportedServerError();
307-
}
308-
reportResult(Connected);
309-
break;
310-
case FetchServerSettingsJob::Result::Undefined:
311-
reportResult(Undefined);
312-
break;
313-
}
314-
});
315-
316-
fetchSetting->start();
317-
return;
318-
}
286+
/* if (_mode != ConnectionValidator::ValidationMode::ValidateAuth) {
287+
auto *fetchSetting = new FetchServerSettingsJob(_account, this);
288+
const auto unsupportedServerError = [this] {
289+
_errors.append({tr("The configured server for this client is too old."), tr("Please update to the latest server and restart the client.")});
290+
};
291+
connect(fetchSetting, &FetchServerSettingsJob::finishedSignal, this, [unsupportedServerError, this](FetchServerSettingsJob::Result result) {
292+
switch (result) {
293+
case FetchServerSettingsJob::Result::UnsupportedServer:
294+
unsupportedServerError();
295+
reportResult(ServerVersionMismatch);
296+
break;
297+
case FetchServerSettingsJob::Result::InvalidCredentials:
298+
reportResult(CredentialsWrong);
299+
break;
300+
case FetchServerSettingsJob::Result::TimeOut:
301+
reportResult(Timeout);
302+
break;
303+
case FetchServerSettingsJob::Result::Success:
304+
if (_account->serverSupportLevel() == Account::ServerSupportLevel::Unknown) {
305+
unsupportedServerError();
306+
}
307+
reportResult(Connected);
308+
break;
309+
case FetchServerSettingsJob::Result::Undefined:
310+
reportResult(Undefined);
311+
break;
312+
}
313+
});
314+
315+
fetchSetting->start();
316+
return;
317+
}*/
319318
reportResult(Connected);
320319
}
321320

src/gui/connectionvalidator.h

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,9 @@ namespace OCC {
6262
|
6363
+-> slotAuthSuccess --+--> X (depending if coming from checkServerAndAuth or not)
6464
|
65-
+---------------------------+
66-
|
67-
+-> checkServerCapabilities
68-
JsonApiJob (cloud/capabilities) -> slotCapabilitiesRecieved -+
69-
|
70-
+------------------------------------------------------------------+
71-
|
72-
+-> fetchUser -+
73-
|
74-
+-> AvatarJob
75-
|
76-
+-> slotAvatarImage --> reportResult()
65+
66+
retrieving server capabilities, user settings, avatar and app providers (if enabled) has moved to account state as those
67+
checks should happen much less frequently!
7768
7869
\endcode
7970
*/
@@ -99,7 +90,7 @@ class OWNCLOUDGUI_EXPORT ConnectionValidator : public QObject
9990
Undefined,
10091
Connected,
10192
NotConfigured,
102-
ServerVersionMismatch, // The server version is too old
93+
// ServerVersionMismatch, // The server version is too old
10394
CredentialsNotReady, // Credentials aren't ready
10495
CredentialsWrong, // AuthenticationRequiredError
10596
SslError, // SSL handshake error, certificate rejected by user?

0 commit comments

Comments
 (0)