Skip to content

Commit

Permalink
fix(dav): Reduce CalDAV backend memory footprint
Browse files Browse the repository at this point in the history
fetchAll inflates memory. Fetching in a loop allows GC to run earlier
and more often.

Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
  • Loading branch information
ChristophWurst authored and backportbot-nextcloud[bot] committed Nov 2, 2023
1 parent 34acba0 commit 442845b
Showing 1 changed file with 34 additions and 30 deletions.
64 changes: 34 additions & 30 deletions apps/dav/lib/CalDAV/CalDavBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -281,14 +281,15 @@ public function getDeletedCalendars(int $deletedBefore): array {
->where($qb->expr()->isNotNull('deleted_at'))
->andWhere($qb->expr()->lt('deleted_at', $qb->createNamedParameter($deletedBefore)));
$result = $qb->executeQuery();
$raw = $result->fetchAll();
$result->closeCursor();
return array_map(function ($row) {
return [
$calendars = [];
while (($row = $result->fetch()) !== false) {
$calendars[] = [
'id' => (int) $row['id'],
'deleted_at' => (int) $row['deleted_at'],
];
}, $raw);
}
$result->closeCursor();
return $calendars;
}

/**
Expand Down Expand Up @@ -1011,7 +1012,7 @@ public function getCalendarObjects($calendarId, $calendarType = self::CALENDAR_T
$stmt = $query->executeQuery();

$result = [];
foreach ($stmt->fetchAll() as $row) {
while (($row = $stmt->fetch()) !== false) {
$result[] = [
'id' => $row['id'],
'uri' => $row['uri'],
Expand All @@ -1038,7 +1039,7 @@ public function getDeletedCalendarObjects(int $deletedBefore): array {
$stmt = $query->executeQuery();

$result = [];
foreach ($stmt->fetchAll() as $row) {
while (($row = $stmt->fetch()) !== false) {
$result[] = [
'id' => $row['id'],
'uri' => $row['uri'],
Expand Down Expand Up @@ -1925,13 +1926,15 @@ public function search(array $calendarInfo, $pattern, array $searchProperties,
}

$result = $outerQuery->executeQuery();
$calendarObjects = array_filter($result->fetchAll(), function (array $row) use ($options) {
$calendarObjects = [];
while (($row = $result->fetch()) !== false) {
$start = $options['timerange']['start'] ?? null;
$end = $options['timerange']['end'] ?? null;

if ($start === null || !($start instanceof DateTimeInterface) || $end === null || !($end instanceof DateTimeInterface)) {
// No filter required
return true;
$calendarObjects[] = $row;
continue;
}

$isValid = $this->validateFilterForObject($row, [
Expand All @@ -1956,8 +1959,10 @@ public function search(array $calendarInfo, $pattern, array $searchProperties,
// Put the stream back to the beginning so it can be read another time
rewind($row['calendardata']);
}
return $isValid;
});
if ($isValid) {
$calendarObjects[] = $row;
}
}
$result->closeCursor();

return array_map(function ($o) use ($options) {
Expand Down Expand Up @@ -2157,28 +2162,28 @@ public function searchPrincipalUri(string $principalUri,
}

$result = $calendarObjectIdQuery->executeQuery();
$matches = $result->fetchAll();
$matches = [];
while (($row = $result->fetch()) !== false) {
$matches[] = (int) $row['objectid'];
}
$result->closeCursor();
$matches = array_map(static function (array $match):int {
return (int) $match['objectid'];
}, $matches);

$query = $this->db->getQueryBuilder();
$query->select('calendardata', 'uri', 'calendarid', 'calendartype')
->from('calendarobjects')
->where($query->expr()->in('id', $query->createNamedParameter($matches, IQueryBuilder::PARAM_INT_ARRAY)));

$result = $query->executeQuery();
$calendarObjects = $result->fetchAll();
$result->closeCursor();

return array_map(function (array $array): array {
$calendarObjects = [];
while (($array = $result->fetch()) !== false) {
$array['calendarid'] = (int)$array['calendarid'];
$array['calendartype'] = (int)$array['calendartype'];
$array['calendardata'] = $this->readBlob($array['calendardata']);

return $array;
}, $calendarObjects);
$calendarObjects[] = $array;
}
$result->closeCursor();
return $calendarObjects;
}, $this->db);
}

Expand Down Expand Up @@ -2656,9 +2661,9 @@ public function getSchedulingObjects($principalUri) {
->where($query->expr()->eq('principaluri', $query->createNamedParameter($principalUri)))
->executeQuery();

$result = [];
foreach ($stmt->fetchAll() as $row) {
$result[] = [
$results = [];
while (($row = $stmt->fetch()) !== false) {
$results[] = [
'calendardata' => $row['calendardata'],
'uri' => $row['uri'],
'lastmodified' => $row['lastmodified'],
Expand All @@ -2668,7 +2673,7 @@ public function getSchedulingObjects($principalUri) {
}
$stmt->closeCursor();

return $result;
return $results;
}

/**
Expand Down Expand Up @@ -3046,14 +3051,13 @@ public function deleteAllBirthdayCalendars() {
->where($query->expr()->eq('uri', $query->createNamedParameter(BirthdayService::BIRTHDAY_CALENDAR_URI)))
->executeQuery();

$ids = $result->fetchAll();
$result->closeCursor();
foreach ($ids as $id) {
while (($row = $result->fetch()) !== false) {
$this->deleteCalendar(
$id['id'],
$row['id'],
true // No data to keep in the trashbin, if the user re-enables then we regenerate
);
}
$result->closeCursor();
}, $this->db);
}

Expand All @@ -3070,7 +3074,7 @@ public function purgeAllCachedEventsForSubscription($subscriptionId) {
$stmt = $query->executeQuery();

$uris = [];
foreach ($stmt->fetchAll() as $row) {
while (($row = $stmt->fetch()) !== false) {
$uris[] = $row['uri'];
}
$stmt->closeCursor();
Expand Down

0 comments on commit 442845b

Please sign in to comment.