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; $this->events[$id] = $master;
} }
else if (is_array($master['recurrence'])) { 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 $start Start date of the recurrence window
* @param DateTime $end End 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 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 * @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']; $object = $event['_formatobj'];
if (!$object) { 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 // use libkolab to compute recurring events
$recurrence = new kolab_date_recurrence($object); $recurrence = new kolab_date_recurrence($object);
@ -713,6 +723,10 @@ class kolab_calendar extends kolab_storage_folder_api
$this->events[$rec_id] = $rec_event; $this->events[$rec_id] = $rec_event;
break; break;
} }
if ($limit && count($events) >= $limit) {
return $events;
}
} }
else if ($next_event['start'] > $end) // stop loop if out of range else if ($next_event['start'] > $end) // stop loop if out of range
break; break;

View file

@ -819,7 +819,7 @@ class kolab_driver extends calendar_driver
// removing the first instance => just move to next occurence // removing the first instance => just move to next occurence
if ($master['recurrence'] && $event['_instance'] == libcalendaring::recurrence_instance_identifier($master)) { 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) // no future instances found: delete the master event (bug #1677)
if (!$recurring['start']) { if (!$recurring['start']) {