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 fix search with limit and time range #45222

Merged
merged 2 commits into from
May 29, 2024

Conversation

kesselb
Copy link
Contributor

@kesselb kesselb commented May 7, 2024

Summary

Event recurrences are evaluated at runtime because the database only knows the first and last occurrence.

Given, a user created 8 events with a yearly reoccurrence and two for events tomorrow.
The upcoming event widget asks the CalDAV backend for 7 events within the next 14 days.

If limit 7 is applied to the SQL query, we find the 7 events with a yearly reoccurrence and discard the events after evaluating the reoccurrence rules because they are not due within the next 14 days and end up with an empty result even if there are two events to show.

The workaround for search requests with a limit and time range is asking for more row than requested and retrying if we have not reached the limit.

TODO

Test cases

search_with_limit_and_timerange.txt

A sample calendar with 7 reoccurring events (in January 2024) and two events happening this month.
GitHub does now allow ICS attachments, thus don't forget to rename.

On master/main the upcoming events widget should be empty.
On this branch Cake Tasting and Pasta Day should appear in the widget.

Checklist

@kesselb kesselb added bug 2. developing Work in progress labels May 7, 2024
@kesselb kesselb added this to the Nextcloud 30 milestone May 7, 2024
@kesselb kesselb self-assigned this May 7, 2024
@kesselb kesselb force-pushed the bug/noid/caldav-search-limit-and-timerange branch from 3fdcf9f to d335b1b Compare May 7, 2024 17:43
@kesselb kesselb force-pushed the bug/noid/caldav-search-limit-and-timerange branch 2 times, most recently from b5856fd to 7d2eee6 Compare May 7, 2024 19:35
@kesselb kesselb mentioned this pull request May 7, 2024
12 tasks
@kesselb kesselb changed the title Bug/noid/caldav search limit and timerange CalDAV fix search with limit and time range May 7, 2024
@kesselb kesselb added 3. to review Waiting for reviews and removed 2. developing Work in progress labels May 7, 2024
@kesselb kesselb force-pushed the bug/noid/caldav-search-limit-and-timerange branch from 7d2eee6 to d2dd88b Compare May 7, 2024 20:20
@kesselb kesselb marked this pull request as ready for review May 7, 2024 20:26
@kesselb kesselb force-pushed the bug/noid/caldav-search-limit-and-timerange branch from d2dd88b to b7c3704 Compare May 7, 2024 20:41
@kesselb
Copy link
Contributor Author

kesselb commented May 8, 2024

Reminder for myself:

The search query does not have an "order by" command.
If we are still seeing weirdnesses with upcoming events / search result, we should consider adding one.

@ChristophWurst
Copy link
Member

The search query does not have an "order by" command.
If we are still seeing weirdnesses with upcoming events / search result, we should consider adding one.

Databases will probably use an index for the query, or traverse the data according to the primary id. So the sorting will be unpredictable across instances but for the same instance it should be stable.

@joshtrichards joshtrichards added the feature: caldav Related to CalDAV internals label May 8, 2024
'name' => 'VCALENDAR',
'comp-filters' => [
[
'name' => 'VEVENT',
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor Author

@kesselb kesselb May 8, 2024

Choose a reason for hiding this comment

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

Well spotted, thank you 🙏

A user mentioned that the widget is not showing items from the tasks app anymore.
I assume that could be the reason.

What do you suggest, extending to VEVENT, VTODO?

Copy link
Member

Choose a reason for hiding this comment

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

At least, yes. However, from what I can see in the validateCompFilters implementation, you would need to call the method again with the same payload, only changing the name property, you can't add a second comp-filter directly, which sounds…bad?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I took a look at the missing tasks / the VTODO handling and wrote down my findings at #45333.
It's more work than I imagined, and therefore I need to discuss it with Christoph.
Happy to have your feedback / pointers on that one ;)

@kesselb
Copy link
Contributor Author

kesselb commented May 8, 2024

Added the test case "testSearchWithLimitAndTimeRangeShouldReturnObjectsInTheSameOrder".

Cake Tasting (2024-05-09) and Pasta Day (2024-05-14) match the criteria. Pasta Day was added to the calendar first and therefore is the first result returned by the SQL server. Likely, the SQL server(s) sorted the results by the primary id.

I observed locally that the records are not always sorted by the primary id. Especially if you move around event's a lot, it happens that suddenly the order changes.

The calendar search api does not document how/if the results are ordered.

  • A is therefore to drop the test case again and ignore it for now.
  • B is to extend the pull request (add order by to the query, sort the final result by DTSTART) to have more reliable results for the api consumer.

@kesselb kesselb force-pushed the bug/noid/caldav-search-limit-and-timerange branch from 9410085 to 9fa82f2 Compare May 8, 2024 15:10
@ChristophWurst
Copy link
Member

I observed locally that the records are not always sorted by the primary id. Especially if you move around event's a lot, it happens that suddenly the order changes.

The calendar search api does not document how/if the results are ordered.

Then we are free to add sorting :) Pick a column. Ideally it's an indexed one.

@kesselb kesselb force-pushed the bug/noid/caldav-search-limit-and-timerange branch from 9fa82f2 to d8189bf Compare May 15, 2024 10:59

$hasLimit = is_int($limit);
$hasTimeRange = false;

if (isset($options['timerange'])) {
Copy link
Contributor

Choose a reason for hiding this comment

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

TIL! You can chuck the initial isset check on $options['timerange'] as isset can handle deep checks with possible non-existing values for the upper arrays

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea, indeed easier to read now.

apps/dav/lib/CalDAV/CalDavBackend.php Show resolved Hide resolved
@kesselb kesselb force-pushed the bug/noid/caldav-search-limit-and-timerange branch 2 times, most recently from 458b1cb to dea1906 Compare May 15, 2024 20:30
Copy link
Member

@ChristophWurst ChristophWurst left a comment

Choose a reason for hiding this comment

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

Looks good

Event recurrences are evaluated at runtime because the database only knows the first and last occurrence.

Given, a user created 8 events with a yearly reoccurrence and two for events tomorrow.
The upcoming event widget asks the CalDAV backend for 7 events within the next 14 days.

If limit 7 is applied to the SQL query, we find the 7 events with a yearly reoccurrence and discard the events after evaluating the reoccurrence rules because they are not due within the next 14 days and end up with an empty result even if there are two events to show.

The workaround for search requests with a limit and time range is asking for more row than requested and retrying if we have not reached the limit.

Signed-off-by: Daniel Kesselberg <mail@danielkesselberg.de>
Sorting the events by the start date leads to more predictable results for the search API consumers.

Signed-off-by: Daniel Kesselberg <mail@danielkesselberg.de>
@kesselb kesselb force-pushed the bug/noid/caldav-search-limit-and-timerange branch from dea1906 to b769dc4 Compare May 28, 2024 17:56
@kesselb kesselb added 4. to release Ready to be released and/or waiting for tests to finish and removed 3. to review Waiting for reviews labels May 28, 2024
@kesselb kesselb merged commit 7f44b9d into master May 29, 2024
155 checks passed
@kesselb kesselb deleted the bug/noid/caldav-search-limit-and-timerange branch May 29, 2024 14:30
@kesselb
Copy link
Contributor Author

kesselb commented May 29, 2024

/backport to stable29

@kesselb
Copy link
Contributor Author

kesselb commented May 29, 2024

/backport to stable28

@kesselb
Copy link
Contributor Author

kesselb commented May 29, 2024

/backport to stable27

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4. to release Ready to be released and/or waiting for tests to finish bug feature: caldav Related to CalDAV internals
Projects
5 participants