-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Catch R2 upload error to avoid breaking conversion tracking #3157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Rate limit exceeded@steven-tey has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 6 minutes and 36 seconds before requesting another review. ⌛ 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. 📒 Files selected for processing (2)
WalkthroughRefactors avatar persistence error handling: PATCH avatar update switches from parallel Promise.allSettled to sequential upload-with-cleanup; POST and tracking flows add .catch handlers that log upload errors and set the customer's avatar field to null; removes the deprecated createCustomer OpenAPI operation and its POST mapping; disables /fraud test suite. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Client
participant API as Customer API
participant Storage as R2
participant DB as Database
Note over API,Storage: Sequential upload with integrated cleanup & rollback
Client->>API: PATCH /customers/[id] (with avatar)
API->>Storage: upload(newAvatar)
alt upload succeeds
Storage-->>API: upload OK
API->>Storage: delete(oldAvatar) [if present]
API->>DB: update customer.avatar -> new URL
DB-->>API: update OK
API-->>Client: 200 OK
else upload fails
Storage--xAPI: error
API->>DB: update customer.avatar -> null
DB-->>API: update OK
API-->>Client: error / cleaned state
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
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 |
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/web/app/(ee)/api/customers/route.ts (1)
168-189: LGTM! Avatar upload error handling prevents broken references.The error handling correctly catches upload failures and nullifies the avatar field in the database, ensuring data consistency. This prevents the customer from having a broken avatar URL if R2 storage fails.
Note: This exact error-handling pattern is duplicated across 4 files (this file, track-sale.ts, track-lead.ts, and customers/[id]/route.ts). Consider extracting a reusable helper function like:
async function uploadCustomerAvatar({ customerId, avatar, finalAvatarUrl, }: { customerId: string; avatar: string; finalAvatarUrl: string; }) { return storage .upload({ key: finalAvatarUrl.replace(`${R2_URL}/`, ""), body: avatar, opts: { width: 128, height: 128 }, }) .catch(async (error) => { console.error("Error persisting customer avatar to R2", error); await prisma.customer.update({ where: { id: customerId }, data: { avatar: null }, }); }); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
apps/web/app/(ee)/api/customers/[id]/route.ts(1 hunks)apps/web/app/(ee)/api/customers/route.ts(1 hunks)apps/web/lib/api/conversions/track-lead.ts(1 hunks)apps/web/lib/api/conversions/track-sale.ts(1 hunks)apps/web/lib/openapi/customers/create-customer.ts(0 hunks)apps/web/lib/openapi/customers/index.ts(0 hunks)
💤 Files with no reviewable changes (2)
- apps/web/lib/openapi/customers/create-customer.ts
- apps/web/lib/openapi/customers/index.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-02T22:46:22.739Z
Learnt from: steven-tey
Repo: dubinc/dub PR: 2924
File: apps/web/lib/api/conversions/track-lead.ts:7-7
Timestamp: 2025-10-02T22:46:22.739Z
Learning: In apps/web/lib/api/conversions/track-lead.ts, lead events are cached in Redis for 5 minutes (keys: `leadCache:${customer.id}` and `leadCache:${customer.id}:${stringifiedEventName}`) to provide immediate data availability while Tinybird ingestion happens asynchronously. This caching pattern allows for async-only recording without breaking "wait" mode semantics.
Applied to files:
apps/web/lib/api/conversions/track-lead.ts
🧬 Code graph analysis (4)
apps/web/lib/api/conversions/track-sale.ts (2)
apps/web/lib/storage.ts (1)
storage(251-251)packages/prisma/index.ts (1)
prisma(3-9)
apps/web/lib/api/conversions/track-lead.ts (2)
apps/web/lib/storage.ts (1)
storage(251-251)packages/prisma/index.ts (1)
prisma(3-9)
apps/web/app/(ee)/api/customers/route.ts (2)
apps/web/lib/storage.ts (1)
storage(251-251)packages/prisma/index.ts (1)
prisma(3-9)
apps/web/app/(ee)/api/customers/[id]/route.ts (2)
apps/web/lib/storage.ts (2)
storage(251-251)isStored(253-255)packages/prisma/index.ts (1)
prisma(3-9)
⏰ 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). (1)
- GitHub Check: build
🔇 Additional comments (2)
apps/web/lib/api/conversions/track-sale.ts (1)
217-234: LGTM! Error handling correctly prevents broken avatar references during sale tracking.The catch block appropriately handles upload failures for newly created customers. Since this code only executes within the
elseblock (line 127) when no existing customer is found, usingfinalCustomerIdis correct as it matches the newly created customer's ID.apps/web/app/(ee)/api/customers/[id]/route.ts (1)
99-122: LGTM! Sequential flow with cleanup improves avatar update reliability.The refactored approach chains the upload with cleanup (deleting the old avatar on success) and error handling (nullifying on failure). This sequential flow is clearer than the previous parallel approach and correctly uses
customer.idfrom the fetched customer.The conditional check at line 109 (
isStored(oldCustomerAvatar)) ensures only R2-stored avatars are deleted, preventing errors from attempting to delete external URLs.
Summary by CodeRabbit
Bug Fixes
Chores
Tests
✏️ Tip: You can customize this high-level summary in your review settings.