Skip to content

fix(deployment): cache cosmos REST fallback routes#3158

Merged
baktun14 merged 3 commits into
mainfrom
fix/deployment-cache-cosmos-fallback-routes
May 14, 2026
Merged

fix(deployment): cache cosmos REST fallback routes#3158
baktun14 merged 3 commits into
mainfrom
fix/deployment-cache-cosmos-fallback-routes

Conversation

@baktun14
Copy link
Copy Markdown
Contributor

@baktun14 baktun14 commented May 8, 2026

Why

/akash/deployment/{version}/deployments/info and /list mirror the Cosmos REST API but are served from console's chain DB by FallbackDeploymentReaderService. They exist so external Cosmos tooling can keep working against deployments whose state has been pruned from chain RPC nodes.

Logs show ~50K requests in 6 hours from a single Azure IP polling one specific draining deployment (dseq=26735741) with userAgent: node. Every call goes through Sequelize against the chain DB — the same DB that's saturated with 235+ active connections (see #3157).

This PR caches at two layers, since neither alone is sufficient:

  • Cache-Control headers help browsers and any cooperating CDN.
  • In-process memoization is what actually defeats server-side bots that ignore HTTP cache headers — identical queries within a block window are served from an in-memory LRU and never reach Sequelize.

What

  1. Route-level cache: { maxAge: 10, staleWhileRevalidate: 30 } on both fallback routes — emits Cache-Control: public, max-age=10, stale-while-revalidate=30.
  2. Service-level memoization in FallbackDeploymentReaderService:
    • findByOwnerAndDseq: @Memoize({ ttlInSeconds: averageBlockTime }) (matches the existing pattern in AkashBlockService).
    • findAll: wrapped with cacheResponse(averageBlockTime, ...) keyed on the params (the @Memoize decorator only handles primitive args).

The cacheResponse helper has stale-while-revalidate semantics in-process and dedupes concurrent identical requests via pendingRequests, so a request burst still results in a single DB hit.

Summary by CodeRabbit

  • Performance Improvements
    • Added HTTP caching to deployment list and info endpoints to reduce load and speed up responses.
    • Introduced result caching/memoization for deployment lookups to minimize repeated database queries and improve endpoint responsiveness.

Review Change Stack

The /akash/deployment/{version}/deployments/{info,list} routes mirror
chain REST and are hit at high frequency by external Cosmos tooling
polling for draining deployments. Each call queries the chain DB
through Sequelize and contributes to connection-pool saturation.

Data only changes when the indexer ingests a new block (~6s), so a
short Cache-Control (max-age=10, stale-while-revalidate=30) lets
browsers and any CDN safely deduplicate without staleness concerns.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 8, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b784f6a0-bb37-400a-843d-c28e597a2ca9

📥 Commits

Reviewing files that changed from the base of the PR and between 4b9317f and 7cb9fc4.

📒 Files selected for processing (1)
  • apps/api/src/deployment/routes/deployments/deployments.router.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/api/src/deployment/routes/deployments/deployments.router.ts

📝 Walkthrough

Walkthrough

Adds TTL-based caching to the fallback deployment reader (cached findAll via cacheResponse, memoized findByOwnerAndDseq) and sets HTTP cache parameters (maxAge=10, staleWhileRevalidate=30) on two database-fallback deployment routes.

Changes

Deployment Cache Configuration

Layer / File(s) Summary
Service imports / TTL
apps/api/src/deployment/services/fallback-deployment-reader/fallback-deployment-reader.service.ts
Adds cacheResponse, @Memoize, and imports averageBlockTime used as TTL.
findAll cache wrapper
apps/api/src/deployment/services/fallback-deployment-reader/fallback-deployment-reader.service.ts
findAll now returns cacheResponse(...) delegating work to a private findAllUncached.
findAll uncached implementation
apps/api/src/deployment/services/fallback-deployment-reader/fallback-deployment-reader.service.ts
Original findAll body moved into findAllUncached (pagination and transform logic unchanged).
findByOwnerAndDseq memoization
apps/api/src/deployment/services/fallback-deployment-reader/fallback-deployment-reader.service.ts
findByOwnerAndDseq annotated with @Memoize({ ttlInSeconds: averageBlockTime }).
Route cache configuration
apps/api/src/deployment/routes/deployments/deployments.router.ts
fallbackListRoute and fallbackInfoRoute updated to cache.maxAge: 10 and cache.staleWhileRevalidate: 30.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/deployment-cache-cosmos-fallback-routes

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

@codecov
Copy link
Copy Markdown

