[Kolab-devel] Caching in Roundcube's libkolabxml storage layer
Thomas Brüderli
bruederli at kolabsys.com
Tue Apr 3 18:34:49 CEST 2012
Hello devs
Since server side akonadi most likely won't make it into the Kolab 3.0
release we have to build our own caching engine to improve access speed
for Kolab objects in Roundcube. The initial plan was to delegate
reading, caching and synching Kolab objects to a server side akonadi
instance and keep things it rather simple on the Roundcube side. In
previous versions we used the entire Horde stack to fetch, cache, read
and write Kolab groupware objects with all it's known downsides. Now
that reading and writing Kolab 3 objects using the libkolabxml PHP
bindings basically works, it's time to get our heads into caching in
order to speed up the listing of contacts, events and such.
Let me start with a short explanation of the new libkolabxml storage
layer we've created in Roundcube. This is how one can list all contacts
from an annotated IMAP folder:
$folders = kolab_storage::get_folders('contact');
$folder = $folders[0]; // instance of kolab_storage_folder class;
foreach ($folder->get_objects() as $contact) {
// $contact is a hash array containing contact properties
// which are relevant in Roundcube
echo $contact['uid'] . "\t" . $contact['name'] . "\n";
}
Fetching a contact by its UID and updating it is pretty simple, too:
$contact = $folder->get_object('<some-uid>');
$contact['name'] = 'John Doe';
$folder->save($contact);
Without a specific caching in place, the following procedure is executed
when reading a contact:
kolab_storage::get_folders()
(1) List all IMAP folders with their metadata and post-filter the list
kolab_storage_folder:get_objects()
(2a) List all messages of a particular IMAP folder or
(2b) search messages by HEADER X-Kolab-Type ...
For each of the returned messages or when calling
kolab_storage_folder:get_object(<uid>) directly, the following happens:
(3) Fetch bodystructure, parse it and find XML part.
(4) Fetch the XML part from IMAP and parse it with libkolabxml
(5) Load object data into a hash array by calling dozens of getter
methods of the Contact/Event/DistributionList class.
(6) Compute repeated instances of recurring events
While caching of (1), (2a) and (3) is already provided by the Roundcube
core IMAP library (if enabled by config), we now have to implement a
caching layer for (4) and (5) and optionally for (6). Also caching for
(2x) could be replaced with a more kolab-specific cache which would
allow one to select ranges of objects (e.g. events from..to) or even
fulltext searches. I'd strongly recommend to also cache the interpreted
object data in addition to the raw XML block because reading from
libkolabxml involves plenty of function calls which are known to be
rather expensive in PHP.
So here's my proposition for a Kolab object cache data structure:
FOLDER: <fully qualified IAMAP folder URI> // example: [1]
MSGUID: <IMAP message UID> // used for synchronizing
EXPIRE: <date-time> // expiration timestamp
UID: <object UID>
TYPE: <object type> // contact/event/distribution-list/etc.
DATA: <serialized object data>
XML: <raw xml block>
DTSTART: <date-time> // event start (empty for other types)
DTEND: <date-time> // event end
TAGS: <object specific keywords used for filtering>
[1] imap://bruederli%40kolab.cc@mail.kolab.cc/INBOX/Contacts
This structure can easily be reflected in a SQL database. If it's a
requirement to have different caching backends such as db, memcache,
file-based, etc. things become slightly more complicated but still
doable. Is it?
Using full IMAP URIs would make it possible to re-use the cache of a
shared folder for multiple users who have access to that folder.
Together with the MSGUID the cache table can be synchronized with the
message index consumed from either the IMAP server or from the Roundcube
internal IMAP index cache.
I intend to implement the caching layer in a transparent way into
kolab_storage and making it configurable, similar to the current IMAP
cache implementation in Roundcube.
Any comments or suggestions are welcome!
Regards,
Thomas
More information about the devel
mailing list