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, Christian -- kernel concepts GmbH Tel: +49-271-771091-14 Sieghuetter Hauptweg 48 D-57072 Siegen http://www.kernelconcepts.de/
Attachment:
signature.asc
Description: This is a digitally signed message part.