[Evolution-hackers] PIM server synchronization and Evolution online/offline state

Hi everyone.

While porting evolution-kolab from Evolution 2.30 to 3.4.x (and on
to 3.5 later on), I have been stumbling upon an issue regarding
groupware server synchronzation.

Back in version 2.30, Evolution has not had a dedicated "synchronize"
button, but there has been the online/offline button, which, when toggled,
resulted in a synchronize() function being called in the cal/book backends.
Evo's online/offline state was independent of network availability back then.
From a user's point of view, it was okay to have the backend synchronize
with the groupware server when Evo online/offline state was toggled.

In version 3.4 of Evolution, this functionality is no longer existing. As I
learned on IRC yesterday, at least as of GLib version 2.32, the "online"
EBackend property is not even toggled by Evolution itself, but by GNetworkMonitor,
depending on network (un)availability. If the network is available, the
EBackend "online" property is set to TRUE by GNetworkMonitor (via the backend
factory), and is set to FALSE once the network becomes unavailable.

Effectively, I am lacking a mechanism which tells my backend that the user
wants to synchronize the local cache (evolution implements a full offline
cache with offline-editing support) with the Kolab server side. If the network
is unavailable and then becomes available, it is debatable whether this would
be a good time to start a synchronization run. However, if GNetworkMonitor signals
network is unavailable, obviously, it is too late to try to synchronize with
the server.

It has been proposed to use an asynchronous backend thread to synchronize with
the server. While it could be done, it has the drawback that during sync, sync
conflicts can occur. evolution-kolab presently implements a pre-configurable
sync conflict resolution strategy which does not need user interaction during
sync, but this was a simplification done in 2.30 since we did not have the
capability to ask for user interaction from E-D-S back then. Years of experience
with Kolab (and other groupwares) have shown that automatic conflict resolution
cannot get it right in many cases and user interaction (manual conflict resolution
via a dialog) is needed. Implementation for this has started in evolution-kolab.
Back to the topic: A synchronization background thread will run into a sync conflict
sooner or later, and a dialog will pop up asking for user interaction. This will
inevitably happen while the user is occupied with something else, like composing
an email, and it will then disturb her workflow, since she was not expecting
some sync conflict dialog to pop up (the principle of least surprise will be
violated), let alone the fact that an async synchronization thread introduces
a nice extra level of complexity.

Kolab server synchronization can become quite bulky, since the Kolab server does
not have some notion of per-client changesets. It is a mere storage, and
synchronization means to grovel through folders in search of emails. This can
take quite some time, depending on how many objects are stored in a given folder,
and it can be heavy on CPU usage as well as network bandwidth usage. If that starts
grovelling just the moment some network becomes available, that can be much 
annoying to the unexpecting user.

IMHO, you it is a plain impossibility to "guess" the correct time for a server
synchronization. As a backend, I do not know what the user wants to do next. Network
may be available, but it may be awfully slow (e.g. some hotel room), and the user would
prefer to just check some mails and do the heavy groupware server synchronization when
back in the office. Some users prefer to work in offline mode, even when networking is
available, and do some bulk sync when the time seems right for them.

This means that the most simple, most straight-forward and least-surprising (for the
user) thing to do would be to invent a dedicated sync button, with which the user can
direct the backends to do the server synchronization *now*. Once this button is pressed,
it is clear to the user that now, things can take their time and she will be willing to
wait for as long as the sync run takes. Depending on network availability, this sync
button can even be grayed out - it surely makes sense to deactivate that button if
there is no network available (maybe some tooltip could show information why the sync
button is deactivated). If networking is available, then the sync button can be pressed.
The sync, due to multiple reasons, can still fail, but this is something for the
backends to handle.

My proposal would be an EBackend virtual function, which the backends can choose to
implement and which is called when the user does a dedicated UI action, like pressing a
sync button:

EBackend::synchronize (EBackend *backend, EDataCal *cal, GCancellable *cancellable, GError *error);

That would be one part of the issue.

Next part is, that I think network (un)availability and Evolution/E-D-S online/offline
state are two separate things, which got mixed in the current implementation. Network
unavailability means I cannot write my objects onto the server. In evolution-kolab,
whenever a PIM object is saved, it is first stored in the local write cache. If in "online"
state (as in Evo 2.30 semantics), evo-kolab would then try to push the object onto the server,
which may fail due to a multitude of reasons - server down, network line shaky (connection
dropouts), firewall-of-the-day is active or whatsoever. The PIM object then simply stays in
the offline cache, waiting for a later successful sync with the server.
  If the evolution-kolab backend is in "offline" state (again, as in Evo 2.30 semantics),
after writing an object to the offline write cache, *no* attempt will be made to push this
object onto the server, and it will sit there in the offline cache until the next
synchronization attempt (best done via a dedicated sync button, IMHO) is made.
  This means that "online" or "offline" state for *Evolution* is a setting a user
should be able to toggle, as it is a client state, while network (un)availability, or even
service unavailability, is a different matter. The current implementation is - IMHO - an
oversimplification which does not match the needs of an offline-capable PIM client. If the
backend can query network availability (or gets this information via an object property),
this is much helpful, but it is not sufficient.

What do you think?

Kind regards,


kernel concepts GmbH       Tel: +49-271-771091-14
Sieghuetter Hauptweg 48
D-57072 Siegen

Attachment: signature.asc
Description: This is a digitally signed message part.

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]