Performance: Get event-to-mail relations once per events list, instead of doing SELECT for every event (including recurrences)

This commit is contained in:
Aleksander Machniak 2016-02-21 19:09:04 +01:00
parent 922d8de6d0
commit d96689620f
4 changed files with 26 additions and 20 deletions

View file

@ -1744,15 +1744,6 @@ class calendar extends rcube_plugin
$event['attachments'][$k]['classname'] = rcube_utils::file2class($attachment['mimetype'], $attachment['name']); $event['attachments'][$k]['classname'] = rcube_utils::file2class($attachment['mimetype'], $attachment['name']);
} }
// convert link URIs references into structs
if (array_key_exists('links', $event)) {
foreach ((array)$event['links'] as $i => $link) {
if (strpos($link, 'imap://') === 0 && ($msgref = $this->driver->get_message_reference($link))) {
$event['links'][$i] = $msgref;
}
}
}
// check for organizer in attendees list // check for organizer in attendees list
$organizer = null; $organizer = null;
foreach ((array)$event['attendees'] as $i => $attendee) { foreach ((array)$event['attendees'] as $i => $attendee) {

View file

@ -298,13 +298,13 @@ class kolab_calendar extends kolab_storage_folder_api
$events = array(); $events = array();
foreach ($this->storage->select($query) as $record) { foreach ($this->storage->select($query) as $record) {
$event = $this->_to_driver_event($record, !$virtual); $event = $this->_to_driver_event($record, !$virtual, false);
// remember seen categories // remember seen categories
if ($event['categories']) { if ($event['categories']) {
$cat = is_array($event['categories']) ? $event['categories'][0] : $event['categories']; $cat = is_array($event['categories']) ? $event['categories'][0] : $event['categories'];
$this->categories[$cat]++; $this->categories[$cat]++;
} }
// list events in requested time window // list events in requested time window
if ($event['start'] <= $end && $event['end'] >= $start) { if ($event['start'] <= $end && $event['end'] >= $start) {
@ -347,7 +347,7 @@ class kolab_calendar extends kolab_storage_folder_api
// add top-level exceptions (aka loose single occurrences) // add top-level exceptions (aka loose single occurrences)
else if (is_array($record['exceptions'])) { else if (is_array($record['exceptions'])) {
foreach ($record['exceptions'] as $ex) { foreach ($record['exceptions'] as $ex) {
$component = $this->_to_driver_event($ex); $component = $this->_to_driver_event($ex, false, false);
if ($component['start'] <= $end && $component['end'] >= $start) { if ($component['start'] <= $end && $component['end'] >= $start) {
$events[] = $component; $events[] = $component;
} }
@ -381,6 +381,10 @@ class kolab_calendar extends kolab_storage_folder_api
return true; return true;
}); });
// Apply event-to-mail relations
$config = kolab_storage_config::get_instance();
$config->apply_links($events, 'event');
// avoid session race conditions that will loose temporary subscriptions // avoid session race conditions that will loose temporary subscriptions
$this->cal->rc->session->nowrite = true; $this->cal->rc->session->nowrite = true;
@ -622,7 +626,7 @@ class kolab_calendar extends kolab_storage_folder_api
if (!$exception['_instance']) if (!$exception['_instance'])
$exception['_instance'] = libcalendaring::recurrence_instance_identifier($exception); $exception['_instance'] = libcalendaring::recurrence_instance_identifier($exception);
$rec_event = $this->_to_driver_event($exception); $rec_event = $this->_to_driver_event($exception, false, false);
$rec_event['id'] = $event['uid'] . '-' . $exception['_instance']; $rec_event['id'] = $event['uid'] . '-' . $exception['_instance'];
$rec_event['isexception'] = 1; $rec_event['isexception'] = 1;
@ -671,7 +675,7 @@ class kolab_calendar extends kolab_storage_folder_api
// add to output if in range // add to output if in range
$rec_id = $event['uid'] . '-' . $instance_id; $rec_id = $event['uid'] . '-' . $instance_id;
if (($next_event['start'] <= $end && $next_event['end'] >= $start) || ($event_id && $rec_id == $event_id)) { if (($next_event['start'] <= $end && $next_event['end'] >= $start) || ($event_id && $rec_id == $event_id)) {
$rec_event = $this->_to_driver_event($next_event); $rec_event = $this->_to_driver_event($next_event, false, false);
$rec_event['_instance'] = $instance_id; $rec_event['_instance'] = $instance_id;
$rec_event['_count'] = $i + 1; $rec_event['_count'] = $i + 1;
@ -703,10 +707,13 @@ class kolab_calendar extends kolab_storage_folder_api
/** /**
* Convert from Kolab_Format to internal representation * Convert from Kolab_Format to internal representation
*/ */
private function _to_driver_event($record, $noinst = false) private function _to_driver_event($record, $noinst = false, $links = true)
{ {
$record['calendar'] = $this->id; $record['calendar'] = $this->id;
$record['links'] = $this->get_links($record['uid']);
if ($links) {
$record['links'] = $this->get_links($record['uid']);
}
if ($this->get_namespace() == 'other') { if ($this->get_namespace() == 'other') {
$record['className'] = 'fc-event-ns-other'; $record['className'] = 'fc-event-ns-other';

View file

@ -608,10 +608,15 @@ class kolab_storage_config
// get list of object UIDs and UIRs map // get list of object UIDs and UIRs map
foreach ($records as $i => $rec) { foreach ($records as $i => $rec) {
$uids[] = $rec['uid']; $uids[] = $rec['uid'];
$ids[self::build_member_url($rec['uid'])] = $i; // there can be many objects with the same uid (recurring events)
$ids[self::build_member_url($rec['uid'])][] = $i;
$records[$i]['links'] = array(); $records[$i]['links'] = array();
} }
if (!empty($uids)) {
$uids = array_unique($uids);
}
// The whole story here is to not do SELECT for every object. // The whole story here is to not do SELECT for every object.
// We'll build one SELECT for many (limit above) objects at once // We'll build one SELECT for many (limit above) objects at once
@ -645,14 +650,17 @@ class kolab_storage_config
$members = array(); $members = array();
foreach ((array) $relation['members'] as $member) { foreach ((array) $relation['members'] as $member) {
if (strpos($member, 'imap://') === 0) { if (strpos($member, 'imap://') === 0) {
$members[$member] = kolab_storage_config::get_message_reference($link, $type) ?: array('uri' => $link); $members[$member] = kolab_storage_config::get_message_reference($member, $type) ?: array('uri' => $member);
} }
} }
$members = array_values($members);
// assign links to objects // assign links to objects
foreach ((array) $relation['members'] as $member) { foreach ((array) $relation['members'] as $member) {
if (($id = $ids[$member]) !== null) { if (($id = $ids[$member]) !== null) {
$records[$id]['links'] = array_unique(array_merge($records[$id]['links'], $members)); foreach ($id as $i) {
$records[$i]['links'] = array_unique(array_merge($records[$i]['links'], $members));
}
} }
} }
} }

View file

@ -598,7 +598,7 @@ class tasklist_kolab_driver extends tasklist_driver
} }
$config->apply_tags($results); $config->apply_tags($results);
$config->apply_links($results); $config->apply_links($results, 'task');
foreach (array_keys($results) as $idx) { foreach (array_keys($results) as $idx) {
$results[$idx] = $this->_to_rcube_task($results[$idx], $results[$idx]['list_id']); $results[$idx] = $this->_to_rcube_task($results[$idx], $results[$idx]['list_id']);