Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@steven-tey
Copy link
Collaborator

@steven-tey steven-tey commented Nov 26, 2025

Summary by CodeRabbit

  • Bug Fixes

    • Avatar upload failures during customer create/lead/sale flows are now non‑fatal and handled gracefully; failed uploads clear avatar references to avoid broken links.
    • PATCH avatar updates now follow a sequential upload-and-cleanup flow to reduce orphaned storage data.
  • Chores

    • Removed the deprecated direct customer creation API; create customers via lead tracking events instead.
  • Tests

    • Fraud test suite was temporarily disabled (skipped).

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Contributor

vercel bot commented Nov 26, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
dub Ready Ready Preview Nov 26, 2025 3:53am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 26, 2025

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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

📥 Commits

Reviewing files that changed from the base of the PR and between e9afb44 and 9b96829.

📒 Files selected for processing (2)
  • apps/web/lib/api/conversions/track-lead.ts (1 hunks)
  • apps/web/lib/api/conversions/track-sale.ts (1 hunks)

Walkthrough

Refactors 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

Cohort / File(s) Change Summary
Avatar Error Handling — PATCH/POST routes
apps/web/app/(ee)/api/customers/[id]/route.ts, apps/web/app/(ee)/api/customers/route.ts
Replaced parallel Promise.allSettled in PATCH with a sequential storage.upload → then optionally storage.delete(old) → catch to log errors and set DB customer.avatar = null. Added .catch to POST avatar uploads to log failures and null the DB avatar on error.
Avatar Error Handling — Tracking flows
apps/web/lib/api/conversions/track-lead.ts, apps/web/lib/api/conversions/track-sale.ts
Added .catch handlers to storage.upload calls that log upload failures and update the related customer's avatar field to null, making avatar persistence non-fatal for lead/sale flows.
OpenAPI — removed createCustomer
apps/web/lib/openapi/customers/create-customer.ts, apps/web/lib/openapi/customers/index.ts
Removed exported createCustomer OpenAPI operation and deleted the post: createCustomer mapping from the customers OpenAPI paths export; removed corresponding import.
Tests — disabled fraud suite
apps/web/tests/fraud/index.test.ts
Converted describe.concurrent to describe.skip.concurrent to skip the /fraud/** test block.
Manifest
package.json
Listed in manifest analysis (no code changes indicated in diff).

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Areas to pay attention to:
    • apps/web/app/(ee)/api/customers/[id]/route.ts: correctness of sequential upload → optional delete → DB update and error path semantics.
    • apps/web/app/(ee)/api/customers/route.ts, track-lead.ts, track-sale.ts: ensure .catch handlers don't swallow/report errors incorrectly and that DB nulling is scoped to the affected customer.
    • apps/web/lib/openapi/customers/*: verify no dangling imports or broken OpenAPI registration after removal.
    • apps/web/tests/fraud/index.test.ts: confirm test skip is intentional.

Possibly related PRs

Suggested reviewers

  • devkiran

Poem

🐰 I hopped through bytes to mend a thread,

When uploads break, I clear the head,
Sequential steps now steer the way,
Old endpoints trimmed, tests gently stayed,
🥕🪄 Errors tamed — the rabbit's day.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main focus of this PR: adding error handling for R2 upload failures to prevent conversion tracking from breaking.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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.

❤️ Share

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

@steven-tey
Copy link
Collaborator Author

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 26, 2025

✅ Actions performed

Full review triggered.

Copy link
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.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 63b1aa5 and 9e98f57.

📒 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 else block (line 127) when no existing customer is found, using finalCustomerId is 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.id from 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.

@steven-tey steven-tey merged commit 5cd34ea into main Nov 26, 2025
7 of 8 checks passed
@steven-tey steven-tey deleted the catch-r2-upload-error branch November 26, 2025 03:57
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.

3 participants