-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Network ranking algorithm v2 #2960
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 18 minutes and 47 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 (34)
WalkthroughAdds program similarity calculations (category, partner, performance), a cron route to batch and persist similarity scores, partner-ranking refactor to use similarities and categories, Prisma schema updates for categories and program similarities, migration/backfill scripts, discoverability changes, UI/schema/constant updates, and related route permission adjustments. Changes
Sequence Diagram(s)sequenceDiagram
participant Cron as Cron Job
participant Route as /api/cron/calc-program-similarities
participant DB as Prisma
participant Calc as Similarity Calculators
participant Rank as PartnerRanking
participant QStash as QStash
Cron->>Route: GET (signed)
Route->>DB: findNextProgram()
DB-->>Route: currentProgram
Route->>DB: fetch candidatePrograms (batch)
loop per candidate pair
Route->>Calc: calculateCategorySimilarity(p1,p2)
Calc->>DB: fetch program categories (parallel)
DB-->>Calc: categories
Calc-->>Route: categoryScore
Route->>Calc: calculatePartnerSimilarity(p1,p2)
Calc->>DB: raw SQL partner counts
DB-->>Calc: partnerStats
Calc-->>Route: partnerScore
Route->>Calc: calculatePerformanceSimilarity(p1,p2)
Calc->>DB: fetch performance aggregates
DB-->>Calc: metrics
Calc-->>Route: performanceScore
Route->>Route: compute weightedScore (0.5/0.3/0.2)
alt score >= PROGRAM_SIMILARITY_SCORE_THRESHOLD
Route->>DB: collect for insert
end
end
Route->>DB: delete existing similarities (batch)
Route->>DB: insert ProgramSimilarity rows (transaction)
DB-->>Route: persisted
Route->>QStash: schedule next run (cursor/payload)
QStash-->>Route: scheduled
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Areas to focus during review:
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 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 |
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: 0
♻️ Duplicate comments (1)
apps/web/app/(ee)/api/cron/calculate-program-similarities/route.ts (1)
173-188: Incomplete deletion leaves stale forward references.The deletion only removes similarities where
programIdis in the batch (lines 176-182), but doesn't delete the "forward" references whereprogramId = currentProgram.idandsimilarProgramIdis in the batch. WithskipDuplicates: trueon insert, old entries with outdated similarity scores will never be updated.Example: When processing program A against batch [B, C]:
- Creates: A→B, B→A, A→C, C→A
- Deletes: WHERE
programId IN [B, C](removes B→*, C→*)- Leaves: A→B, A→C from previous runs (stale scores)
Apply this diff to delete both directions:
await prisma.$transaction(async (tx) => { const programIds = programs.map((program) => program.id); await tx.programSimilarity.deleteMany({ where: { - programId: { - in: programIds, - }, + OR: [ + { programId: { in: programIds } }, + { programId: currentProgram.id, similarProgramId: { in: programIds } }, + ], }, });
🧹 Nitpick comments (1)
apps/web/app/(ee)/api/network/partners/route.ts (1)
70-72: Refine categories parsing to handle edge cases.While the current code correctly handles truly empty strings (which are falsy), it could produce
[""]for whitespace-only strings like" "or comma-separated lists with empty segments like"a,,b".Apply this diff to handle these edge cases:
- categories: partner.categories - ? partner.categories.split(",").map((c: string) => c.trim()) - : [], + categories: partner.categories?.trim() + ? partner.categories.split(",").map((c: string) => c.trim()).filter(Boolean) + : [],The
.filter(Boolean)removes any empty strings, and checking.trim()first ensures whitespace-only strings are treated as empty.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
apps/web/app/(ee)/api/cron/calculate-program-similarities/route.ts(1 hunks)apps/web/app/(ee)/api/network/partners/route.ts(2 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/payouts/program-payout-settings-sheet.tsx(2 hunks)apps/web/lib/constants/payouts.ts(1 hunks)apps/web/lib/constants/program.ts(1 hunks)apps/web/lib/zod/schemas/programs.ts(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/web/lib/zod/schemas/programs.ts
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-05-29T04:45:18.504Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2448
File: packages/email/src/templates/partner-program-summary.tsx:0-0
Timestamp: 2025-05-29T04:45:18.504Z
Learning: In the PartnerProgramSummary email template (packages/email/src/templates/partner-program-summary.tsx), the stat titles are hardcoded constants ("Clicks", "Leads", "Sales", "Earnings") that will always match the ICONS object keys after toLowerCase() conversion, so icon lookup failures are not possible.
Applied to files:
apps/web/lib/constants/program.ts
📚 Learning: 2025-10-15T01:05:43.266Z
Learnt from: steven-tey
Repo: dubinc/dub PR: 2958
File: apps/web/app/app.dub.co/(dashboard)/[slug]/settings/members/page-client.tsx:432-457
Timestamp: 2025-10-15T01:05:43.266Z
Learning: In apps/web/app/app.dub.co/(dashboard)/[slug]/settings/members/page-client.tsx, defer refactoring the custom MenuItem component (lines 432-457) to use the shared dub/ui MenuItem component to a future PR, as requested by steven-tey.
Applied to files:
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/payouts/program-payout-settings-sheet.tsx
📚 Learning: 2025-06-06T07:59:03.120Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2177
File: apps/web/lib/api/links/bulk-create-links.ts:66-84
Timestamp: 2025-06-06T07:59:03.120Z
Learning: In apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined results from links.find() operations when building invalidLinks arrays, because existing links are fetched from the database based on the input links, so matches are expected to always exist.
Applied to files:
apps/web/app/(ee)/api/cron/calculate-program-similarities/route.ts
📚 Learning: 2025-10-28T19:17:28.085Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2985
File: apps/web/app/(ee)/api/network/programs/[programSlug]/route.ts:20-27
Timestamp: 2025-10-28T19:17:28.085Z
Learning: In this codebase, Prisma's extendedWhereUnique feature is enabled (or Prisma 5.x is used), allowing findUniqueOrThrow to accept additional non-unique filters alongside unique fields like slug. This pattern is valid and acceptable.
Applied to files:
apps/web/app/(ee)/api/cron/calculate-program-similarities/route.ts
🧬 Code graph analysis (3)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/payouts/program-payout-settings-sheet.tsx (1)
apps/web/lib/constants/payouts.ts (1)
PAYOUT_HOLDING_PERIOD_DAYS(9-9)
apps/web/app/(ee)/api/network/partners/route.ts (4)
apps/web/lib/constants/program.ts (1)
PROGRAM_SIMILARITY_SCORE_THRESHOLD(3-3)apps/web/lib/zod/schemas/partner-network.ts (2)
getNetworkPartnersQuerySchema(36-50)NetworkPartnerSchema(63-102)apps/web/lib/api/network/partner-ranking.ts (1)
calculatePartnerRanking(40-213)apps/web/lib/actions/partners/get-conversion-score.ts (1)
getConversionScore(4-18)
apps/web/app/(ee)/api/cron/calculate-program-similarities/route.ts (7)
apps/web/lib/cron/verify-vercel.ts (1)
verifyVercelSignature(3-20)apps/web/lib/api/errors.ts (1)
handleApiError(124-173)packages/prisma/index.ts (1)
prisma(3-9)apps/web/app/(ee)/api/cron/calculate-program-similarities/calculate-category-similarity.ts (1)
calculateCategorySimilarity(4-43)apps/web/app/(ee)/api/cron/calculate-program-similarities/calculate-partner-similarity.ts (1)
calculatePartnerSimilarity(10-44)apps/web/app/(ee)/api/cron/calculate-program-similarities/calculate-performance-similarity.ts (1)
calculatePerformanceSimilarity(12-65)apps/web/lib/constants/program.ts (1)
PROGRAM_SIMILARITY_SCORE_THRESHOLD(3-3)
⏰ 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 (9)
apps/web/lib/constants/payouts.ts (1)
9-9: LGTM!The new constant is well-defined and appropriately placed in the payouts constants module. The values represent reasonable holding period options for payout settings.
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/payouts/program-payout-settings-sheet.tsx (1)
5-8: LGTM!The refactoring to use
PAYOUT_HOLDING_PERIOD_DAYSis implemented correctly. The import is properly structured and the usage at line 110 is consistent with the change.Also applies to: 110-110
apps/web/lib/constants/program.ts (1)
3-3: LGTM! Well-defined similarity threshold constant.Centralizing the 0.3 threshold as a named constant improves maintainability and ensures consistent filtering across the similarity calculation and ranking workflows.
apps/web/app/(ee)/api/network/partners/route.ts (2)
25-32: LGTM! Similarity filtering correctly applied.The similarPrograms query correctly filters by the threshold and limits results for efficient ranking. The use of
gt(strict greater than) is consistent with the threshold filtering in the cron job.
46-60: LGTM! Ranking integration is correct.The similarPrograms mapping and calculatePartnerRanking invocation properly forward all parameters. The
starred ?? undefinedconversion correctly handles nullish values.apps/web/app/(ee)/api/cron/calculate-program-similarities/route.ts (4)
29-62: LGTM! Proper cron handler implementation.Both GET and POST handlers correctly implement signature verification (Vercel for initial trigger, QStash for subsequent calls) and handle errors appropriately.
119-171: LGTM! Similarity calculation is well-structured.The parallel computation of the three similarity components and their weighted combination (category 0.5, partner 0.3, performance 0.2) is efficient and logical. Bidirectional pairs are correctly created for scores above the threshold.
191-218: LGTM! Batch scheduling logic is sound.The logic correctly determines whether to continue with the same current program (if batch is full) or advance to the next program (if batch is incomplete), and properly schedules the next invocation via QStash.
221-261: LGTM! findNextProgram helper is correctly implemented.The helper properly handles both specific program lookup and sequential program discovery. The ACME program exclusion is now consistently applied regardless of whether
afterProgramIdis provided, and workspace plan filtering is appropriate.
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
♻️ Duplicate comments (1)
apps/web/app/(ee)/api/network/partners/route.ts (1)
72-74: Handle empty or whitespace-only categories strings.This still returns
[""]whenpartner.categoriesis an empty string. Trim first and filter falsy values so consumers always receive either meaningful categories or an empty array.- categories: partner.categories - ? partner.categories.split(",").map((c: string) => c.trim()) - : [], + categories: partner.categories?.trim() + ? partner.categories + .split(",") + .map((c: string) => c.trim()) + .filter(Boolean) + : [],
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/web/app/(ee)/api/network/partners/route.ts(2 hunks)apps/web/lib/api/network/partner-ranking.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
apps/web/app/(ee)/api/network/partners/route.ts (4)
apps/web/lib/constants/program.ts (1)
PROGRAM_SIMILARITY_SCORE_THRESHOLD(3-3)apps/web/lib/zod/schemas/partner-network.ts (2)
getNetworkPartnersQuerySchema(36-50)NetworkPartnerSchema(63-102)apps/web/lib/api/network/partner-ranking.ts (1)
calculatePartnerRanking(40-290)apps/web/lib/actions/partners/get-conversion-score.ts (1)
getConversionScore(4-18)
apps/web/lib/api/network/partner-ranking.ts (1)
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
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: 0
🧹 Nitpick comments (2)
apps/web/ui/partners/partner-network/network-partner-sheet.tsx (2)
45-54: Consider addingenabledoption for consistency.The keyboard shortcut could benefit from the
enabledoption to prevent registration whenonNextis unavailable, aligning with the pattern used elsewhere in this file (line 227-230).Apply this diff:
- useKeyboardShortcut( - "ArrowRight", - () => { - if (onNext) { - onNext(); - } - }, - { sheet: true }, - ); + useKeyboardShortcut( + "ArrowRight", + () => onNext?.(), + { sheet: true, enabled: !!onNext }, + );
56-65: Consider addingenabledoption for consistency.Similar to the ArrowRight shortcut, this could benefit from the
enabledoption to prevent registration whenonPreviousis unavailable.Apply this diff:
- useKeyboardShortcut( - "ArrowLeft", - () => { - if (onPrevious) { - onPrevious(); - } - }, - { sheet: true }, - ); + useKeyboardShortcut( + "ArrowLeft", + () => onPrevious?.(), + { sheet: true, enabled: !!onPrevious }, + );
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/about-you-form.tsx(1 hunks)apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/profile-discovery-guide.tsx(1 hunks)apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/use-partner-discovery-requirements.ts(1 hunks)apps/web/lib/actions/partners/update-partner-profile.ts(1 hunks)apps/web/lib/partners/discoverability.ts(3 hunks)apps/web/ui/partners/partner-network/network-partner-sheet.tsx(1 hunks)packages/prisma/schema/program.prisma(3 hunks)
✅ Files skipped from review due to trivial changes (1)
- apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/about-you-form.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/prisma/schema/program.prisma
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-05-29T04:45:18.504Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2448
File: packages/email/src/templates/partner-program-summary.tsx:0-0
Timestamp: 2025-05-29T04:45:18.504Z
Learning: In the PartnerProgramSummary email template (packages/email/src/templates/partner-program-summary.tsx), the stat titles are hardcoded constants ("Clicks", "Leads", "Sales", "Earnings") that will always match the ICONS object keys after toLowerCase() conversion, so icon lookup failures are not possible.
Applied to files:
apps/web/lib/partners/discoverability.ts
📚 Learning: 2025-09-17T17:44:03.965Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2857
File: apps/web/lib/actions/partners/update-program.ts:96-0
Timestamp: 2025-09-17T17:44:03.965Z
Learning: In apps/web/lib/actions/partners/update-program.ts, the team prefers to keep the messagingEnabledAt update logic simple by allowing client-provided timestamps rather than implementing server-controlled timestamp logic to avoid added complexity.
Applied to files:
apps/web/lib/actions/partners/update-partner-profile.ts
📚 Learning: 2025-07-30T15:29:54.131Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2673
File: apps/web/ui/partners/rewards/rewards-logic.tsx:268-275
Timestamp: 2025-07-30T15:29:54.131Z
Learning: In apps/web/ui/partners/rewards/rewards-logic.tsx, when setting the entity field in a reward condition, dependent fields (attribute, operator, value) should be reset rather than preserved because different entities (customer vs sale) have different available attributes. Maintaining existing fields when the entity changes would create invalid state combinations and confusing UX.
Applied to files:
apps/web/lib/actions/partners/update-partner-profile.ts
📚 Learning: 2025-10-17T08:18:19.278Z
Learnt from: devkiran
Repo: dubinc/dub PR: 0
File: :0-0
Timestamp: 2025-10-17T08:18:19.278Z
Learning: In the apps/web codebase, `@/lib/zod` should only be used for places that need OpenAPI extended zod schema. All other places should import from the standard `zod` package directly using `import { z } from "zod"`.
Applied to files:
apps/web/lib/actions/partners/update-partner-profile.ts
📚 Learning: 2025-09-18T17:03:06.200Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2858
File: apps/web/ui/partners/partner-application-sheet.tsx:262-266
Timestamp: 2025-09-18T17:03:06.200Z
Learning: The useKeyboardShortcut hook with context options like {sheet: true, modal: true} requires ALL specified contexts to be present simultaneously. The shortcut will only trigger when both existingSheetBackdrop and existingModalBackdrop are present, using strict equality matching in the implementation.
Applied to files:
apps/web/ui/partners/partner-network/network-partner-sheet.tsx
🧬 Code graph analysis (1)
apps/web/lib/partners/discoverability.ts (2)
apps/web/lib/types.ts (2)
PartnerProps(441-444)EnrolledPartnerProps(453-453)apps/web/lib/partners/online-presence.ts (1)
PartnerOnlinePresenceFields(13-27)
⏰ 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 (6)
apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/profile-discovery-guide.tsx (1)
70-71: LGTM! Clear and aligned with the PR's Partner Network theme.The updated copy effectively communicates the value proposition to partners and aligns with the broader network ranking and categorization changes introduced in this PR.
apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/use-partner-discovery-requirements.ts (1)
10-19: LGTM!The refactoring correctly passes
programEnrollmentsfrom the SWR hook togetPartnerDiscoveryRequirements, and the memoization dependencies are properly updated.apps/web/lib/partners/discoverability.ts (3)
44-46: Verify the business logic change from industryInterests to monthlyTraffic.The discovery requirement has changed from "Specify your industry interests" to "Specify your estimated monthly traffic". This is a significant change in what partners need to provide for discoverability. Please confirm this aligns with the product requirements for partner discovery.
54-54: Improved label with formatted currency.The use of
currencyFormatterwithtrailingZeroDisplay: "stripIfInteger"provides a cleaner user-facing label for the commission requirement.
54-61: Confirmed: Logic change is as described—verify product alignment.Your analysis is accurate. The refactoring changes the requirement from:
- Previous: Total commissions ≥ $100 across all programs (combined)
- Current: At least 2 approved programs (excluding ACME), each with ≥ $100
This is a deliberate architectural change (see commit: "improve getPartnerDiscoveryRequirements") that shifts from aggregated to per-program thresholds. A partner earning $200 from one program would have qualified before but now fails.
Recommend confirming this stricter threshold aligns with current product goals for partner discoverability.
apps/web/lib/actions/partners/update-partner-profile.ts (1)
186-186: Update type safety concern - no issues found.The code is type-safe. The
updatedPartner.programsrelation (fetched at line 144 withprograms: true) contains fullProgramEnrollmentobjects that include all required fields:
programId✓status✓totalCommissions✓The function accepts
Pick<EnrolledPartnerProps, "programId" | "status" | "totalCommissions">[], which is satisfied by the Prisma relation. TypeScriptPickis a type utility that selects specific fields; passing objects with additional fields is valid since those three fields are present inProgramEnrollment.
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
♻️ Duplicate comments (2)
apps/web/app/(ee)/api/network/partners/route.ts (2)
25-32: AddorderBywhen usingtakeonsimilarPrograms.Prisma will throw
The query includes "take" but it does not include an "orderBy"at runtime. Add an explicit sort (e.g., highest similarity first) before shipping.similarPrograms: { where: { similarityScore: { gt: PROGRAM_SIMILARITY_SCORE_THRESHOLD, }, }, + orderBy: { + similarityScore: "desc", + }, take: 5, },
72-74: Strip whitespace-only category entries.When
partner.categoriesis whitespace,split(",")yields[""], so callers receive an empty string category. Trim first and filter out blank items to avoid rendering ghost chips.- categories: partner.categories - ? partner.categories.split(",").map((c: string) => c.trim()) - : [], + categories: partner.categories?.trim() + ? partner.categories + .split(",") + .map((c: string) => c.trim()) + .filter((c: string) => c.length > 0) + : [],
🧹 Nitpick comments (1)
apps/web/app/(ee)/api/network/partners/route.ts (1)
51-62: Remove leftoverconsole.timeinstrumentation.
console.time/console.timeEndinside the API route will spam logs in production. Drop these or gate them behind an explicit debug flag.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/web/app/(ee)/api/network/partners/route.ts(2 hunks)apps/web/lib/api/network/calculate-partner-ranking.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-28T19:17:28.085Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2985
File: apps/web/app/(ee)/api/network/programs/[programSlug]/route.ts:20-27
Timestamp: 2025-10-28T19:17:28.085Z
Learning: In this codebase, Prisma's extendedWhereUnique feature is enabled (or Prisma 5.x is used), allowing findUniqueOrThrow to accept additional non-unique filters alongside unique fields like slug. This pattern is valid and acceptable.
Applied to files:
apps/web/app/(ee)/api/network/partners/route.ts
🧬 Code graph analysis (2)
apps/web/app/(ee)/api/network/partners/route.ts (4)
apps/web/lib/constants/program.ts (1)
PROGRAM_SIMILARITY_SCORE_THRESHOLD(3-3)apps/web/lib/zod/schemas/partner-network.ts (2)
getNetworkPartnersQuerySchema(36-50)NetworkPartnerSchema(63-102)apps/web/lib/api/network/calculate-partner-ranking.ts (1)
calculatePartnerRanking(40-290)apps/web/lib/actions/partners/get-conversion-score.ts (1)
getConversionScore(4-18)
apps/web/lib/api/network/calculate-partner-ranking.ts (2)
packages/prisma/client.ts (1)
Prisma(29-29)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
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: 2
🧹 Nitpick comments (3)
apps/web/scripts/migrations/update-discoverable-partners.ts (1)
22-83: Remove or document the commented-out code.This 61-line commented-out block adds significant noise to the migration script. If these social field checks are not needed, remove them. If they might be needed in the future, consider documenting why they're commented out or moving them to a separate reference file.
Apply this diff to remove the commented-out code:
}, - // AND: [ - // { - // OR: [ - // { - // website: { - // equals: "", - // }, - // }, - // { website: null }, - // ], - // }, - // { - // OR: [ - // { - // youtube: { - // equals: "", - // }, - // }, - // { youtube: null }, - // ], - // }, - // { - // OR: [ - // { - // twitter: { - // equals: "", - // }, - // }, - // { twitter: null }, - // ], - // }, - // { - // OR: [ - // { - // linkedin: { - // equals: "", - // }, - // }, - // { linkedin: null }, - // ], - // }, - // { - // OR: [ - // { - // instagram: { - // equals: "", - // }, - // }, - // { instagram: null }, - // ], - // }, - // { - // OR: [ - // { - // tiktok: { - // equals: "", - // }, - // }, - // { tiktok: null }, - // ], - // }, - // ], },apps/web/lib/partners/get-discoverability-requirements.ts (2)
9-9: Consider extracting the commission threshold to a shared constant.The threshold
PARTNER_DISCOVERY_MIN_COMMISSIONS = 10_00is duplicated between this file and the migration script. To ensure consistency and make future updates easier, consider extracting this toapps/web/lib/constants/program.tsalongsideLARGE_PROGRAM_IDS.In
apps/web/lib/constants/program.ts, add:export const LARGE_PROGRAM_IDS = [ "prog_CYCu7IMAapjkRpTnr8F1azjN", "prog_1K0QHV7MP3PR05CJSCF5VN93X", ]; export const PARTNER_DISCOVERY_MIN_COMMISSIONS = 10_00;Then update both files to import it:
-const PARTNER_DISCOVERY_MIN_COMMISSIONS = 10_00; +import { LARGE_PROGRAM_IDS, PARTNER_DISCOVERY_MIN_COMMISSIONS } from "../constants/program";
36-38: Address or track the TODO comment.The TODO indicates that the online presence requirement should also verify that accounts are verified, not just connected. This could affect discoverability quality if unverified accounts are accepted.
Should this verification check be implemented now, or would you like me to open an issue to track this enhancement?
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
apps/web/app/(ee)/api/partner-profile/programs/[programId]/analytics/route.ts(2 hunks)apps/web/app/(ee)/api/partner-profile/programs/[programId]/customers/[customerId]/route.ts(2 hunks)apps/web/app/(ee)/api/partner-profile/programs/[programId]/events/route.ts(2 hunks)apps/web/lib/constants/program.ts(1 hunks)apps/web/lib/partners/get-discoverability-requirements.ts(1 hunks)apps/web/scripts/migrations/update-discoverable-partners.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/web/lib/constants/program.ts
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-09-17T17:44:03.965Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2857
File: apps/web/lib/actions/partners/update-program.ts:96-0
Timestamp: 2025-09-17T17:44:03.965Z
Learning: In apps/web/lib/actions/partners/update-program.ts, the team prefers to keep the messagingEnabledAt update logic simple by allowing client-provided timestamps rather than implementing server-controlled timestamp logic to avoid added complexity.
Applied to files:
apps/web/app/(ee)/api/partner-profile/programs/[programId]/events/route.tsapps/web/scripts/migrations/update-discoverable-partners.ts
📚 Learning: 2025-07-17T06:41:45.620Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2637
File: apps/web/app/(ee)/api/singular/webhook/route.ts:0-0
Timestamp: 2025-07-17T06:41:45.620Z
Learning: In the Singular integration (apps/web/app/(ee)/api/singular/webhook/route.ts), the event names in the singularToDubEvent object have intentionally different casing: "Copy GAID" and "copy IDFA". This casing difference is valid and should not be changed, as these are the correct event names expected from Singular.
Applied to files:
apps/web/app/(ee)/api/partner-profile/programs/[programId]/events/route.ts
📚 Learning: 2025-06-16T19:21:23.506Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2519
File: apps/web/ui/analytics/utils.ts:35-37
Timestamp: 2025-06-16T19:21:23.506Z
Learning: In the `useAnalyticsFilterOption` function in `apps/web/ui/analytics/utils.ts`, the pattern `options?.context ?? useContext(AnalyticsContext)` is intentionally designed as a complete replacement strategy, not a merge. When `options.context` is provided, it should contain all required fields (`baseApiPath`, `queryString`, `selectedTab`, `requiresUpgrade`) and completely replace the React context, not be merged with it. This is used for dependency injection or testing scenarios.
Applied to files:
apps/web/app/(ee)/api/partner-profile/programs/[programId]/analytics/route.ts
🧬 Code graph analysis (5)
apps/web/app/(ee)/api/partner-profile/programs/[programId]/events/route.ts (1)
apps/web/lib/constants/program.ts (1)
LARGE_PROGRAM_IDS(2-5)
apps/web/app/(ee)/api/partner-profile/programs/[programId]/analytics/route.ts (1)
apps/web/lib/constants/program.ts (1)
LARGE_PROGRAM_IDS(2-5)
apps/web/scripts/migrations/update-discoverable-partners.ts (2)
packages/prisma/index.ts (1)
prisma(3-9)apps/web/lib/constants/program.ts (1)
LARGE_PROGRAM_IDS(2-5)
apps/web/lib/partners/get-discoverability-requirements.ts (3)
apps/web/lib/types.ts (2)
PartnerProps(441-444)EnrolledPartnerProps(453-453)apps/web/lib/partners/online-presence.ts (2)
PartnerOnlinePresenceFields(13-27)ONLINE_PRESENCE_FIELDS(29-103)apps/web/lib/constants/program.ts (1)
LARGE_PROGRAM_IDS(2-5)
apps/web/app/(ee)/api/partner-profile/programs/[programId]/customers/[customerId]/route.ts (1)
apps/web/lib/constants/program.ts (1)
LARGE_PROGRAM_IDS(2-5)
⏰ 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 (6)
apps/web/app/(ee)/api/partner-profile/programs/[programId]/events/route.ts (2)
5-8: LGTM! Clean import of centralized constants.The import correctly brings in
LARGE_PROGRAM_IDSto support multiple large programs, improving maintainability.
31-31: LGTM! Refactoring to dynamic program ID check.The change from a hardcoded ID to
LARGE_PROGRAM_IDS.includes(program.id)is backward-compatible and makes it easy to manage multiple large programs centrally.apps/web/app/(ee)/api/partner-profile/programs/[programId]/customers/[customerId]/route.ts (2)
6-9: LGTM! Consistent with the refactoring pattern.The import correctly adds
LARGE_PROGRAM_IDSfor centralized large program management, consistent with the other route handlers.
31-31: LGTM! Dynamic check properly implemented.The refactoring from hardcoded ID to
LARGE_PROGRAM_IDS.includes(program.id)is correctly applied and maintains backward compatibility.apps/web/app/(ee)/api/partner-profile/programs/[programId]/analytics/route.ts (1)
5-8: LGTM! Consistent import pattern.The import correctly adds
LARGE_PROGRAM_IDSto enable centralized management of large program IDs across all partner profile routes.apps/web/scripts/migrations/update-discoverable-partners.ts (1)
15-15: No issues found. The $10 commission threshold is intentional.The threshold is defined as a centralized constant
PARTNER_DISCOVERY_MIN_COMMISSIONS = 10_00inapps/web/lib/partners/get-discoverability-requirements.tsand is displayed to partners as part of the discovery requirements: "Earn $10 in commissions." This is a deliberate, well-designed barrier to filter inactive partners while keeping the threshold achievable, and it's used consistently throughout the eligibility logic.
apps/web/app/(ee)/api/partner-profile/programs/[programId]/analytics/route.ts
Show resolved
Hide resolved
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
Summary by CodeRabbit
New Features
Updates