Calendar:Feature Implementations:Calendar Cache
- 1 Basic overview
- 2 Ranged caching
- 3 Offline mode support
- 4 Order of Implementation
- 5 Possible Implementation Strategies
This page describes what is needed to create an abstract implementation to cache calendar events in general. This can be a subset of events or the whole calendar. The latter is needed for offline support. Caching in general will speed up access to remote calendars. It must however be optional, since i.e the memory calendar should not need to be cached.
Note also that as of now, this is only a collection of thoughts. Also, this also applies to tasks. Only writing events instead of tasks and events was used to optimize readablity.
Currently, there is no centralized way for a Provider to cache events. Furthermore, depending on the way providers retrieve events, it is difficult to find a solution that is general enough so that all providers profit from it.
The reason we need to cache calendar events is to speed up access and avoid long waits for the user. Also, extensive caching is needed to support an 'offline' mode. The problem can there split up into two large milestones:
- Ranged caching (for local speedup)
- Offline mode support
The second item depends on the first item to some extent.
In this model, single events can be cached in a certain range. This does not require the whole calendar to be retrieved but much more supports the views in displaying items faster.
For this model it is sufficient to use a memory calendar to cache events, which is updated when local changes are made or the calendar is updated from a remote source. This is already implemented in the ICS calendar.
Caching introduces the need for a simplified versioning on events. One possibility is to use sequence numbers with a timestamp on when the event was last changed and a universally unique token to identify the item version. Depending on the provider, this will make it easier to find out if it is needed to update the cache of the event.
Differences in Provider approaces
There are differnt types of providers that all have their distinct behaviour in regard to caching.
Flat file Providers
These providers include WebDAV. The calendar can only be retrived as a whole. The only way to cache with these providers it to download a full copy of the calendar and copy it into the empty cache.
Event based Providers
These Providers include WCAP and Google. Events can be ideally retrieved by range, by unique ID, or other specific aspects. It is much easier to handle caching here, since deltas can be used to influence which events are updated.
This might be restating the obvious, but these calendars should not be cached, since there is no gain in performance.
It is always possible that the cached events are not up to date. In this case those events need to be resyncronized with the server. Depending on the current action, the impact of these issues are differently severe. Additional UI is definativly needed to handle conflicts.
Low impact. At least the element in question can be retrieved from the server. It is unimportant if this is only one event or if the whole calendar file has to be retrieved, as in the ICS Provider.
Low Impact. The Event can be added almost without problems. Providers that do not support editing or adding single events (i.e ICS) can refresh the whole calendar prior to adding the event. If the provider does not have a locking mechanism, this could create inevitable race conditions.
High Impact. If the event has changed since the last time it has been retrieved from the remote source, then there may be a conflict in how the event changed. If not that, then the difference between the local cache and the server copy could influence the users intention of editing the event. The most harmless case would be that the change has already been made by someone else.
Medium impact. Deleting the event is not a problem even if the local cache and the remote calendar are inconsistant, but the user's choice may be influenced by details on the updated event.
Offline mode support
In this model, a larger part of the calendar needs to be cached similar to how it is described above. Additionally, it is not sufficient to use a memory calendar as the underlying cache. A storage calendar has to be used instead so changes can be held over a restart.
Furthermore, it is essential to mark changes made while in offline mode to keep the amount of needed syncronization low. That way only events that were modified need to be considered, in contrast to every event in the calendar being compared to its remote version.
With respect to an offline mode, the Issues described above will occur much more often and more visible to the user. Especially when the user goes back online, changes that were made when the user was offline need to be fully syncronized with the calendar.
Also, to maximize offline capabilities the full calendar needs to be downloaded. This implicates a high performance hit and could make the user impatient since the UI will not change in this time.
Another aspect may be that some providers can not easily get all events from the remote source (i.e caldav)
Order of Implementation
Regarding user experience, it would be better to implement offline support first and then add specific ranged caching aspects to that implementation. This has the advantage that it is much more evident to the user than some "simple" speedups. However, implementing the ranged caching first might produce a cleaner implementation on which it is easier to build offline support.
Regarding Offline support, the calendar can be forced into readonly mode at first, until a full syncronization of changes made while offline is available.
Possible Implementation Strategies
(Some thoughts about the implementation follow)
A ranged based cache can be implemented in different ways:
1) In interface that's a cache store, where providers can store results after they got the items from the remote calendar, and where the calendar can try to get items for a new query before asking the real remote store.
2) A wrapper around a provider. The wrapper would implement calICalendar, and would store results itself, and use this cache when it makes sense.
The implementation of this range based cache needs a way to know which timerange (and other query parameters) a certain result set belong to. Then it needs a way to find out if it already has the result for a new query. That new query must have the same parameters, and the timeblock must be a subset of the stored timeblock.