Skip to content

feat(calendar): lazy-load events by date range with cache-first refresh#603

Open
tompscanlan wants to merge 1 commit into
muni-town:mainfrom
OpenMeet-Team:fix/calendar-lazy-load
Open

feat(calendar): lazy-load events by date range with cache-first refresh#603
tompscanlan wants to merge 1 commit into
muni-town:mainfrom
OpenMeet-Team:fix/calendar-lazy-load

Conversation

@tompscanlan

@tompscanlan tompscanlan commented Mar 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Addresses feedback about calendar events being stale/out-of-date.

Why replace LiveQuery?

The old approach used a LiveQuery on comp_calendar_event to reactively display events. But LiveQuery's reactivity added no value here — nothing else writes to that table, only our own code after fetching from the OpenMeet API. The result was:

  • No date filtering — full-table scan of all events on every render
  • No freshness concept — events fetched once stayed forever, even if changed on OpenMeet
  • Redundant re-scans — each insert or replace triggered LiveQuery to re-run a query over data we just fetched

What replaces it

A cache-first architecture that lazy-loads events by visible date range:

  • SQLite as durable cache: OPFS-backed SQLite gives instant paint on revisit; if cached data is older than 5 minutes, a fresh API fetch runs and replaces it
  • Range-based loading: datesSet callback fetches only the month/day the user is viewing, passes startDate/endDate query params to the API
  • Race condition handling: generation counter discards stale API responses on rapid navigation

Files changed

File Change
+page.svelte Cache-first loading with loadEventsForRange, loadFromSQLite, writeToSQLite, generation counter, loading overlay
calendar-utils.ts (new) Pure functions extracted from component for testability
calendar-utils.test.ts (new) 16 unit tests
openmeet.ts Added optional startDate/endDate params to fetchGroupEvents
calendar.svelte.ts Removed CalendarEvent interface and calendarEventsQuery (replaced by range-based loading)

Test plan

  • Unit tests pass (pnpm test — 16 tests in calendar-utils.test.ts)
  • Navigate between months — events load per-range, spinner overlays calendar
  • Connect/disconnect OpenMeet — events refresh correctly
  • Revisit a previously-viewed month — instant paint from cache, no spinner if < 5 min
  • Test in non-UTC timezone — date ranges match calendar boundaries

@tompscanlan tompscanlan marked this pull request as ready for review March 7, 2026 19:24
Replace full-table LiveQuery with range-based loading. LiveQuery's
reactivity added no value here — only our own code writes to
comp_calendar_event after API fetches, so it was re-scanning all events
on every write we already had the data for.

- datesSet callback drives lazy-load per visible date range
- 5-minute TTL for cache freshness, SQLite for instant paint on revisit
- Generation counter discards stale API responses on rapid navigation
- Reactive $state array replaces imperative setOption for event updates
- Pure utility functions extracted to calendar-utils.ts with 16 unit tests
- fetchGroupEvents accepts optional startDate/endDate query params

Addresses feedback about calendar events appearing out-of-date.
@tompscanlan tompscanlan force-pushed the fix/calendar-lazy-load branch from c7124c8 to 237ea8e Compare March 7, 2026 19:57
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