Skip to content

Make the recurrence window relative to today, and configurable - #2377

Open
Cyber1000 wants to merge 1 commit into
TechbeeAT:developfrom
Cyber1000:fix/recurrence-window
Open

Make the recurrence window relative to today, and configurable#2377
Cyber1000 wants to merge 1 commit into
TechbeeAT:developfrom
Cyber1000:fix/recurrence-window

Conversation

@Cyber1000

Copy link
Copy Markdown

The window recurrence instances are generated for is centred on DTSTART and sized by the frequency - one year for DAILY and WEEKLY, ten for MONTHLY, a hundred for YEARLY. Since nothing is generated before DTSTART, it reaches forward from the start of the series. Measured on a real collection of 5973 tasks with 42 recurring series:

  • 2892 instance rows, so the collection shows 8865 entries. Reproduced with ical4j against the actual (DTSTART, RRULE) pairs: 2892, to the row.
  • for 27 of the 42 - every weekly series older than a year - the window ends before today, so only stale instances exist and nothing current is ever created. A weekly entry from 2018 gets 53 instances from 2018 and 2019. That part is not about cost at all.

The window becomes a setting, with the current behaviour as the default:

  • From the start of the series (default)
  • Around today (1 month) -> ~330 instances for the 42 series
  • Around today (3 months) -> ~660, and 648 measured on the device
  • Around today (1 year) -> ~2080

Each keeps one month of history so a recently missed occurrence stays visible. Sub-daily frequencies stay bounded by their frequency - three months of a SECONDLY rule is millions of rows wherever the window sits. A series that has not started yet is anchored on its own start, or it would materialise nothing and disappear from a list that shows instances in place of the series itself.

Changing the setting rebuilds every series right away. Instances are inserted with dirty = false and changed ones are kept, so nothing is uploaded and individually completed occurrences survive.

Worth a second opinion: the window is read through RecurrenceWindow.current instead of being passed in, because getInstancesFromRrule() is reached from Room DAO methods and from the sync content provider, neither of which carries a Context - a parameter would have to be threaded through moveToCollection() and saveAll() into the ViewModels. Happy to change that.

Analysis and measurements were done with Claude Code.

Refs #1660

The window recurrence instances are generated for is centred on DTSTART and sized by the
frequency - one year for DAILY and WEEKLY, ten for MONTHLY, a hundred for YEARLY. Since
nothing is generated before DTSTART, it reaches forward from the start of the series.
Measured on a real collection of 5973 tasks with 42 recurring series:

  - 2892 instance rows, so the collection shows 8865 entries. Reproduced with ical4j against
    the actual (DTSTART, RRULE) pairs: 2892, to the row.
  - for 27 of the 42 - every weekly series older than a year - the window ends before today,
    so only stale instances exist and nothing current is ever created. A weekly entry from
    2018 gets 53 instances from 2018 and 2019. That part is not about cost at all.

The window becomes a setting, with the current behaviour as the default:

  - From the start of the series (default)
  - Around today (1 month)   -> ~330 instances for the 42 series
  - Around today (3 months)  -> ~660, and 648 measured on the device
  - Around today (1 year)    -> ~2080

Each keeps one month of history so a recently missed occurrence stays visible. Sub-daily
frequencies stay bounded by their frequency - three months of a SECONDLY rule is millions of
rows wherever the window sits. A series that has not started yet is anchored on its own start,
or it would materialise nothing and disappear from a list that shows instances in place of the
series itself.

Changing the setting rebuilds every series right away. Instances are inserted with
dirty = false and changed ones are kept, so nothing is uploaded and individually completed
occurrences survive.

Worth a second opinion: the window is read through RecurrenceWindow.current instead of being
passed in, because getInstancesFromRrule() is reached from Room DAO methods and from the sync
content provider, neither of which carries a Context - a parameter would have to be threaded
through moveToCollection() and saveAll() into the ViewModels. Happy to change that.

Analysis and measurements were done with Claude Code.

Refs TechbeeAT#1660
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant