feat: add Cloudflare cache purge by tag for app updates#1511
Conversation
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📝 WalkthroughWalkthroughAdds per-app Cache-Tag headers in Cloudflare worker cache flows and a new backend utility to purge those per-app tags via Cloudflare API; integrates purge calls as background tasks in app/version lifecycle and billing webhook handlers. Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Client/App
participant CF_Worker as Cloudflare Worker
participant Supabase as Supabase Backend
participant CF_API as Cloudflare API
Client->>CF_Worker: Request endpoint
CF_Worker->>CF_Worker: Generate response\nset Cache-Tag: "app:<id>" (on-prem/plan)
CF_Worker-->>Client: Response with Cache-Tag header
Client->>Supabase: Create new version / create app / billing event
Supabase->>Supabase: Update DB (apps table)
Supabase->>Supabase: Schedule backgroundTask(purgeOnPremCache / purgePlanCacheForOrg)
Supabase->>CF_API: POST /client/v4/zones/<zone>/purge_cache { "tags": [...] } (parallel per zone)
CF_API-->>Supabase: 200/response
Supabase-->>Client: Complete request (notifications / webhooks continue)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@supabase/functions/_backend/triggers/on_version_create.ts`:
- Around line 11-12: The import order violates the perfectionist/sort-imports
rule; swap the two import statements so that purgeAppCacheTags is imported
before backgroundTask (i.e., import { purgeAppCacheTags } from
'../utils/cloudflare_cache_purge.ts' appears above import { backgroundTask }
from '../utils/utils.ts') to satisfy the linter.
| import { backgroundTask } from '../utils/utils.ts' | ||
| import { purgeAppCacheTags } from '../utils/cloudflare_cache_purge.ts' |
There was a problem hiding this comment.
Fix import order to satisfy perfectionist/sort-imports.
CI reports the new import should precede ../utils/utils.ts (Line 11-12).
🔧 Suggested fix
-import { backgroundTask } from '../utils/utils.ts'
-import { purgeAppCacheTags } from '../utils/cloudflare_cache_purge.ts'
+import { purgeAppCacheTags } from '../utils/cloudflare_cache_purge.ts'
+import { backgroundTask } from '../utils/utils.ts'📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { backgroundTask } from '../utils/utils.ts' | |
| import { purgeAppCacheTags } from '../utils/cloudflare_cache_purge.ts' | |
| import { purgeAppCacheTags } from '../utils/cloudflare_cache_purge.ts' | |
| import { backgroundTask } from '../utils/utils.ts' |
🧰 Tools
🪛 GitHub Actions: Run tests
[error] 12-12: perfectionist/sort-imports: Expected '../utils/cloudflare_cache_purge.ts' to come before '../utils/utils.ts'.
🤖 Prompt for AI Agents
In `@supabase/functions/_backend/triggers/on_version_create.ts` around lines 11 -
12, The import order violates the perfectionist/sort-imports rule; swap the two
import statements so that purgeAppCacheTags is imported before backgroundTask
(i.e., import { purgeAppCacheTags } from '../utils/cloudflare_cache_purge.ts'
appears above import { backgroundTask } from '../utils/utils.ts') to satisfy the
linter.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@supabase/functions/_backend/utils/cloudflare_cache_purge.ts`:
- Around line 95-101: The purgePlanCacheForOrg function currently uses
supabaseAdmin to fetch apps; replace that with the project DB client by calling
getPgClient() or getDrizzleClient() inside purgePlanCacheForOrg and run a SELECT
app_id FROM apps WHERE owner_org = $1 (or equivalent drizzle query) using orgId
as the parameter, then map/iterate the returned rows the same way you did with
the previous data; ensure you handle query errors/empty results consistently
(same variable names like apps or rows) and remove the supabaseAdmin
import/usage in this function.
- Around line 59-61: The code reads response.json().catch(() => null) into
result and then accesses result.success which fails TypeScript strict checks;
fix by narrowing or asserting the JSON shape before property access: replace the
current assignment with a typed assertion or safe narrow, e.g. set result using
const result = (await response.json().catch(() => null)) as { success?: boolean
} | null; or alternatively check typeof result === 'object' && 'success' in
result before using result.success; update the location where cloudlogErr is
called (same block) to use the narrowed/typed result so TypeScript strict mode
is satisfied.
| export async function purgePlanCacheForOrg(c: Context, orgId: string) { | ||
| // Get all app_ids for this org | ||
| const { data: apps, error } = await supabaseAdmin(c) | ||
| .from('apps') | ||
| .select('app_id') | ||
| .eq('owner_org', orgId) | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Use getPgClient/getDrizzleClient for the org apps lookup.
This new DB access uses supabaseAdmin, but backend guidelines require PostgreSQL access through getPgClient()/getDrizzleClient() during the D1 migration. Please refactor this query accordingly. As per coding guidelines, ...
🤖 Prompt for AI Agents
In `@supabase/functions/_backend/utils/cloudflare_cache_purge.ts` around lines 95
- 101, The purgePlanCacheForOrg function currently uses supabaseAdmin to fetch
apps; replace that with the project DB client by calling getPgClient() or
getDrizzleClient() inside purgePlanCacheForOrg and run a SELECT app_id FROM apps
WHERE owner_org = $1 (or equivalent drizzle query) using orgId as the parameter,
then map/iterate the returned rows the same way you did with the previous data;
ensure you handle query errors/empty results consistently (same variable names
like apps or rows) and remove the supabaseAdmin import/usage in this function.
Add Cache-Tag headers to on-prem and plan-upgrade responses in the Cloudflare Snippet worker, enabling global cache purge via Cloudflare API. When a new app version is created, purge all cached responses for that app across all zones to prevent stale 429 responses from blocking updates. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
… triggers
- On-prem cache uses `app-onprem:{appId}` tag, purged on app create and version create
- Plan cache uses `app-plan:{appId}` tag, purged on Stripe payment success
- Added purgePlanCacheForOrg to purge all apps in an org when subscription succeeds
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes TypeScript error: Property 'success' does not exist on type '{}'
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
9f51d91 to
f502f57
Compare
Skip cache purge when not running on workerd (Cloudflare Workers) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
* feat: add Cloudflare cache purge by tag for app updates
Add Cache-Tag headers to on-prem and plan-upgrade responses in the Cloudflare Snippet worker, enabling global cache purge via Cloudflare API. When a new app version is created, purge all cached responses for that app across all zones to prevent stale 429 responses from blocking updates.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* refactor: separate on-prem and plan cache tags with appropriate purge triggers
- On-prem cache uses `app-onprem:{appId}` tag, purged on app create and version create
- Plan cache uses `app-plan:{appId}` tag, purged on Stripe payment success
- Added purgePlanCacheForOrg to purge all apps in an org when subscription succeeds
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: add type assertion for Cloudflare API response
Fixes TypeScript error: Property 'success' does not exist on type '{}'
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: only run cache purge on Cloudflare Workers runtime
Skip cache purge when not running on workerd (Cloudflare Workers)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>



Summary
Add Cache-Tag headers to cached responses in the Cloudflare Snippet worker, enabling global cache purge via Cloudflare API. When a new app version is uploaded, purge all cached responses for that app across all zones to prevent stale 429 responses from blocking updates.
Test plan
CF_CACHE_PURGE_TOKENandCF_CACHE_PURGE_ZONE_IDSenv vars are setChecklist
🤖 Generated with Claude Code
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.