Files
client/plans/cache-first-audit-instructions.md
2026-04-17 16:52:51 -04:00

134 lines
4.4 KiB
Markdown

# Cache-First Anti-Pattern Audit Instructions
## Goal
Scan the codebase for places where `ndkFetchEvents` is called in a way that blocks rendering or user-visible UI when cached data could be used instead. Report each finding so a developer can apply the cache-first fix.
---
## Background
Read `docs/cache-first-page-patterns.md` first. It explains the three data APIs:
- `queryCache(filters)` — fast, local IndexedDB, 5s timeout
- `ndkFetchEvents(filters)` — slow, relay network, 15s timeout
- `subscribe(filters, opts)` — live streaming, no timeout
The rule: **never `await ndkFetchEvents(...)` in the critical render path if the data could exist in cache.** Instead, use `queryCache` first, render immediately, then fire-and-forget `ndkFetchEvents` for background hydration.
---
## What to Search For
### Pattern 1: `await ndkFetchEvents(...)` in page HTML files
Search all `www/*.html` files for:
```
await ndkFetchEvents(
```
For each match, determine:
- Is this in the main initialization flow (inside `main()` or the top-level IIFE)?
- Is there a `queryCache` call before it for the same or similar filter?
- Could the data plausibly exist in IndexedDB cache (i.e., it was fetched before on a previous page load)?
**Report as a finding if**: `await ndkFetchEvents` is called without a preceding `queryCache` for the same data, and the result is used to render UI that the user sees.
**Exclude**: Cases where `ndkFetchEvents` is used with `void` (fire-and-forget) or inside a `.then()` chain — those are already non-blocking.
### Pattern 2: `await ndkFetchEvents(...)` in shared modules
Search all `www/js/*.mjs` files for:
```
await ndkFetchEvents
```
or
```
await ndkFetchEventsFn
```
For each match, determine:
- Is this function called during page initialization or rendering?
- Does the module have access to a `queryCache` / `queryCacheFn` function?
- If not, is `queryCache` being passed through the dependency chain from the page?
**Report as a finding if**: A module-level function awaits `ndkFetchEvents` without first trying cache, AND the module does not have `queryCacheFn` available.
### Pattern 3: Missing `queryCache` in dependency threading
Search all `www/js/*.mjs` files for functions that accept a deps/options object containing `ndkFetchEvents`:
```
ndkFetchEvents
```
in destructuring patterns like `const { ndkFetchEvents, ... } = deps;`
For each match, check:
- Does the same destructuring also include `queryCache`?
- If the function forwards deps to another module, does it forward `queryCache` too?
**Report as a finding if**: A function destructures `ndkFetchEvents` from a deps object but does NOT also destructure `queryCache`.
### Pattern 4: Pages that import `ndkFetchEvents` but not `queryCache`
Search all `www/*.html` files for import statements from `init-ndk.mjs`:
```
import {
```
Check whether the import includes both `ndkFetchEvents` and `queryCache`.
**Report as a finding if**: A page imports `ndkFetchEvents` but does NOT import `queryCache`.
---
## Files to Scan
### HTML pages (check all):
- `www/*.html`
### JavaScript modules (check all):
- `www/js/*.mjs`
### Specifically check these known integration points:
- `www/js/post-interactions.mjs` — embed hydration, interaction fetching
- `www/js/post-interactions2.mjs` — dependency forwarding
- `www/js/mute-list.mjs` — mute list loading
- `www/js/profile-cache.mjs` — profile resolution
- `www/js/blossom-ui.mjs` — blossom server loading
- `www/js/relay-ui.mjs` — relay status loading
- `www/js/zaps.mjs` — zap-related fetches
- `www/js/utilities.mjs` — utility functions that may fetch
---
## Output Format
For each finding, report:
```
FILE: www/example.html (or www/js/example.mjs)
LINE: 123
PATTERN: [1|2|3|4] — [brief description]
CODE: `await ndkFetchEvents({ kinds: [1], ... })`
CONTEXT: [What this code does — e.g., "fetches user's kind 1 posts for feed render"]
SEVERITY: [HIGH if it blocks visible UI, MEDIUM if it blocks secondary content, LOW if it's a dep threading gap]
FIX HINT: [e.g., "Add queryCache call before this, render from cache, make this fire-and-forget"]
```
---
## What NOT to Flag
- `void ndkFetchEvents(...)` — already fire-and-forget, correct pattern
- `ndkFetchEvents(...)` inside `.then()` chains — already non-blocking
- `await ndkFetchEvents(...)` for `publishEvent` confirmation — must await
- `ndkFetchEvents` used only in background refresh intervals (e.g., `setInterval`)
- `subscribe(...)` calls — these are already event-driven