codecov Bot commented May 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 62.11%. Comparing base (b3d30c4) to head (7cb9fc4).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3158      +/-   ##
==========================================
- Coverage   63.70%   62.11%   -1.60%     
==========================================
  Files        1089     1004      -85     
  Lines       26447    24130    -2317     
  Branches     6412     6008     -404     
==========================================
- Hits        16849    14988    -1861     
+ Misses       8402     7975     -427     
+ Partials     1196     1167      -29     
Flag Coverage Δ *Carryforward flag
api 84.32% <100.00%> (+<0.01%) ⬆️
deploy-web 46.26% <ø> (-0.42%) ⬇️ Carriedforward from 4b9317f
log-collector ?
notifications 90.66% <ø> (-0.40%) ⬇️ Carriedforward from 4b9317f
provider-console 81.48% <ø> (ø) Carriedforward from 4b9317f
provider-inventory ?
provider-proxy 85.00% <ø> (-1.08%) ⬇️ Carriedforward from 4b9317f
tx-signer ?

*This pull request uses carry forward flags. Click here to find out more.

Files with missing lines Coverage Δ
...yment-reader/fallback-deployment-reader.service.ts 90.47% <100.00%> (+0.23%) ⬆️

... and 370 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Cache-Control alone does not deter the server-side bots that drive
this traffic — they ignore the header. Memoize the service methods
so identical queries within a block window are served from an
in-process LRU and never reach Sequelize.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
apps/api/src/deployment/services/fallback-deployment-reader/fallback-deployment-reader.service.ts (1)

27-29: ⚡ Quick win

Normalize the findAll cache key to avoid cache fragmentation.

Using raw JSON.stringify(params) can split cache entries for equivalent requests (e.g., defaulted vs omitted fields, key-order differences), which reduces hit rate on hot endpoints.

Proposed change
 async findAll(params: DatabaseDeploymentListParams): Promise<RestAkashDeploymentListResponse> {
-  return cacheResponse(averageBlockTime, `FallbackDeploymentReaderService#findAll#${JSON.stringify(params)}`, () => this.findAllUncached(params));
+  const normalizedParams = Object.entries({
+    skip: params.skip ?? 0,
+    limit: params.limit ?? 100,
+    key: params.key ?? "",
+    countTotal: params.countTotal ?? true,
+    ...params
+  }).sort(([a], [b]) => a.localeCompare(b));
+
+  return cacheResponse(
+    averageBlockTime,
+    `FallbackDeploymentReaderService#findAll#${JSON.stringify(normalizedParams)}`,
+    () => this.findAllUncached(params)
+  );
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/api/src/deployment/services/fallback-deployment-reader/fallback-deployment-reader.service.ts`
around lines 27 - 29, The cache key for FallbackDeploymentReaderService.findAll
uses JSON.stringify(params) which fragments cache; normalize params before
keying by creating a canonical representation (e.g., fill in omitted defaults
from DatabaseDeploymentListParams, sort object keys or pick/serialize only the
deterministic subset of fields used for the query) and use that normalized
string in the cacheResponse key; update the call in findAll to compute
normalizedParams (or a stableKeyFromParams helper) and use
`FallbackDeploymentReaderService#findAll#${normalizedKey}` when calling
cacheResponse so equivalent requests map to the same cache entry.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@apps/api/src/deployment/services/fallback-deployment-reader/fallback-deployment-reader.service.ts`:
- Around line 27-29: The cache key for FallbackDeploymentReaderService.findAll
uses JSON.stringify(params) which fragments cache; normalize params before
keying by creating a canonical representation (e.g., fill in omitted defaults
from DatabaseDeploymentListParams, sort object keys or pick/serialize only the
deterministic subset of fields used for the query) and use that normalized
string in the cacheResponse key; update the call in findAll to compute
normalizedParams (or a stableKeyFromParams helper) and use
`FallbackDeploymentReaderService#findAll#${normalizedKey}` when calling
cacheResponse so equivalent requests map to the same cache entry.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 63b0828e-9232-4dc6-b12a-6ee51dad45e1

📥 Commits

Reviewing files that changed from the base of the PR and between e1c2ad7 and 4b9317f.

📒 Files selected for processing (1)
  • apps/api/src/deployment/services/fallback-deployment-reader/fallback-deployment-reader.service.ts

@baktun14 baktun14 enabled auto-merge May 14, 2026 18:36
@baktun14 baktun14 added this pull request to the merge queue May 14, 2026
Merged via the queue into main with commit a3b1b76 May 14, 2026
56 checks passed
@baktun14 baktun14 deleted the fix/deployment-cache-cosmos-fallback-routes branch May 14, 2026 19:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants