Skip to content

Commit c2ec6fc

Browse files
[calendar] fix: prevent excessive fetching on client reload and refactor calendarfetcherutils.js (#3976)
The bottom line of this PR is, that it fixes an issue and simplifies the code by dealing with the TODOs in the code. For review, I suggest looking at each commit individually. If there are too many changes for a PR, let me know and I'll split it up :slightly_smiling_face: ## 1. [fix(calendar): prevent excessive fetching with smart refresh strategy](8892cd3) - Add lastFetch timestamp tracking to CalendarFetcher - Add shouldRefetch() method with configurable minimum interval (default: 3 minutes) - When reusing existing fetcher: fetch if data is stale (>3 min), otherwise broadcast cached events - Prevents double broadcasts to consuming modules while maintaining fresh data - Balances rate limit prevention (Issue #3971) with data freshness on user reload - Prevents excessive fetching during rapid reloads (e.g., Fully Kiosk screensaver use case) - Allows fresh calendar data when enough time has passed since last fetch ## 2. [refactor(calendar): simplify event exclusion logic](d507aba) - Extract filtering logic from `shouldEventBeExcluded` into new helper `checkEventAgainstFilter` - Simplify the main loop in `shouldEventBeExcluded It resolves a TODO from the comments in the code: * `This seems like an overly complicated way to exclude events based on the title.` ## 3. [refactor(calendar): extract recurring event expansion logic](d510160) This change separates the expansion of recurring events from the main filtering loop into a new helper function 'expandRecurringEvent'. It resolves two TODOs from the comments in the code: - `This should be a separate function` - `This should create an event per moment so we can change anything we want` This improves code readability, reduces complexity in 'filterEvents', and allows for cleaner handling of individual recurrence instances. ## 4. [refactor(calendar): simplify recurring event handling](b04f716) - Simplify 'getMomentsFromRecurringEvent' using modern syntax - Improve handling of full-day events across different timezones ## 5. [test(calendar): fix UNTIL date in fullday_until.ics fixture](1d762b2) The issue was with the UNTIL date being May 4th while DTSTART was May 5th. This created an invalid recurrence rule where the end date came before the start date. The fix only adjusts the UNTIL date from May 4th to May 5th, so it matches the start date.
1 parent fdac92d commit c2ec6fc

File tree

5 files changed

+198
-196
lines changed

5 files changed

+198
-196
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ planned for 2026-01-01
4040
- [gitignore] cleanup/simplify .gitignore (#3952, #3954, #3968, #3969)
4141
- [compliments] refactor: optimize `loadComplimentFile` method and add unit tests(#3969)
4242
- [core] chore: simplify Wayland start script (#3974)
43+
- [calendar] refactor: simplify recurring event handling and event exclusion logic (#3976)
4344

4445
### Fixed
4546

@@ -52,6 +53,7 @@ planned for 2026-01-01
5253
- [weather] fixed windy icon not showing up in pirateweather (#3957)
5354
- [compliments] fixed duplicate query param "?" when constructing refresh url (#3967)
5455
- [compliments] fixed compliments remote file minimum delay to be 15 minutes (#3970)
56+
- [calendar] prevent excessive fetching with smart refresh strategy (#3976)
5557

5658
### Updated
5759

modules/default/calendar/calendarfetcher.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class CalendarFetcher {
3838
this.events = [];
3939
this.reloadTimer = null;
4040
this.serverErrorCount = 0;
41+
this.lastFetch = null;
4142
this.fetchFailedCallback = () => {};
4243
this.eventsReceivedCallback = () => {};
4344
}
@@ -165,6 +166,7 @@ class CalendarFetcher {
165166
maximumEntries: this.maximumEntries,
166167
maximumNumberOfDays: this.maximumNumberOfDays
167168
});
169+
this.lastFetch = Date.now();
168170
this.broadcastEvents();
169171
} catch (error) {
170172
Log.error(`${this.url} - iCal parsing failed: ${error.message}`);
@@ -179,6 +181,19 @@ class CalendarFetcher {
179181
this.scheduleNextFetch(nextDelay);
180182
}
181183

184+
/**
185+
* Check if enough time has passed since the last fetch to warrant a new one.
186+
* Uses reloadInterval as the threshold to respect user's configured fetchInterval.
187+
* @returns {boolean} True if a new fetch should be performed
188+
*/
189+
shouldRefetch () {
190+
if (!this.lastFetch) {
191+
return true;
192+
}
193+
const timeSinceLastFetch = Date.now() - this.lastFetch;
194+
return timeSinceLastFetch >= this.reloadInterval;
195+
}
196+
182197
/**
183198
* Broadcasts the current events to listeners
184199
*/

0 commit comments

Comments
 (0)