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

fix: (CalDav) Delete invitation link when deleting Calendars or Events #47832

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

SebastianKrupinski
Copy link
Contributor

Summary

When deleting a calendar or event also delete event invitation links

*
* @param int $calendarId
*/
protected function purgeCalendarInvitations(int $calendarId) {

Check notice

Code scanning / Psalm

MissingReturnType

Method OCA\DAV\CalDAV\CalDavBackend::purgeCalendarInvitations does not have a return type, expecting void
*
* @param string $eventId UID of the event
*/
protected function purgeObjectInvitations(string $eventId) {

Check notice

Code scanning / Psalm

MissingReturnType

Method OCA\DAV\CalDAV\CalDavBackend::purgeObjectInvitations does not have a return type, expecting void
Copy link
Member

@tcitworld tcitworld left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need a repair step to purge all entries in calendar_invitations which don't match existing calendar objects.

// delete all links that match object uid's
$cmd2 = $this->db->getQueryBuilder();
$cmd2->delete($this->dbObjectInvitationsTable)
->where($cmd2->expr()->in('uid', new Literal($cmd1->getSQL())))
Copy link
Member

@tcitworld tcitworld Sep 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this explode on Oracle if there's a lot of events for the calendar?

$exception = new QueryException('More than 1000 expressions in a list are not allowed on Oracle.');

Ah no, it's raw SQL being passed.

Maybe a join between tables is better here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Morning, if that is the case with Oracle then yes this will need to get reworked.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like join delete will not work... due to lack of alias support in DBAL.

We would need to execute something like this...

DELETE i
FROM oc_calendar_invitations i
INNER JOIN oc_calendarobjects o ON o.uid = i.uid
WHERE o.calendarid = 3432

And DBAL does not support DELETE i FROM...
https://github.com/doctrine/dbal/blob/7a8252418689feb860ea8dfeab66d64a56a64df8/src/Connection.php#L392

So our options are...

  1. Using a raw sql statement (probably the most efficient)
  2. Extending our DBAL implementation to support aliases and using a join (not sure this will really fly)
  3. Pulling the UID's from CalendarObjects, splitting them up in chunks of 1k or smaller, and executing a "where in" on each chunk.

Lets have @ChristophWurst weigh in on this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The raw SQL statement sounds the best then.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SELECT, chunk and DELETE like nextcloud/mail#9761

@miaulalala
Copy link
Contributor

We also need a repair step to purge all entries in calendar_invitations which don't match existing calendar objects.

Set the expiration date for those outdated links to in the past, and the CleanupInvitationTokenJob will take care of it.

https://github.com/nextcloud/server/blob/af6de04e9e141466dc229e444ff3f146f4a34765/apps/dav/lib/BackgroundJob/CleanupInvitationTokenJob.php

It will probably need modifications like

protected function run($argument): void {
$time = $this->time->getTime() - (60 * 60);
$this->calDavBackend->deleteOutdatedSchedulingObjects($time, 50000);
$this->logger->info('Removed outdated scheduling objects');
}

as to not completely crash an instance until all outdated links are deleted.

Would be a good idea to get some data from our instance too to see how many of these links exist in our database. Please ask the sysadmins to run a query for you.

@tcitworld
Copy link
Member

In my production instance, with ~22k rows in oc_calendar_invitations and 22M rows in oc_calendarobjects, I get 2162 entries for

select count(i.id) from oc_calendar_invitations i left join oc_calendarobjects o on i.uid = o.uid where o.id is null;

@SebastianKrupinski
Copy link
Contributor Author

In my production instance, with ~22k rows in oc_calendar_invitations and 22M rows in oc_calendarobjects, I get 2162 entries for

22M rows! wow. Can you tell how many calendar object the biggest calendar has?

@tcitworld
Copy link
Member

Can you tell how many calendar object the biggest calendar has?

51k objects

Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com>
Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com>
Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3. to review Waiting for reviews
Projects
Status: 🏗️ In progress
Development

Successfully merging this pull request may close these issues.

When a calendar event is deleted, corresponding calendar_invitation entries are not deleted
4 participants