-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Fix decode #2663
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
Fix decode #2663
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
WalkthroughThis update introduces a domain-level link retention policy, enabling automatic cleanup of old links based on a configurable retention period. It adds a new cron-triggered API endpoint for batch deletion, modifies the Prisma schema to support retention settings, updates validation schemas, and enhances the UI to allow links to be excluded from retention cleanup. Changes
Sequence Diagram(s)sequenceDiagram
participant VercelCron as Vercel Cron
participant API as /api/cron/link-retention-cleanup
participant DB as Prisma DB
participant Qstash as Qstash
participant Tinybird as Analytics
VercelCron->>API: GET /api/cron/link-retention-cleanup
API->>DB: Fetch domains with linkRetentionDays
loop For each domain
API->>DB: Delete old links in batches
API->>Tinybird: Record deletions
alt More links remain
API->>Qstash: Schedule another cleanup (POST)
end
end
API-->>VercelCron: Response
Qstash->>API: POST /api/cron/link-retention-cleanup (with domain slug)
API->>DB: Fetch domain by slug
API->>DB: Delete old links in batches
API->>Tinybird: Record deletions
alt More links remain
API->>Qstash: Schedule another cleanup (POST)
end
API-->>Qstash: Response
Estimated code review effort4 (approximately one day) Possibly related PRs
Poem
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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: 3
🔭 Outside diff range comments (3)
apps/web/scripts/stripe/update-stripe-customers.ts (2)
17-31: Script processes only 20 customers — iterate until none remain
take: 20limits the update to the first page; re-running the script is required to finish the backlog. Prefer a loop with cursor pagination so the whole dataset is covered in one run.
34-40: Escape email when building the Stripe search query
If an email contains a single quote ('), the query will break. UseencodeURIComponentor Stripe’s parameterized search filters instead of string interpolation.- query: `email:'${customer.email}'`, + query: `email:"${customer.email.replace(/"/g, '\\"')}"`,apps/web/lib/types.ts (1)
162-166: Reintroduceidondomainsor update alldomain.idreferencesRemoving the
idfield fromWorkspaceProps.domainsbreaks several active code paths that still expectdomain.id. You must either restoreid: stringin the domain type or refactor these usages to use another identifier (e.g.slug).Affected locations:
- apps/web/ui/links/use-available-domains.ts
• Line whereactiveDefaultDomains.some(({ id }) => id === domain.id)- apps/web/scripts/migrate-domains.ts
• Returning{ id: domain.id, … }- apps/web/app/api/workspaces/[idOrSlug]/import/rebrandly/route.ts
• Query string interpolation:?domain.id=${id}Please address these breaks before merging.
🧹 Nitpick comments (7)
apps/web/scripts/stripe/update-stripe-customers.ts (1)
33-83: Consider batching requests to improve throughput
The script makes one network round-trip per customer. UsingPromise.allin small batches or Stripe’s bulk retrieval (if available) will cut runtime significantly for large customer sets.packages/ui/src/icons/nucleo/infinity-icon.tsx (1)
12-20: Redundantfillattribute on wrapping<g>
<g fill="currentColor">is unnecessary because the nested<path>setsfill="none". Dropping the redundant attribute slightly reduces markup noise and eliminates confusion about intended fill behavior.- <g fill="currentColor"> + <g>apps/web/app/(ee)/api/partners/links/upsert/route.ts (1)
100-101: Whitespace-only change — consider squashingThis blank line has no functional impact but adds noise to
git blame. Unless intentional for readability, consider reverting or squashing with a future change.apps/web/lib/swr/use-domains.ts (1)
25-27: Verify type consistency with schema definition.The type extension correctly adds
linkRetentionDaysto the domain objects. However, consider whether the optional property (?) aligns with the schema'snullish()definition, which allowsnullvalues in addition toundefined.Consider making the type more explicit to match the schema:
- const { data, error, mutate } = useSWR< - (DomainProps & { linkRetentionDays?: number })[] - >( + const { data, error, mutate } = useSWR< + (DomainProps & { linkRetentionDays?: number | null })[] + >(apps/web/scripts/convert-case-sensitive.ts (1)
38-44: Consider making the key length assumption more robust.The assumption that keys longer than 7 characters are already encoded might not always be accurate. Consider adding additional validation or making this configurable.
- if (link.key.length > 7) { + if (link.key.length > 7 || link.key.includes('=')) { console.log( - `Skipping link ${link.id} because key length is greater than 7 (already encoded)`, + `Skipping link ${link.id} because it appears to be already encoded`, ); return; }apps/web/app/(ee)/api/cron/link-retention-cleanup/route.ts (2)
22-30: Consider adding database index for performance.The query filters domains by
linkRetentionDays: { not: null }. For optimal performance, ensure there's a database index on thelinkRetentionDayscolumn.#!/bin/bash # Description: Check if there's an index on linkRetentionDays in the Prisma schema # Expected: Should find index definition for linkRetentionDays # Search for domain schema and index definitions ast-grep --pattern 'model Domain { $$$ }' # Look for index definitions rg -A 5 -B 5 "linkRetentionDays.*index|@@index.*linkRetentionDays" --type prisma
126-133: Consider the commented concern about Tinybird storage.The comment raises a valid question about whether to delete records from Tinybird entirely versus marking them as deleted. This affects analytics history and storage costs.
Consider documenting the decision rationale or implementing a configurable approach for Tinybird record handling based on business requirements.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (23)
apps/web/app/(ee)/api/cron/link-retention-cleanup/route.ts(1 hunks)apps/web/app/(ee)/api/partners/links/upsert/route.ts(1 hunks)apps/web/app/api/links/[linkId]/route.ts(2 hunks)apps/web/app/api/workspaces/[idOrSlug]/route.ts(1 hunks)apps/web/lib/api/links/case-sensitivity.ts(1 hunks)apps/web/lib/swr/use-domains.ts(1 hunks)apps/web/lib/swr/use-workspace.ts(2 hunks)apps/web/lib/types.ts(1 hunks)apps/web/lib/zod/schemas/links.ts(1 hunks)apps/web/lib/zod/schemas/workspaces.ts(1 hunks)apps/web/scripts/convert-case-sensitive.ts(1 hunks)apps/web/scripts/stripe/update-stripe-customers.ts(1 hunks)apps/web/tests/utils/schema.ts(2 hunks)apps/web/ui/links/link-builder/constants.ts(3 hunks)apps/web/ui/links/link-builder/link-feature-buttons.tsx(1 hunks)apps/web/ui/links/link-builder/more-dropdown.tsx(6 hunks)apps/web/ui/links/link-builder/options-list.tsx(2 hunks)apps/web/vercel.json(1 hunks)packages/prisma/schema/domain.prisma(1 hunks)packages/prisma/schema/link.prisma(3 hunks)packages/ui/src/icons/nucleo/index.ts(1 hunks)packages/ui/src/icons/nucleo/infinity-icon.tsx(1 hunks)packages/ui/src/tooltip.tsx(1 hunks)
🧰 Additional context used
🧠 Learnings (15)
apps/web/app/(ee)/api/partners/links/upsert/route.ts (1)
Learnt from: devkiran
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.
apps/web/lib/zod/schemas/links.ts (1)
Learnt from: devkiran
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.
apps/web/app/api/links/[linkId]/route.ts (1)
Learnt from: devkiran
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.
packages/ui/src/icons/nucleo/infinity-icon.tsx (1)
Learnt from: TWilson023
PR: #2614
File: apps/web/ui/partners/design/previews/lander-preview.tsx:181-181
Timestamp: 2025-07-09T20:52:56.592Z
Learning: In apps/web/ui/partners/design/previews/lander-preview.tsx, the ellipsis wave animation delay calculation 3 - i * -0.15 is intentionally designed to create negative delays that offset each dot's animation cycle. This pattern works correctly for the intended ellipsis effect and should not be changed to positive incremental delays.
apps/web/tests/utils/schema.ts (1)
Learnt from: devkiran
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.
packages/prisma/schema/link.prisma (1)
Learnt from: devkiran
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.
apps/web/scripts/convert-case-sensitive.ts (2)
Learnt from: devkiran
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.
Learnt from: devkiran
PR: #2637
File: apps/web/app/(ee)/api/singular/webhook/route.ts:0-0
Timestamp: 2025-07-17T06:41:45.598Z
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.
apps/web/app/(ee)/api/cron/link-retention-cleanup/route.ts (1)
Learnt from: devkiran
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.
apps/web/lib/types.ts (1)
Learnt from: TWilson023
PR: #2538
File: apps/web/ui/partners/overview/blocks/commissions-block.tsx:16-27
Timestamp: 2025-06-18T20:26:25.177Z
Learning: In the Dub codebase, components that use workspace data (workspaceId, defaultProgramId) are wrapped in WorkspaceAuth which ensures these values are always available, making non-null assertions safe. This is acknowledged as a common pattern in their codebase, though not ideal.
apps/web/app/api/workspaces/[idOrSlug]/route.ts (2)
Learnt from: devkiran
PR: #2433
File: apps/web/ui/modals/add-payment-method-modal.tsx:60-62
Timestamp: 2025-05-29T09:49:19.604Z
Learning: The /api/workspaces/${slug}/billing/payment-methods POST endpoint in the billing API returns either an error (handled by response.ok check) or a response object containing a url property for successful requests.
Learnt from: devkiran
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.
apps/web/lib/swr/use-workspace.ts (1)
Learnt from: TWilson023
PR: #2538
File: apps/web/ui/partners/overview/blocks/commissions-block.tsx:16-27
Timestamp: 2025-06-18T20:26:25.177Z
Learning: In the Dub codebase, components that use workspace data (workspaceId, defaultProgramId) are wrapped in WorkspaceAuth which ensures these values are always available, making non-null assertions safe. This is acknowledged as a common pattern in their codebase, though not ideal.
apps/web/ui/links/link-builder/options-list.tsx (1)
Learnt from: TWilson023
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.
apps/web/ui/links/link-builder/constants.ts (2)
Learnt from: devkiran
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.
Learnt from: devkiran
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.
apps/web/lib/api/links/case-sensitivity.ts (2)
Learnt from: devkiran
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.
Learnt from: devkiran
PR: #2637
File: apps/web/app/(ee)/api/singular/webhook/route.ts:0-0
Timestamp: 2025-07-17T06:41:45.598Z
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.
apps/web/scripts/stripe/update-stripe-customers.ts (1)
Learnt from: TWilson023
PR: #2538
File: apps/web/ui/partners/overview/blocks/commissions-block.tsx:16-27
Timestamp: 2025-06-18T20:26:25.177Z
Learning: In the Dub codebase, components that use workspace data (workspaceId, defaultProgramId) are wrapped in WorkspaceAuth which ensures these values are always available, making non-null assertions safe. This is acknowledged as a common pattern in their codebase, though not ideal.
🧬 Code Graph Analysis (4)
apps/web/app/api/links/[linkId]/route.ts (1)
apps/web/lib/zod/schemas/links.ts (1)
updateLinkBodySchemaExtended(467-469)
apps/web/ui/links/link-builder/link-feature-buttons.tsx (1)
apps/web/ui/links/link-builder/more-dropdown.tsx (1)
MoreDropdown(18-178)
apps/web/lib/swr/use-domains.ts (1)
apps/web/lib/types.ts (1)
DomainProps(216-231)
apps/web/lib/swr/use-workspace.ts (1)
apps/web/lib/types.ts (1)
ExtendedWorkspaceProps(177-186)
⏰ 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 (39)
apps/web/vercel.json (1)
50-54: Verify 1-minute cron interval for retention cleanupRunning link-retention cleanup every minute may cause unnecessary load and higher invocations cost. Double-check expected volume and adjust to a coarser cadence (e.g., hourly) if real-time cleanup isn’t required.
packages/ui/src/icons/nucleo/index.ts (1)
131-131: Export looks good
InfinityIconis correctly re-exported, maintaining alphabetic order. No further action needed.apps/web/lib/swr/use-workspace.ts (1)
1-1: Type alias update aligns with new schemaRenaming to
ExtendedWorkspacePropsand updating the SWR generic keeps typings consistent with the enriched workspace shape. ✅Also applies to: 21-22
packages/prisma/schema/domain.prisma (1)
12-12: LGTM: Clear schema addition for link retention feature.The new
linkRetentionDaysfield is well-designed with appropriate nullability and clear documentation of the default behavior. This supports the domain-level link retention policy implementation.apps/web/app/api/links/[linkId]/route.ts (1)
14-17: LGTM: Clean schema extension for link retention feature.The change appropriately extends the validation schema to support the new
linkRetentionCleanupDisabledAtfield while maintaining all existing functionality. The import and usage are correctly updated.Also applies to: 81-83
apps/web/lib/zod/schemas/links.ts (1)
467-469: LGTM: Appropriate schema extension for retention cleanup control.The extended schema cleanly adds the
linkRetentionCleanupDisabledAtfield with appropriate typing (string().nullish()) for optional timestamp values. This follows established patterns in the codebase.apps/web/ui/links/link-builder/link-feature-buttons.tsx (1)
47-47: LGTM: Proper variant prop propagation.The
variantprop is correctly passed to theMoreDropdowncomponent, enabling context-aware option filtering for the link retention feature.apps/web/app/api/workspaces/[idOrSlug]/route.ts (1)
28-28: LGTM: Domain data extended for retention feature support.The addition of
idandlinkRetentionDaysfields to the domain selection appropriately extends the workspace API to support the new link retention cleanup functionality. These fields will be needed by frontend components to manage retention settings.Also applies to: 32-32
apps/web/lib/zod/schemas/workspaces.ts (1)
163-167: LGTM! Schema extension is well-implemented.The addition of
linkRetentionDaysas a nullable number field to the domains array is correctly implemented usingnullish(), which appropriately handles the optional nature of this retention policy field.apps/web/lib/api/links/case-sensitivity.ts (1)
76-82: Excellent refactor to eliminate mutation.The change from mutating the input
linkobject to returning a new object with spread syntax is a great improvement. This follows immutability principles and eliminates potential side effects, making the function more predictable and safer to use.apps/web/tests/utils/schema.ts (2)
8-8: Test schema properly extended.The addition of
linkRetentionCleanupDisabledAtfield to the test schema is correctly implemented and aligns with the broader feature implementation.
62-62: Test expectation correctly updated.The
expectedLinkobject properly includes the new field with anulldefault value, maintaining consistency with the schema definition.packages/ui/src/tooltip.tsx (2)
136-137: Good improvement to component flexibility.Making
ctaandhrefoptional props increases the component's reusability and prevents potential issues with undefined values.
141-155: Proper conditional rendering implementation.The updated logic correctly renders the title always and only shows the CTA link when both
ctaandhrefare provided. This prevents rendering incomplete links and improves the component's robustness.apps/web/ui/links/link-builder/options-list.tsx (3)
25-31: Enhanced filtering logic looks well-implemented.The updated filtering logic correctly supports both the new
enabledfunction approach and the legacydata[key]truthiness check, maintaining backward compatibility while enabling more sophisticated toggle state determination.
65-70: Conditional prop spreading is clean and follows good patterns.The conditional spreading of props based on the
enabledfunction result is well-structured and allows for dynamic icon assignment based on toggle state.
1-83: Inconsistency between PR title and implemented changes.The PR title indicates "Fix decode" but the changes implement link retention functionality. This appears to be an inconsistency between the stated objectives and actual implementation.
Likely an incorrect or invalid review comment.
apps/web/scripts/convert-case-sensitive.ts (2)
9-19: Improved filtering logic with proper typing.The typed
whereobject and additional filtering criteria (date-based and excluding already encoded keys) are well-designed improvements that prevent unnecessary processing.
29-35: Good addition of progress reporting.The remaining links count provides valuable feedback during script execution, especially useful for large-scale operations.
packages/prisma/schema/link.prisma (3)
28-28: Well-designed field addition for retention feature.The
linkRetentionCleanupDisabledAtfield is appropriately typed as optional DateTime and has a clear, descriptive name that indicates its purpose for tracking when retention cleanup was explicitly disabled.
76-77: Good organizational improvement.Moving the
programIdfield and its relation together improves the schema organization and readability.
90-90: Enhanced index documentation.The updated comment for the
[domain, createdAt]index clearly explains its usage for bulk link deletion workflows and deleting old short-lived links, which is helpful for maintenance.apps/web/ui/links/link-builder/constants.ts (3)
17-17: Appropriate import addition.The
UseFormSetValueimport is correctly added to support the new callback functionality.
29-31: Well-designed type extensions.The optional
enableandremovecallbacks are properly typed and extend theMoreIteminterface cleanly to support dynamic toggle state management.
55-69: Excellent implementation of the permanent retention feature.The new "Permanent Retention" item is well-designed with:
- Appropriate InfinityIcon for the concept
- Clear description explaining its purpose
- Proper enabled function checking
linkRetentionCleanupDisabledAt- Correct enable/remove callbacks using
setValuewithshouldDirty: trueapps/web/lib/types.ts (1)
177-186: Well-structured type enhancements for retention feature.The new
ExtendedWorkspacePropsinterface properly extendsWorkspacePropsand adds the necessarylinkRetentionDaysfield to support the retention functionality. The additional fields (defaultProgramId,allowedHostnames,workspacePreferences) enhance the workspace data model appropriately.apps/web/ui/links/link-builder/more-dropdown.tsx (6)
18-22: LGTM! Clean component interface extension.The addition of the optional
variantprop with sensible defaults follows good TypeScript practices.
35-40: Well-implemented conditional filtering logic.The filtering logic properly checks for domain-specific
linkRetentionDaysconfiguration and restricts the link retention cleanup option to the page variant only. This provides appropriate context-aware functionality.
69-77: Robust callback handling for enable/remove actions.The enhanced keyboard shortcut handler properly checks for the existence of
enableandremovecallbacks before invoking them, providing a clean extension point for different option types.
110-117: Consistent click handler implementation.The click handler mirrors the keyboard shortcut logic, ensuring consistent behavior across interaction methods. The callback pattern is well-implemented.
148-151: Smart conditional rendering for learn more links.The conditional rendering of the "Learn more" CTA only when
learnMoreUrlis provided prevents broken or empty links, improving user experience.
23-23: No action needed:useWorkspacealready exposesdomains.linkRetentionDays
The hook spreadsExtendedWorkspaceProps(which includesdomains: DomainProps[]), andDomainPropsdefineslinkRetentionDays: number | nullso
domains?.find(...).linkRetentionDaysis correctly typed.apps/web/app/(ee)/api/cron/link-retention-cleanup/route.ts (7)
12-12: Good choice for dynamic execution.The
force-dynamicexport ensures this cron endpoint executes dynamically on each request, which is appropriate for cleanup operations that need fresh data.
60-61: Well-chosen batch processing limits.The constants
LINKS_PER_BATCH = 100andMAX_LINK_BATCHES = 10provide reasonable limits to prevent memory issues while ensuring efficient processing.
66-71: Robust input validation and early returns.The function properly validates the domain has required fields and positive retention days before proceeding. This prevents unnecessary processing and potential errors.
77-91: Efficient query with proper filtering.The query correctly filters by domain, creation date, and cleanup exemption status. The ordering by
createdAt: "asc"ensures oldest links are processed first, which is logical for retention cleanup.
108-124: Proper transaction handling for data consistency.The transaction ensures atomic deletion of links and decrementing of the project's total link count. This prevents data inconsistency if either operation fails.
144-152: Smart scheduling logic prevents infinite loops.The condition
processedBatches >= MAX_LINK_BATCHES && hasMoreLinksproperly ensures continuation only when necessary, preventing both infinite scheduling and premature termination.
1-156: Flag inconsistency between PR title and implementation.The PR is titled "Fix decode" but implements link retention cleanup functionality. This suggests either an incorrect PR title or mismatched objectives.
Please verify that this PR has the correct title and objectives, as the implemented functionality doesn't appear related to "decode" operations.
Likely an incorrect or invalid review comment.
| const { domain: passedDomain } = z | ||
| .object({ | ||
| domain: z.string(), | ||
| }) | ||
| .parse(JSON.parse(rawBody)); | ||
|
|
||
| const domain = await prisma.domain.findUniqueOrThrow({ | ||
| where: { | ||
| slug: passedDomain, | ||
| }, | ||
| }); |
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.
🛠️ Refactor suggestion
Potential error handling issue with findUniqueOrThrow.
Using findUniqueOrThrow will cause the entire cron job to fail if a domain doesn't exist. Consider whether this should be a soft failure that logs the error but continues processing.
- const domain = await prisma.domain.findUniqueOrThrow({
+ const domain = await prisma.domain.findUnique({
where: {
slug: passedDomain,
},
});
+
+ if (!domain) {
+ console.warn(`Domain ${passedDomain} not found, skipping cleanup`);
+ return NextResponse.json("Domain not found");
+ }📝 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.
| const { domain: passedDomain } = z | |
| .object({ | |
| domain: z.string(), | |
| }) | |
| .parse(JSON.parse(rawBody)); | |
| const domain = await prisma.domain.findUniqueOrThrow({ | |
| where: { | |
| slug: passedDomain, | |
| }, | |
| }); | |
| const { domain: passedDomain } = z | |
| .object({ | |
| domain: z.string(), | |
| }) | |
| .parse(JSON.parse(rawBody)); | |
| const domain = await prisma.domain.findUnique({ | |
| where: { | |
| slug: passedDomain, | |
| }, | |
| }); | |
| if (!domain) { | |
| console.warn(`Domain ${passedDomain} not found, skipping cleanup`); | |
| return NextResponse.json("Domain not found"); | |
| } |
🤖 Prompt for AI Agents
In apps/web/app/(ee)/api/cron/link-retention-cleanup/route.ts around lines 39 to
49, the use of findUniqueOrThrow causes the cron job to fail completely if the
domain is not found. Modify the code to use findUnique instead, then check if
the result is null. If null, log an error message and continue processing
without throwing, to allow the cron job to handle missing domains gracefully.
| where: { | ||
| domain: "domain.com", | ||
| const where: Prisma.LinkWhereInput = { | ||
| domain: "domain.com", |
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.
🛠️ Refactor suggestion
Make domain configurable for production use.
The hardcoded domain "domain.com" should be made configurable to support different environments and use cases.
+const DOMAIN = process.env.TARGET_DOMAIN || "domain.com";
+
const where: Prisma.LinkWhereInput = {
- domain: "domain.com",
+ domain: DOMAIN,📝 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.
| domain: "domain.com", | |
| // Make the target domain configurable via environment variable | |
| const DOMAIN = process.env.TARGET_DOMAIN || "domain.com"; | |
| const where: Prisma.LinkWhereInput = { | |
| domain: DOMAIN, | |
| // …other filters | |
| }; |
🤖 Prompt for AI Agents
In apps/web/scripts/convert-case-sensitive.ts at line 10, the domain is
hardcoded as "domain.com", which limits flexibility for different environments.
Modify the code to read the domain value from a configuration source such as an
environment variable or a config file, allowing it to be set dynamically for
production and other use cases.
| where: { | ||
| id: "xxx", | ||
| id: "ws_1JRV43Y6B85PGH7B54KA79M81", | ||
| }, | ||
| }); |
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.
💡 Verification agent
❓ Verification inconclusive
Avoid hard-coding workspace IDs — parameterize via env/CLI instead
Embedding a production workspace ID directly in source control is brittle and can lead to accidental data corruption if this script is copied to other environments. Surface the ID as an environment variable or CLI flag so it can be swapped safely at runtime.
- id: "ws_1JRV43Y6B85PGH7B54KA79M81",
+ // e.g. export WORKSPACE_ID=ws_...
+ id: process.env.WORKSPACE_ID!,Parameterize the workspace ID in update-stripe-customers.ts
Hard-coding a production workspace ID in this script is brittle and risks accidental data corruption across environments. Load the ID from an environment variable or accept it as a CLI flag.
Affected file:
- apps/web/scripts/stripe/update-stripe-customers.ts
Suggested fix:
@@ apps/web/scripts/stripe/update-stripe-customers.ts
- where: {
- id: "ws_1JRV43Y6B85PGH7B54KA79M81",
- },
+ // e.g. export WORKSPACE_ID=ws_...
+ const workspaceId = process.env.WORKSPACE_ID!;
+ where: { id: workspaceId },Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In apps/web/scripts/stripe/update-stripe-customers.ts around lines 8 to 11, the
workspace ID is hard-coded, which is risky for production use. Modify the script
to load the workspace ID from an environment variable or accept it as a
command-line argument instead of hard-coding it. Update the code to read the
workspace ID dynamically and use that variable in the query to ensure safer and
more flexible execution across environments.
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Chores