Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CalDAV/CardDAV: put every method from backends that does multiple DB calls in transactions #36528

Merged
merged 2 commits into from
Apr 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 47 additions & 5 deletions apps/dav/lib/CalDAV/CalDavBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ public function getDeletedCalendars(int $deletedBefore): array {
* @return array
*/
public function getCalendarsForUser($principalUri) {
return $this->atomic(function () use ($principalUri) {
$principalUriOriginal = $principalUri;
$principalUri = $this->convertPrincipal($principalUri, true);
$fields = array_column($this->propertyMap, 0);
Expand Down Expand Up @@ -441,6 +442,7 @@ public function getCalendarsForUser($principalUri) {
$result->closeCursor();

return array_values($calendars);
}, $this->db);
}

/**
Expand Down Expand Up @@ -830,6 +832,7 @@ public function createCalendar($principalUri, $calendarUri, array $properties) {
* @return void
*/
public function updateCalendar($calendarId, PropPatch $propPatch) {
$this->atomic(function () use ($calendarId, $propPatch) {
$supportedProperties = array_keys($this->propertyMap);
$supportedProperties[] = '{' . Plugin::NS_CALDAV . '}schedule-calendar-transp';

Expand Down Expand Up @@ -863,6 +866,7 @@ public function updateCalendar($calendarId, PropPatch $propPatch) {

return true;
});
}, $this->db);
}

/**
Expand All @@ -872,6 +876,7 @@ public function updateCalendar($calendarId, PropPatch $propPatch) {
* @return void
*/
public function deleteCalendar($calendarId, bool $forceDeletePermanently = false) {
$this->atomic(function () use ($calendarId, $forceDeletePermanently) {
// The calendar is deleted right away if this is either enforced by the caller
// or the special contacts birthday calendar or when the preference of an empty
// retention (0 seconds) is set, which signals a disabled trashbin.
Expand Down Expand Up @@ -928,9 +933,11 @@ public function deleteCalendar($calendarId, bool $forceDeletePermanently = false
));
}
}
}, $this->db);
}

public function restoreCalendar(int $id): void {
$this->atomic(function () use ($id) {
$qb = $this->db->getQueryBuilder();
$update = $qb->update('calendars')
->set('deleted_at', $qb->createNamedParameter(null))
Expand All @@ -947,6 +954,7 @@ public function restoreCalendar(int $id): void {
$calendarData,
$shares
));
}, $this->db);
}

/**
Expand Down Expand Up @@ -1206,6 +1214,7 @@ public function getMultipleCalendarObjects($calendarId, array $uris, $calendarTy
public function createCalendarObject($calendarId, $objectUri, $calendarData, $calendarType = self::CALENDAR_TYPE_CALENDAR) {
$extraData = $this->getDenormalizedData($calendarData);

return $this->atomic(function () use ($calendarId, $objectUri, $calendarData, $extraData, $calendarType) {
// Try to detect duplicates
$qb = $this->db->getQueryBuilder();
$qb->select($qb->func()->count('*'))
Expand Down Expand Up @@ -1274,6 +1283,7 @@ public function createCalendarObject($calendarId, $objectUri, $calendarData, $ca
}

return '"' . $extraData['etag'] . '"';
}, $this->db);
}

/**
Expand All @@ -1297,6 +1307,8 @@ public function createCalendarObject($calendarId, $objectUri, $calendarData, $ca
*/
public function updateCalendarObject($calendarId, $objectUri, $calendarData, $calendarType = self::CALENDAR_TYPE_CALENDAR) {
$extraData = $this->getDenormalizedData($calendarData);

return $this->atomic(function () use ($calendarId, $objectUri, $calendarData, $extraData, $calendarType) {
$query = $this->db->getQueryBuilder();
$query->update('calendarobjects')
->set('calendardata', $query->createNamedParameter($calendarData, IQueryBuilder::PARAM_LOB))
Expand Down Expand Up @@ -1331,6 +1343,7 @@ public function updateCalendarObject($calendarId, $objectUri, $calendarData, $ca
}

return '"' . $extraData['etag'] . '"';
}, $this->db);
}

