fix(cache): improve cache handling by checking availability before operations#397
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📜 Recent review details⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
📝 WalkthroughWalkthroughCacheStorageService now checks runtime availability of the Cache API and opens caches via Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
frontend/src/app/shared/service/cache-storage.service.ts (2)
13-15: Prefer a single availability predicate.
cacheAvailableandcache()currently duplicate the same guard. Reusing the getter insidecache()would make it harder for the unsupported-environment behavior to drift later.Also applies to: 145-149
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/app/shared/service/cache-storage.service.ts` around lines 13 - 15, The cache availability check is duplicated: reuse the private getter cacheAvailable inside the cache() method (and any other places with the same guard) instead of re-checking typeof caches !== 'undefined'; update cache() to return null or throw consistently when cacheAvailable is false, and remove the duplicated typeof caches check so all code paths rely on the single cacheAvailable predicate (affecting the cache() method and the similar guard around the other occurrence that currently mirrors lines 145-149).
17-44: Add coverage for the no-cachesfallback.This branch is now what keeps
getCache()compatible withfrontend/src/app/features/book/service/book-file.service.ts:30-38andfrontend/src/app/features/readers/pdf-reader/pdf-reader.component.ts:610-622, both of which immediately consume the returnedResponsevia.blob(). A focused test that stubscachesaway and asserts the response is still readable would lock that in.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/app/shared/service/cache-storage.service.ts` around lines 17 - 44, Add a unit/integration test covering the "no caches" fallback in getCache so we don't regress the behavior used by BookFileService and PdfReader components: stub global caches to undefined (e.g. (globalThis as any).caches = undefined), call cacheStorageService.getCache(uri, /*noValidate*/ false) and immediately consume the returned Response via .blob() (or .arrayBuffer()) to assert the body is readable and not locked; also assert that cacheStorageService.put(...) is not invoked when cacheAvailable is false/when caches is absent and that fetchFromUri is used (spy on fetchFromUri and put). Target the getCache, fetchFromUri, put and attemptToGetAndValidateCache symbols when adding the test to ensure the fallback path works exactly as callers expect.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@frontend/src/app/shared/service/cache-storage.service.ts`:
- Around line 13-15: The cache availability check is duplicated: reuse the
private getter cacheAvailable inside the cache() method (and any other places
with the same guard) instead of re-checking typeof caches !== 'undefined';
update cache() to return null or throw consistently when cacheAvailable is
false, and remove the duplicated typeof caches check so all code paths rely on
the single cacheAvailable predicate (affecting the cache() method and the
similar guard around the other occurrence that currently mirrors lines 145-149).
- Around line 17-44: Add a unit/integration test covering the "no caches"
fallback in getCache so we don't regress the behavior used by BookFileService
and PdfReader components: stub global caches to undefined (e.g. (globalThis as
any).caches = undefined), call cacheStorageService.getCache(uri, /*noValidate*/
false) and immediately consume the returned Response via .blob() (or
.arrayBuffer()) to assert the body is readable and not locked; also assert that
cacheStorageService.put(...) is not invoked when cacheAvailable is false/when
caches is absent and that fetchFromUri is used (spy on fetchFromUri and put).
Target the getCache, fetchFromUri, put and attemptToGetAndValidateCache symbols
when adding the test to ensure the fallback path works exactly as callers
expect.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 38f226f5-8a3c-4c94-aa41-8d208bd9d42c
📒 Files selected for processing (1)
frontend/src/app/shared/service/cache-storage.service.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Test Suite / Frontend Tests
- GitHub Check: Test Suite / Backend Tests
- GitHub Check: Analyze (java-kotlin)
🧰 Additional context used
📓 Path-based instructions (2)
frontend/src/**/*.{ts,tsx,html,scss}
📄 CodeRabbit inference engine (AGENTS.md)
Use 2-space indentation in TypeScript, HTML, and SCSS files
Files:
frontend/src/app/shared/service/cache-storage.service.ts
frontend/src/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
frontend/src/app/**/*.{ts,tsx}: Preferinject()over constructor injection
Followfrontend/eslint.config.js: component selectors useapp-*, directive selectors useapp*, andanyis disallowed
Files:
frontend/src/app/shared/service/cache-storage.service.ts
🧠 Learnings (1)
📚 Learning: 2026-03-20T14:50:04.237Z
Learnt from: NamLe029
Repo: grimmory-tools/grimmory PR: 75
File: booklore-ui/src/app/shared/service/cache-storage.service.ts:38-45
Timestamp: 2026-03-20T14:50:04.237Z
Learning: In `booklore-ui/src/app/shared/service/cache-storage.service.ts`, the call `this.put(uri, res.clone())` inside `getCache()` is intentionally not awaited. This is a fire-and-forget design: the response is returned to the client immediately, and the cache write happens asynchronously in the background to avoid blocking the caller.
Applied to files:
frontend/src/app/shared/service/cache-storage.service.ts
🔇 Additional comments (1)
frontend/src/app/shared/service/cache-storage.service.ts (1)
104-141: Nice safe defaults for unsupported environments.Returning resolved fallbacks from the public cache operations keeps callers out of capability-detection code and makes the unsupported-browser path much easier to reason about.
zachyale
left a comment
There was a problem hiding this comment.
@balazs-szucs Should we be modifying the frontend within settings to either disable cache settings or surface to the user the cache is unavailable to them in this case?
That way they don't get confused as to why it isn't working when enabled- otherwise, they may think it's a Grimmory bug instead of a client side restriction.
|
Because you have already rejected the promise when cache is unavailable in |
right now current behavior is one hiccup in the cache can make the reader "unavailable" or blank. Users do have some control over the browser cache, see reader settings, but generally, this is the kind of stuff they do not generally care about on a technical level, they are have some control over the cache on the browser side. I do not i have ever encountered a case where a random user asked "where is my cache" 🤣 i do not think this a big deal, it solves the problem, i can take a closer look later. But i think the browser cache is good, also browser are good managing caches i think, so generally, by and large there shouldn't be problems, and when there is just "fails" silently so there shouldn't be a huge problem on UX side.
I think so yeah, I'll see what i can do. |
|
Initially, when i designed this, i have thought of the risk of caching failure and had some protection for it. The But that's only for the |
Thanks, i think with 06bb812 |
|
looks good to me |
…erations (grimmory-tools#397) * fix(cache): improve cache handling by checking availability before operations * fix(cache): improve cache handling and improve error management
…erations (grimmory-tools#397) * fix(cache): improve cache handling by checking availability before operations * fix(cache): improve cache handling and improve error management
…erations (#397) * fix(cache): improve cache handling by checking availability before operations * fix(cache): improve cache handling and improve error management
…erations (#397) * fix(cache): improve cache handling by checking availability before operations * fix(cache): improve cache handling and improve error management
…erations (grimmory-tools#397) * fix(cache): improve cache handling by checking availability before operations * fix(cache): improve cache handling and improve error management
Description
Linked Issue: Fixes #
Changes
This pull request improves the robustness of the
CacheStorageServiceby adding checks to ensure the browser's Cache API is available before performing any cache operations. This prevents errors in environments where the Cache API is not supported, such as non-secure contexts or certain browsers.Cache API availability checks:
cacheAvailablegetter to consistently determine if the Cache API is available (typeof caches !== 'undefined').getCache,match,has,put,delete,clear,getCacheSizeInBytes) to check forcacheAvailableand return safe fallback values when the Cache API is unavailable.cache()method to reject with a clear error if the Cache API is not available, preventing further cache operations in unsupported environments.getCache) only occur when the Cache API is available.Summary by CodeRabbit
Bug Fixes
Refactor