https://bugs.kde.org/show_bug.cgi?id=492489

Alessandro Accardo <[email protected]> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |[email protected]

--- Comment #2 from Alessandro Accardo <[email protected]> ---
Still happening here with kdepim-runtime 26.08.1 (openSUSE Tumbleweed, Qt
6.11.2, Frameworks 6.30) against Exchange Online / Office 365 with OAuth2. Same
log pattern as comment 1, exactly one line per minute:

  akonadi_ews_resource[18935]: Streaming request timeout - restarting
  akonadi_ews_resource[18935]: Streaming request timeout - restarting
  ...

Manual "Check mail" works fine every time, but new mail never shows up on its
own.

I went through the code and I think the cause is the port away from KIO in
commit dd785b95af83fd74618b5e4ce2904fa86db771e3 ("Port EWS resource away from
KIO Http").

Before that commit, EwsGetStreamingEventsRequest overrode
requestData(KIO::Job*, const QByteArray&), which appended every incoming chunk
to mResponseData and restarted mRespTimer. After 250 ms of silence
requestDataTimeout() parsed the buffer and emitted eventsReceived().

After the port there is no equivalent anymore:
- EwsRequest::prepare() connects KJob::percentChanged to requestProgress()
(ewsrequest.cpp:103). TransferJob only calls setProcessedAmount() and never
sets a total, so as far as I can tell percentChanged is never emitted and
requestProgress() never runs.
- Even if it did run, the streaming override of requestProgress() does not read
anything from the reply. It only restarts mRespTimer, and that is also the only
place where mRespTimer gets started.
- The only place that fills mResponseData is EwsRequest::requestResult(), which
runs when the reply finishes. A streaming reply stays open until
ConnectionTimeout expires, so that doesn't happen in time.

So mRespTimer never starts, requestDataTimeout() never runs, eventsReceived()
is never emitted, and after 60 s (streamingConnTimeout in
ewssubscriptionmanager.cpp) the subscription manager kills the request and
starts a new one. Any notification the server sent on that connection is lost.
That matches the one-minute log pattern exactly. I checked master and the
relevant files are the same as in 26.08.1.

Unrelated to the above, but I noticed it in the same function: since
5b9a8023fa6f56a0638f36824c404b4867227431 ("EWS: Use std::chrono") mTimeout is
std::chrono::seconds, and ewssubscriptionmanager.cpp passes 30min, so the
request now contains

  <m:ConnectionTimeout>1800</m:ConnectionTimeout>

The EWS docs say the value is in minutes and "must be between 1 and 30,
inclusive"
(https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/connectiontimeout),
and before that commit the value sent was 30. The default in the constructor
went from 30 (minutes) to 30s as well. Office 365 doesn't seem to reject it
(otherwise I'd expect errors in the log rather than a clean 60 s cycle), but I
haven't looked at the actual server response, so I can't say how it handles it.

What I have in mind for a fix is roughly this: have TransferJob forward
QNetworkReply::readyRead, connect that to requestProgress() instead of
percentChanged, and in the streaming override do mResponseData +=
reply->readAll() before restarting mRespTimer. For the other requests nothing
changes, since the data stays buffered in the reply until requestResult() calls
readAll(). requestResult() would also need mResponseData += readAll() instead
of =, so a chunk that was read but not parsed yet isn't overwritten when the
connection closes. For the timeout, I'd make mTimeout and setTimeout()
std::chrono::minutes, default 30min. That way count() gives the right number,
and passing seconds by mistake won't compile.

I have a draft patch along those lines, but I haven't been able to build or
test it yet, so I'm not attaching it for now. If this sounds like the right
direction I can finish it and open a merge request.

Also, for anyone else hitting this, the PollInterval setting in the resource
config doesn't help: it isn't read anywhere in the current code. A workaround
that does work is setting a retrieval interval on the Inbox in KMail's folder
properties. It's handled by the Akonadi server's IntervalCheck, so it can't go
below 5 minutes, but at least mail comes in without a manual check.

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to