/**
Expand All @@ -1346,6 +1359,7 @@ public function updateCalendarObject($calendarId, $objectUri, $calendarData, $ca
* @throws Exception
*/
public function moveCalendarObject(int $sourceCalendarId, int $targetCalendarId, int $objectId, string $oldPrincipalUri, string $newPrincipalUri, int $calendarType = self::CALENDAR_TYPE_CALENDAR): bool {
return $this->atomic(function () use ($sourceCalendarId, $targetCalendarId, $objectId, $oldPrincipalUri, $newPrincipalUri, $calendarType) {
$object = $this->getCalendarObjectById($oldPrincipalUri, $objectId);
if (empty($object)) {
return false;
Expand Down Expand Up @@ -1383,6 +1397,7 @@ public function moveCalendarObject(int $sourceCalendarId, int $targetCalendarId,
$this->dispatcher->dispatchTyped(new CalendarObjectMovedEvent($sourceCalendarId, $sourceCalendarRow, $targetCalendarId, $targetCalendarRow, $sourceShares, $targetShares, $object));
}
return true;
}, $this->db);
}


Expand Down Expand Up @@ -1415,6 +1430,7 @@ public function setClassification($calendarObjectId, $classification) {
* @return void
*/
public function deleteCalendarObject($calendarId, $objectUri, $calendarType = self::CALENDAR_TYPE_CALENDAR, bool $forceDeletePermanently = false) {
$this->atomic(function () use ($calendarId, $objectUri, $calendarType, $forceDeletePermanently) {
$data = $this->getCalendarObject($calendarId, $objectUri, $calendarType);

if ($data === null) {
Expand Down Expand Up @@ -1486,6 +1502,7 @@ public function deleteCalendarObject($calendarId, $objectUri, $calendarType = se
}

$this->addChange($calendarId, $objectUri, 3, $calendarType);
}, $this->db);
}

/**
Expand All @@ -1494,6 +1511,7 @@ public function deleteCalendarObject($calendarId, $objectUri, $calendarType = se
* @throws Forbidden
*/
public function restoreCalendarObject(array $objectData): void {
$this->atomic(function () use ($objectData) {
$id = (int) $objectData['id'];
$restoreUri = str_replace("-deleted.ics", ".ics", $objectData['uri']);
$targetObject = $this->getCalendarObject(
Expand Down Expand Up @@ -1538,6 +1556,7 @@ public function restoreCalendarObject(array $objectData): void {
$row
)
);
}, $this->db);
}

/**
Expand Down Expand Up @@ -1686,6 +1705,7 @@ public function calendarQuery($calendarId, array $filters, $calendarType = self:
* @return array
*/
public function calendarSearch($principalUri, array $filters, $limit = null, $offset = null) {
return $this->atomic(function () use ($principalUri, $filters, $limit, $offset) {
$calendars = $this->getCalendarsForUser($principalUri);
$ownCalendars = [];
$sharedCalendars = [];
Expand Down Expand Up @@ -1798,6 +1818,7 @@ public function calendarSearch($principalUri, array $filters, $limit = null, $of
}

return $result;
}, $this->db);
}

/**
Expand Down Expand Up @@ -2022,6 +2043,7 @@ public function searchPrincipalUri(string $principalUri,
array $searchProperties,
array $searchParameters,
array $options = []): array {
return $this->atomic(function () use ($principalUri, $pattern, $componentTypes, $searchProperties, $searchParameters, $options) {
$escapePattern = !\array_key_exists('escape_like_param', $options) || $options['escape_like_param'] !== false;

$calendarObjectIdQuery = $this->db->getQueryBuilder();
Expand Down Expand Up @@ -2126,6 +2148,7 @@ public function searchPrincipalUri(string $principalUri,

return $array;
}, $calendarObjects);
}, $this->db);
}

/**
Expand Down Expand Up @@ -2254,6 +2277,7 @@ public function getCalendarObjectById(string $principalUri, int $id): ?array {
* @return array
*/
public function getChangesForCalendar($calendarId, $syncToken, $syncLevel, $limit = null, $calendarType = self::CALENDAR_TYPE_CALENDAR) {
return $this->atomic(function () use ($calendarId, $syncToken, $syncLevel, $limit, $calendarType) {
// Current synctoken
$qb = $this->db->getQueryBuilder();
$qb->select('synctoken')
Expand Down Expand Up @@ -2332,6 +2356,7 @@ public function getChangesForCalendar($calendarId, $syncToken, $syncLevel, $limi
$stmt->closeCursor();
}
return $result;
}, $this->db);
}

/**
Expand Down Expand Up @@ -2473,6 +2498,7 @@ public function createSubscription($principalUri, $uri, array $properties) {
* @return void
*/
public function updateSubscription($subscriptionId, PropPatch $propPatch) {
$this->atomic(function () use ($subscriptionId, $propPatch) {
$supportedProperties = array_keys($this->subscriptionPropertyMap);
$supportedProperties[] = '{http://calendarserver.org/ns/}source';

Expand Down Expand Up @@ -2502,6 +2528,7 @@ public function updateSubscription($subscriptionId, PropPatch $propPatch) {

return true;
});
}, $this->db);
}

/**
Expand All @@ -2511,6 +2538,7 @@ public function updateSubscription($subscriptionId, PropPatch $propPatch) {
* @return void
*/
public function deleteSubscription($subscriptionId) {
$this->atomic(function () use ($subscriptionId) {
$subscriptionRow = $this->getSubscriptionById($subscriptionId);

$query = $this->db->getQueryBuilder();
Expand All @@ -2537,6 +2565,7 @@ public function deleteSubscription($subscriptionId) {
if ($subscriptionRow) {
$this->dispatcher->dispatchTyped(new SubscriptionDeletedEvent((int)$subscriptionId, $subscriptionRow, []));
}
}, $this->db);
}

/**
Expand Down Expand Up @@ -2657,9 +2686,10 @@ public function createSchedulingObject($principalUri, $objectUri, $objectData) {
* @param int $calendarType
* @return void
*/
protected function addChange($calendarId, $objectUri, $operation, $calendarType = self::CALENDAR_TYPE_CALENDAR) {
protected function addChange(int $calendarId, string $objectUri, int $operation, int $calendarType = self::CALENDAR_TYPE_CALENDAR): void {
$table = $calendarType === self::CALENDAR_TYPE_CALENDAR ? 'calendars': 'calendarsubscriptions';

$this->atomic(function () use ($calendarId, $objectUri, $operation, $calendarType, $table) {
$query = $this->db->getQueryBuilder();
$query->select('synctoken')
->from($table)
Expand All @@ -2679,10 +2709,12 @@ protected function addChange($calendarId, $objectUri, $operation, $calendarType
])
->executeStatement();

$stmt = $this->db->prepare("UPDATE `*PREFIX*$table` SET `synctoken` = `synctoken` + 1 WHERE `id` = ?");
$stmt->execute([
$calendarId
]);
$query = $this->db->getQueryBuilder();
$query->update($table)
->set('synctoken', $query->createNamedParameter($syncToken + 1, IQueryBuilder::PARAM_INT))
->where($query->expr()->eq('id', $query->createNamedParameter($calendarId)))
->executeStatement();
}, $this->db);
}

/**
Expand Down Expand Up @@ -2805,6 +2837,7 @@ private function readBlob($cardData) {
* @param list<string> $remove
*/
public function updateShares(IShareable $shareable, array $add, array $remove): void {
$this->atomic(function () use ($shareable, $add, $remove) {
$calendarId = $shareable->getResourceId();
$calendarRow = $this->getCalendarById($calendarId);
if ($calendarRow === null) {
Expand All @@ -2815,6 +2848,7 @@ public function updateShares(IShareable $shareable, array $add, array $remove):
$this->calendarSharingBackend->updateShares($shareable, $add, $remove);

$this->dispatcher->dispatchTyped(new CalendarShareUpdatedEvent($calendarId, $calendarRow, $oldShares, $add, $remove));
}, $this->db);
}

/**
Expand All @@ -2830,6 +2864,7 @@ public function getShares(int $resourceId): array {
* @return string|null
*/
public function setPublishStatus($value, $calendar) {
return $this->atomic(function () use ($value, $calendar) {
$calendarId = $calendar->getResourceId();
$calendarData = $this->getCalendarById($calendarId);

Expand All @@ -2856,6 +2891,7 @@ public function setPublishStatus($value, $calendar) {

$this->dispatcher->dispatchTyped(new CalendarUnpublishedEvent($calendarId, $calendarData));
return null;
}, $this->db);
}

/**
Expand Down Expand Up @@ -2893,6 +2929,7 @@ public function applyShareAcl(int $resourceId, array $acl): array {
* @param int $calendarType
*/
public function updateProperties($calendarId, $objectUri, $calendarData, $calendarType = self::CALENDAR_TYPE_CALENDAR) {
$this->atomic(function () use ($calendarId, $objectUri, $calendarData, $calendarType) {
$objectId = $this->getCalendarObjectId($calendarId, $objectUri, $calendarType);

try {
Expand Down Expand Up @@ -2957,12 +2994,14 @@ public function updateProperties($calendarId, $objectUri, $calendarData, $calend
}
}
}
}, $this->db);
}

/**
* deletes all birthday calendars
*/
public function deleteAllBirthdayCalendars() {
$this->atomic(function () {
$query = $this->db->getQueryBuilder();
$result = $query->select(['id'])->from('calendars')
->where($query->expr()->eq('uri', $query->createNamedParameter(BirthdayService::BIRTHDAY_CALENDAR_URI)))
Expand All @@ -2976,12 +3015,14 @@ public function deleteAllBirthdayCalendars() {
true // No data to keep in the trashbin, if the user re-enables then we regenerate
);
}
}, $this->db);
}

/**
* @param $subscriptionId
*/
public function purgeAllCachedEventsForSubscription($subscriptionId) {
$this->atomic(function () use ($subscriptionId) {
$query = $this->db->getQueryBuilder();
$query->select('uri')
->from('calendarobjects')
Expand Down Expand Up @@ -3014,6 +3055,7 @@ public function purgeAllCachedEventsForSubscription($subscriptionId) {
foreach ($uris as $uri) {
$this->addChange($subscriptionId, $uri, 3, self::CALENDAR_TYPE_SUBSCRIPTION);
}
}, $this->db);
}

/**
Expand Down
Loading