Hi,
I've been reading the IMAP specification to find ways to improve current
rcube cache algorithms. The following is from the IMAPv4 specs:
2.3.1.2. Message Sequence Number Message Attribute
A relative position from 1 to the number of messages in the mailbox.
This position MUST be ordered by ascending unique identifier. As
each new message is added, it is assigned a message sequence number
that is 1 higher than the number of messages in the mailbox before
that new message was added.
Currently rcube stores the whole header list for each mailbox in the DB.
If the current message count is bigger than the message count of the
cache then it fetches the whole header list again and stores it in the
cache on DB.
I think this could be improved by redesigning the caching algorithm,
since each new message in a mailbox is given a sequence number higher
than the other ones, we can just fetch the new messages. The following
code should clarify the idea:
$mbox_count = messagecount($mbox);
$cache_count = count($cache);
if ($mbox_count > $cache_count) {
$newMessages = iil_C_FetchHeaders( $conn, $mbox,
"$cache_count:$mbox_count" );
$cache = array_merge( $cache, $newMessages );
}
Unfortunatly the specs also say:
Message sequence numbers can be reassigned during the session. For
example, when a message is permanently removed (expunged) from the
mailbox, the message sequence number for all subsequent messages is
decremented. The number of messages in the mailbox is also
decremented. Similarly, a new message can be assigned a message
sequence number that was once held by some other message prior to an
expunge.
We can solve this however since we have the UID of each header in the
cache. Instead of fetching the (mbox_count - cache_count) headers, we
can fetch (mbox_count-cache_count)+1, with this we should get as the
first header the last one in the cache. We then compare its UID, so if
we have in the cache the last header with id=269 and uid=468 but in the
new list it has the id=269 but the uid=493 it means that there have been
deleted messages in that folder and that we must revalidate the whole list.
This could also be optimized but it'll require a quite complex algorithm
which I guess is not worth it for most cases.
The following pseudo-code should show the idea good enough:
$mbox_count = messagecount($mbox);
$cache_count = count($cache);
if ($mbox_count > $cache_count) {
$newMessages = iil_C_FetchHeaders( $conn, $mbox,
($cache_count-1).":$mbox_count" );
if ($newMessages[0]->uid != end($cache)->uid) {
//revalidate the cache
$cache = iil_C_FetchHeaders( $conn, $mbox, "0:".($cache_count-1));
}
$cache = array_merge( $cache, $newMessages );
}
The code I think is simple enough although I would like to discuss this
before trying its implementation, I'm worried about the specs support in
different servers.
ciao,
ivan