Skip to content

perf: cache /v1/data/pubTree and manifest resolve in Redis (prod cherry-pick of #1286)#1287

Merged
hubsmoke merged 1 commit into
mainfrom
hotfix/cache-resolve-pubtree-prod
May 3, 2026
Merged

perf: cache /v1/data/pubTree and manifest resolve in Redis (prod cherry-pick of #1286)#1287
hubsmoke merged 1 commit into
mainfrom
hotfix/cache-resolve-pubtree-prod

Conversation

@hubsmoke

@hubsmoke hubsmoke commented May 3, 2026

Copy link
Copy Markdown
Member

Summary

Cherry-pick of #1286 (already merged to develop, verified live on nodes-api-dev — see metrics below) directly to main so prod gets the win without waiting for the full develop → main promotion.

Same surgical 14-line addition as #1286. Identical pattern to #1281/#1285 (the versions cache).

Verified live on dev

TEST 1 — resolve /<uuid>/0  (the slow 5-8s endpoint):
  cold MISS:  4.20s
  warm HIT:   165ms   ← 25× faster
  warm HIT:   129ms
  warm HIT:   111ms

TEST 2 — pubTree /v1/data/pubTree/<uuid>/<cid>:
  cold MISS:  386ms
  warm HIT:   138ms
  warm HIT:   122ms

TEST 3 — /<uuid> (latest, will be invalidated on publish):
  cold MISS:  4.31s
  warm HIT:   113ms   ← 38× faster

Test ran against real dev uuid XSwfV4AYF5qHfmu0AOLKnGNEGkjlitU4tbl_W2DsMwc. (dpid 1812).

Combined stack on prod after this lands

Layer PR Effect
Vercel edge cache (HTML) #1540 LIVE — 12-16s cold → 70ms warm
desci-server versions cache #1281/#1285 LIVE
desci-server resolve cache this PR cold first-hit per Vercel region 6s → ~1.5s
desci-server pubTree cache this PR further 250ms savings per cold

Test plan

  • After deploy to prod, curl nodes-api.desci.com/<uuid>/0 twice. First hit ~5s, second hit <200ms.
  • Same for /v1/data/pubTree/<uuid>/<manifestCid>.
  • Publish a new version — confirm /<uuid> (no version) returns the new latest on the very next request (latest key invalidated by publish.ts).
  • Confirm /<uuid>/0 (specific index) is unaffected by publish — it's immutable, stays cached.

Safety

  • Only success paths cache. Components (PDF/code) and 4xx/5xx not cached.
  • pubTree keys are content-addressed (manifestCid is a content hash), so per-version entries are inherently immutable. No invalidation needed beyond what publish.ts already does.
  • resolve per-index and per-CID keys are immutable. Only :latest is invalidated, hooked into the existing delFromCache block in publish.ts.

🤖 Generated with Claude Code

Same pattern as #1281 (which cached /v1/pub/versions). The dpid SSR path
in nodes-web-v2 hits both endpoints on every cold render:

  resolvePublishedManifest → GET /<uuid>/<version>     (handled by raw/resolve.ts)
  loadDriveTree           → GET /v1/data/pubTree/...  (handled by data/retrieve.ts)

The first is the slow one — it calls getIndexedResearchObjects (theGraph,
~5-8s) plus an IPFS gateway fetch. The second varies but is typically
1-3s. Together they dominate the dpid cold-load TTFB.

Both responses are content-addressed:
- pubTree by (uuid, manifestCid, rootCid, dataPath, depth) — manifestCid
  is itself a content hash, so the tuple is fully immutable. No
  invalidation needed; new publishes mint a new manifestCid and write
  a fresh cache entry.
- resolve by (uuid, firstParam) where firstParam is "" / index / CID.
  Index- and CID-keyed entries are immutable. The "latest" key is
  invalidated in publish.ts alongside the existing `indexed-versions`
  invalidation.

Cache safety: only success paths cache. Component (PDF/code) responses
in resolve.ts and 4xx/5xx responses are NOT cached.

Combined with the Vercel edge cache shipped in nodes-web-v2#1540, cold
SSR drops from 12-16s → ~1.5s; warm SSR is unchanged at ~150ms.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 3, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a5225828-2a27-44de-9fef-09008f3b2904

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch hotfix/cache-resolve-pubtree-prod

Comment @coderabbitai help to get the list of available commands and usage tips.

@hubsmoke hubsmoke merged commit e2930b5 into main May 3, 2026
2 of 3 checks passed
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