Fix performance/memory errors when editing recurring events

When we indeed need to find only a specific event occurrence, make the
recurrence loop return asap, instead of looping over all possible
occurrences in 100 years and returning all of them.
This commit is contained in:
Aleksander Machniak 2018-12-13 09:50:41 +00:00
parent 39fbf99978
commit 779af09a68
2 changed files with 17 additions and 3 deletions

View file

@ -214,7 +214,12 @@ class kolab_calendar extends kolab_storage_folder_api
$this->events[$id] = $master;
}
else if (is_array($master['recurrence'])) {
$this->get_recurring_events($record, $master['start'], null, $id);
// For performance reasons we'll get only the specific instance
if (($date = substr($id, strlen($master_id) + 1, 8)) && strlen($date) == 8 && is_numeric($date)) {
$start_date = new DateTime($date . 'T000000', $master['start']->getTimezone());
}
$this->get_recurring_events($record, $start_date ?: $master['start'], null, $id, 1);
}
}
}
@ -597,10 +602,11 @@ class kolab_calendar extends kolab_storage_folder_api
* @param DateTime $start Start date of the recurrence window
* @param DateTime $end End date of the recurrence window
* @param string $event_id ID of a specific recurring event instance
* @param int $limit Max. number of instances to return
*
* @return array List of recurring event instances
*/
public function get_recurring_events($event, $start, $end = null, $event_id = null)
public function get_recurring_events($event, $start, $end = null, $event_id = null, $limit = null)
{
$object = $event['_formatobj'];
if (!$object) {
@ -669,6 +675,10 @@ class kolab_calendar extends kolab_storage_folder_api
}
}
if ($limit && count($events) >= $limit) {
return $events;
}
// use libkolab to compute recurring events
$recurrence = new kolab_date_recurrence($object);
@ -713,6 +723,10 @@ class kolab_calendar extends kolab_storage_folder_api
$this->events[$rec_id] = $rec_event;
break;
}
if ($limit && count($events) >= $limit) {
return $events;
}
}
else if ($next_event['start'] > $end) // stop loop if out of range
break;

View file

@ -819,7 +819,7 @@ class kolab_driver extends calendar_driver
// removing the first instance => just move to next occurence
if ($master['recurrence'] && $event['_instance'] == libcalendaring::recurrence_instance_identifier($master)) {
$recurring = reset($storage->get_recurring_events($event, $event['start'], null, $event['id'].'-1'));
$recurring = reset($storage->get_recurring_events($event, $event['start'], null, $event['id'] . '-1', 1));
// no future instances found: delete the master event (bug #1677)
if (!$recurring['start']) {