First slice of the reader offline/caching workstream (WS-1).
Prefetch + LRU (new epub-page-cache.service.ts): a read-through in-memory LRU (24 pages) with in-flight de-duplication in front of getEpubPage, plus prefetchAround(±5) after each load so page turns are usually instant. Wired into epub-reader.loadPage. (This is the online perf layer; the IndexedDB offline store is a separate follow-up.)
ngsw fix: the api-books dataGroup pointed at https://api.spikersoft.com/Book* — a path that never exists (real API is /api/...), so it cached nothing. Replaced with:
api-book-metadata — /api/book/* (freshness 7d). ngsw's * = [^/]* (single segment), so this matches only the bare metadata GET — not/api/book/{id}/file (auth'd PDF) or /epub-page.
Critically, /api/book/{id}/file and all /api/reader/* (progress, bookmarks, social) match no dataGroup, so auth'd/dynamic data is never SW-cached.
Note: ngsw config isn't unit-testable — the caching scope should be spot-checked against a built SW (confirm /file and /api/reader/* aren't in any cache).
Remaining WS-1 (follow-up PRs): IndexedDB offline book store + download service (quota preflight/rollback/progress), offline reader fallback + blob-URL resource rewriting, download-button UI + profile offline-books section, auth.guard offline entry.
First slice of the reader offline/caching workstream (WS-1).
**Prefetch + LRU** (new `epub-page-cache.service.ts`): a read-through in-memory LRU (24 pages) with in-flight de-duplication in front of `getEpubPage`, plus `prefetchAround(±5)` after each load so page turns are usually instant. Wired into `epub-reader.loadPage`. (This is the online perf layer; the IndexedDB offline store is a separate follow-up.)
**ngsw fix**: the `api-books` dataGroup pointed at `https://api.spikersoft.com/Book*` — a path that never exists (real API is `/api/...`), so it cached nothing. Replaced with:
- `api-book-metadata` — `/api/book/*` (freshness 7d). ngsw's `*` = `[^/]*` (single segment), so this matches only the bare metadata GET — **not** `/api/book/{id}/file` (auth'd PDF) or `/epub-page`.
- `api-epub-pages` — `/api/book/*/epub-page*` (freshness, 2s timeout).
- `api-epub-resources` — `/api/book/*/epub-resource*` (performance 30d).
Critically, `/api/book/{id}/file` and all `/api/reader/*` (progress, bookmarks, social) match **no** dataGroup, so auth'd/dynamic data is never SW-cached.
Note: ngsw config isn't unit-testable — the caching scope should be spot-checked against a built SW (confirm `/file` and `/api/reader/*` aren't in any cache).
**Remaining WS-1 (follow-up PRs):** IndexedDB offline book store + download service (quota preflight/rollback/progress), offline reader fallback + blob-URL resource rewriting, download-button UI + profile offline-books section, `auth.guard` offline entry.
PR: spikersoft-angular `feat/reader-offline-ngsw-prefetch`.
Resolved in spikersoft-angular PR #223 (merged to master). EpubPageCacheService (LRU + prefetch±5 + in-flight dedupe) wired into epub-reader.loadPage; ngsw api-books (dead /Book*) replaced with api-book-metadata/api-epub-pages/api-epub-resources — auth'd /file and /api/reader/* match no dataGroup. Closing.
Resolved in spikersoft-angular PR #223 (merged to `master`). EpubPageCacheService (LRU + prefetch±5 + in-flight dedupe) wired into `epub-reader.loadPage`; ngsw `api-books` (dead `/Book*`) replaced with `api-book-metadata`/`api-epub-pages`/`api-epub-resources` — auth'd `/file` and `/api/reader/*` match no dataGroup. Closing.
Resolved in spikersoft-backend PR #360 (merged to master). The two empty catches are gone — Keycloak update failures now propagate to UserController, which logs and returns BadRequest (restoring the designed, already-tested behavior). The two handler tests that pinned the swallow were corrected to assert propagation. S2486 finding closes as FIXED on the next scan. Closing.
Resolved in spikersoft-backend PR #360 (merged to master). The two empty catches are gone — Keycloak update failures now propagate to UserController, which logs and returns BadRequest (restoring the designed, already-tested behavior). The two handler tests that pinned the swallow were corrected to assert propagation. S2486 finding closes as FIXED on the next scan. Closing.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
First slice of the reader offline/caching workstream (WS-1).
Prefetch + LRU (new
epub-page-cache.service.ts): a read-through in-memory LRU (24 pages) with in-flight de-duplication in front ofgetEpubPage, plusprefetchAround(±5)after each load so page turns are usually instant. Wired intoepub-reader.loadPage. (This is the online perf layer; the IndexedDB offline store is a separate follow-up.)ngsw fix: the
api-booksdataGroup pointed athttps://api.spikersoft.com/Book*— a path that never exists (real API is/api/...), so it cached nothing. Replaced with:api-book-metadata—/api/book/*(freshness 7d). ngsw's*=[^/]*(single segment), so this matches only the bare metadata GET — not/api/book/{id}/file(auth'd PDF) or/epub-page.api-epub-pages—/api/book/*/epub-page*(freshness, 2s timeout).api-epub-resources—/api/book/*/epub-resource*(performance 30d).Critically,
/api/book/{id}/fileand all/api/reader/*(progress, bookmarks, social) match no dataGroup, so auth'd/dynamic data is never SW-cached.Note: ngsw config isn't unit-testable — the caching scope should be spot-checked against a built SW (confirm
/fileand/api/reader/*aren't in any cache).Remaining WS-1 (follow-up PRs): IndexedDB offline book store + download service (quota preflight/rollback/progress), offline reader fallback + blob-URL resource rewriting, download-button UI + profile offline-books section,
auth.guardoffline entry.PR: spikersoft-angular
feat/reader-offline-ngsw-prefetch.Resolved in spikersoft-angular PR #223 (merged to
master). EpubPageCacheService (LRU + prefetch±5 + in-flight dedupe) wired intoepub-reader.loadPage; ngswapi-books(dead/Book*) replaced withapi-book-metadata/api-epub-pages/api-epub-resources— auth'd/fileand/api/reader/*match no dataGroup. Closing.Resolved in spikersoft-backend PR #360 (merged to master). The two empty catches are gone — Keycloak update failures now propagate to UserController, which logs and returns BadRequest (restoring the designed, already-tested behavior). The two handler tests that pinned the swallow were corrected to assert propagation. S2486 finding closes as FIXED on the next scan. Closing.