Skip to content

Improve POST /links endpoint performance #2177

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

Open
wants to merge 33 commits into
base: main
Choose a base branch
from

Conversation

devkiran
Copy link
Collaborator

@devkiran devkiran commented Mar 18, 2025

Summary by CodeRabbit

  • New Features

    • Improved bulk link creation now explicitly detects and reports duplicate short links, providing separate lists of valid and invalid links.
    • Added retry logic for creating links with randomly generated keys to reduce conflicts and improve reliability.
  • Bug Fixes

    • Enhanced error handling for link creation and updates, with clearer conflict and validation error responses when duplicate short links are detected.
    • Improved reporting of failed bulk link imports, distinguishing between successful and failed link creations.
  • Refactor

    • Simplified error handling in several link-related endpoints for more transparent error propagation.
    • Streamlined key generation logic for short links, removing unnecessary existence checks for faster performance.

Copy link

vercel bot commented Mar 18, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
dub ✅ Ready (Inspect) Visit Preview Jun 7, 2025 4:27am

@devkiran devkiran marked this pull request as ready for review March 22, 2025 12:50
@devkiran devkiran requested a review from steven-tey March 22, 2025 12:50
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR improves the performance and reliability of the POST /links endpoint by refining link creation flows and error handling. Key changes include:

  • Updating the sitemap importer to log valid and invalid links separately.
  • Refactoring key generation functions (removing asynchronous duplicate checks) and introducing a retry mechanism.
  • Enhancing bulk link creation to identify and separate duplicate links.

Reviewed Changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated no comments.

Show a summary per file
File Description
apps/web/scripts/sitemap-importer.ts Updates logging to display separate validLinks/invalidLinks from bulkCreateLinks.
apps/web/lib/planetscale/index.ts Removed redundant export for key existence check.
apps/web/lib/planetscale/get-random-key.ts Removed duplicate key checking to delegate that responsibility; now returns a new random key directly.
apps/web/lib/api/links/utils/key-checks.ts Removed dependency on checkIfKeyExists to streamline key validation.
apps/web/lib/api/links/update-link.ts, create-link.ts Added try-catch blocks to wrap Prisma update/create calls with custom error messages.
apps/web/lib/api/links/create-link-with-key-retry.ts New retry functionality for handling duplicate key (P2002) errors.
apps/web/lib/api/links/bulk-create-links.ts Improved duplicate link detection and separation of valid and invalid links.
apps/web/lib/api/errors.ts Simplified logging of error messages.
apps/web/app/api/links/* Streamlined API routes to use the new key retry and bulk creation logic.
Comments suppressed due to low confidence (2)

apps/web/lib/planetscale/get-random-key.ts:8

  • Removing duplicate key checking from getRandomKey shifts the responsibility of handling duplicates to the caller. Please ensure that the new retry mechanism (in createLinkWithKeyRetry) reliably catches and resolves conflicts.
-  const exists = await checkIfKeyExists({ domain, key });

apps/web/lib/api/links/bulk-create-links.ts:77

  • [nitpick] The use of Array.find to map each duplicate link assumes that there is at most one occurrence per duplicate key. If duplicated entries in the incoming links array are possible, consider handling multiple occurrences explicitly.
link: links.find((l) => existingLink.shortLink === linkConstructorSimple({ domain: l.domain, key: l.key })) as ProcessedLinkProps,

Copy link
Contributor

coderabbitai bot commented Jun 6, 2025

Walkthrough

This update refactors link creation and update flows to improve error handling, duplicate detection, and key generation. It introduces a retry mechanism for random key generation, removes database existence checks for keys, and changes several API handlers to let errors propagate naturally. Return types and logging are updated to distinguish valid and invalid link creations.

Changes

File(s) Change Summary
apps/web/app/api/links/[linkId]/route.ts,
apps/web/app/api/links/upsert/route.ts,
apps/web/app/api/links/route.ts
Removed try-catch error wrapping in link update/create handlers; errors now propagate naturally.
apps/web/app/api/links/bulk/route.ts,
apps/web/scripts/sitemap-importer.ts
Updated bulk link creation to handle and log valid/invalid links separately.
apps/web/app/api/links/random/route.ts,
apps/web/lib/api/links/process-link.ts
Removed await from getRandomKey calls; now returns promise or value directly.
apps/web/lib/api/errors.ts Simplified error logging by removing static prefix from logs.
apps/web/lib/api/links/bulk-create-links.ts Added explicit duplicate detection; now returns { validLinks, invalidLinks } object.
apps/web/lib/api/links/create-link-with-key-retry.ts Introduced new function for link creation with retry logic on random key conflicts.
apps/web/lib/api/links/create-link.ts,
apps/web/lib/api/links/update-link.ts
Added explicit Prisma error handling for unique constraint violations and other errors.
apps/web/lib/api/links/utils/key-checks.ts Removed check for existing short link key in database.
apps/web/lib/planetscale/check-if-key-exists.ts,
apps/web/lib/planetscale/index.ts
Removed key existence check utility and its export.
apps/web/lib/planetscale/get-random-key.ts Refactored to a synchronous function; removed domain parameter and key existence checks.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API_Handler
    participant createLinkWithKeyRetry
    participant createLink
    participant getRandomKey

    Client->>API_Handler: POST /api/links (with link data)
    API_Handler->>createLinkWithKeyRetry: createLinkWithKeyRetry({ link, isRandomKey })
    alt isRandomKey
        loop up to maxRetries
            createLinkWithKeyRetry->>createLink: createLink(link)
            alt P2002 unique constraint error
                createLinkWithKeyRetry->>getRandomKey: getRandomKey({ prefix, long })
                createLinkWithKeyRetry->>createLink: createLink(link with new key)
            else Other error
                createLinkWithKeyRetry->>API_Handler: throw error
            end
        end
        createLinkWithKeyRetry->>API_Handler: throw 409 if retries exhausted
    else user-specified key
        createLinkWithKeyRetry->>createLink: createLink(link)
        alt P2002 unique constraint error
            createLinkWithKeyRetry->>API_Handler: throw 409 conflict
        else Other error
            createLinkWithKeyRetry->>API_Handler: throw error
        end
    end
    API_Handler->>Client: Return created link or error
Loading
sequenceDiagram
    participant Client
    participant API_BulkHandler
    participant bulkCreateLinks
    participant DB

    Client->>API_BulkHandler: POST /api/links/bulk (with links)
    API_BulkHandler->>bulkCreateLinks: bulkCreateLinks({ links })
    bulkCreateLinks->>DB: Query for existing short links
    alt Duplicates found
        bulkCreateLinks->>API_BulkHandler: Return { validLinks, invalidLinks }
    else No duplicates
        bulkCreateLinks->>DB: Create new links
        bulkCreateLinks->>API_BulkHandler: Return { validLinks, invalidLinks }
    end
    API_BulkHandler->>Client: Return valid and invalid link lists
Loading

Suggested reviewers

  • steven-tey

Poem

A bunny with code in its paws,
Hopped through the links without pause.
With keys now retried,
And errors supplied,
Duplicates flagged—what a cause!
Bulk or unique, each link finds its fate,
In this garden of APIs, things look great!
🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c0dd26e and 3b36cd8.

📒 Files selected for processing (1)
  • apps/web/lib/api/links/bulk-create-links.ts (5 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
apps/web/lib/api/links/bulk-create-links.ts (2)
apps/web/lib/types.ts (1)
  • ProcessedLinkProps (254-258)
apps/web/lib/api/links/utils/transform-link.ts (1)
  • transformLink (20-44)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (6)
apps/web/lib/api/links/bulk-create-links.ts (6)

25-30: LGTM! Clean early return with new structure.

The new return structure clearly separates valid and invalid links, improving API clarity.


86-95: Filtering logic looks correct.

The filtering correctly removes existing links using consistent logic with the duplicate detection above.


96-105: Good map maintenance and edge case handling.

Properly cleans up the map and handles the case where all input links are duplicates.


185-196: Excellent fix for the ordering bug!

Using shortLinkToIndexMap.get() with proper undefined checks addresses the previous ordering concerns and ensures tags are attached to the correct links.


236-247: Consistent improvement for webhook handling.

Same excellent pattern as the tag handling - using the map lookup with proper undefined checks.


312-317: Clean structured return aligns with PR objectives.

The new return structure clearly separates valid and invalid links, improving error handling and API transparency.

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 5

🔭 Outside diff range comments (1)
apps/web/lib/api/links/bulk-create-links.ts (1)

18-30: 🛠️ Refactor suggestion

Specify an explicit return type for the new response shape

The function’s return signature changed from an array to an object but no explicit Promise<…> type is declared.
This relies on inference and risks breaking downstream callers silently compiled to any, while callers that still expect an array will now fail at runtime instead of compile-time.

+type BulkCreateLinksResult = {
+  validLinks: ProcessedLinkProps[];
+  invalidLinks: {
+    error: string;
+    code: string;
+    link: ProcessedLinkProps;
+  }[];
+};
+
-export async function bulkCreateLinks({ … }: { … }) {
+export async function bulkCreateLinks({ … }: { … }): Promise<BulkCreateLinksResult> {
🧹 Nitpick comments (5)
apps/web/lib/api/links/update-link.ts (1)

170-170: Simplify unnecessary ternary expression.

The static analysis tool correctly identified an unnecessary boolean literal in the conditional expression.

-        webhooks: webhookIds ? true : false,
+        webhooks: !!webhookIds,

Or more simply, if webhookIds is always a boolean context:

-        webhooks: webhookIds ? true : false,
+        webhooks: Boolean(webhookIds),
🧰 Tools
🪛 Biome (1.9.4)

[error] 170-170: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

apps/web/lib/api/links/create-link.ts (1)

136-136: Simplify boolean ternary expression.

The ternary operator is unnecessary when the result is already boolean.

-webhooks: webhookIds ? true : false,
+webhooks: !!webhookIds,

Or even simpler if webhookIds is expected to be truthy/falsy:

-webhooks: webhookIds ? true : false,
+webhooks: Boolean(webhookIds),
🧰 Tools
🪛 Biome (1.9.4)

[error] 136-136: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

apps/web/lib/api/links/create-link-with-key-retry.ts (1)

48-54: Consider immutable link updates and type safety.

The current implementation mutates the original link object, which could be unexpected behavior. Also, the bracket notation for accessing prefix suggests it might not be a direct property.

-// Otherwise, generate a new random key and retry
-const newKey = getRandomKey({
-  prefix: link["prefix"],
-  long: link.domain === "loooooooo.ng",
-});
-
-link = { ...link, key: newKey };
+// Otherwise, generate a new random key and retry
+const newKey = getRandomKey({
+  prefix: link.prefix,
+  long: link.domain === "loooooooo.ng",
+});
+
+link = { ...link, key: newKey };

This change assumes prefix is a proper property of ProcessedLinkProps. If it's not, consider adding it to the type definition for better type safety.

apps/web/lib/api/links/bulk-create-links.ts (2)

53-65: Remove the take clause – it risks missing duplicates

take: shortLinkToIndexMap.size limits the number of rows Prisma returns.
If two rows share the same shortLink (unlikely but possible due to DB corruption or race), one duplicate might be skipped, leading to a false “valid” link that later violates a unique constraint.

Simply omitting take lets the DB return all matches and is still bounded by IN (...), so the query remains performant.


294-299: Minor: avoid repeated transformLink allocations

transformLink is called for every link even when it already returns a ProcessedLinkProps.
If it’s an identity function for most fields, consider mapping once during createdLinksData construction to cut an extra loop.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 74bc6a7 and 3b1ca1a.

📒 Files selected for processing (16)
  • apps/web/app/api/links/[linkId]/route.ts (1 hunks)
  • apps/web/app/api/links/bulk/route.ts (1 hunks)
  • apps/web/app/api/links/random/route.ts (1 hunks)
  • apps/web/app/api/links/route.ts (3 hunks)
  • apps/web/app/api/links/upsert/route.ts (1 hunks)
  • apps/web/lib/api/errors.ts (1 hunks)
  • apps/web/lib/api/links/bulk-create-links.ts (3 hunks)
  • apps/web/lib/api/links/create-link-with-key-retry.ts (1 hunks)
  • apps/web/lib/api/links/create-link.ts (2 hunks)
  • apps/web/lib/api/links/process-link.ts (1 hunks)
  • apps/web/lib/api/links/update-link.ts (2 hunks)
  • apps/web/lib/api/links/utils/key-checks.ts (0 hunks)
  • apps/web/lib/planetscale/check-if-key-exists.ts (0 hunks)
  • apps/web/lib/planetscale/get-random-key.ts (1 hunks)
  • apps/web/lib/planetscale/index.ts (0 hunks)
  • apps/web/scripts/sitemap-importer.ts (1 hunks)
💤 Files with no reviewable changes (3)
  • apps/web/lib/planetscale/index.ts
  • apps/web/lib/api/links/utils/key-checks.ts
  • apps/web/lib/planetscale/check-if-key-exists.ts
🧰 Additional context used
🪛 Biome (1.9.4)
apps/web/lib/api/links/create-link.ts

[error] 136-136: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

apps/web/lib/api/links/update-link.ts

[error] 170-170: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (13)
apps/web/lib/api/errors.ts (1)

125-125: LGTM: Cleaner error logging

Removing the static prefix makes error logs more concise and readable while maintaining the essential error information.

apps/web/lib/api/links/process-link.ts (1)

257-260:

✅ Verification successful

Verify that getRandomKey is now synchronous

The removal of await aligns with the performance optimization to eliminate upfront database existence checks. This should improve endpoint performance by generating keys synchronously.


🏁 Script executed:

#!/bin/bash
# Verify that getRandomKey function is now synchronous
ast-grep --pattern 'export function getRandomKey($_) {
  $$$
}'

Length of output: 978


Approved: getRandomKey is synchronous

Verified that getRandomKey in apps/web/lib/planetscale/get-random-key.ts is defined as a regular (non-async) function, so removing the await on its call is correct.

apps/web/app/api/links/random/route.ts (1)

20-22: LGTM: Consistent with getRandomKey synchronization

The removal of await is consistent with the performance optimization to make key generation synchronous.

apps/web/app/api/links/[linkId]/route.ts (1)

172-191: LGTM: Simplified error handling architecture

The removal of the try-catch block allows errors to propagate naturally from updateLink, which now handles Prisma constraint violations internally. This centralizes error handling and simplifies the control flow.

apps/web/scripts/sitemap-importer.ts (1)

62-68: LGTM! Clean adaptation to the new bulkCreateLinks interface.

The destructuring of the response into validLinks and invalidLinks arrays properly aligns with the updated API structure, and the enhanced logging provides better visibility into the bulk creation results.

apps/web/app/api/links/bulk/route.ts (1)

248-257: Improved error handling for bulk creation results.

The refactored response handling properly merges invalid links from bulkCreateLinks into the error list, ensuring that duplicates and validation failures detected during bulk creation are correctly reported to the client.

apps/web/app/api/links/route.ts (1)

104-104: LGTM! Clean extraction of key for retry logic.

The explicit extraction of the key variable improves readability for the subsequent createLinkWithKeyRetry call.

apps/web/lib/api/links/update-link.ts (1)

85-187: Excellent centralized error handling for database operations.

The explicit error handling for Prisma operations is well-structured:

  • Specific handling for unique constraint violations (P2002) with appropriate "conflict" error
  • Generic fallback for other database errors with "unprocessable_entity"

This aligns perfectly with the PR objective of letting errors propagate naturally while providing meaningful error codes.

🧰 Tools
🪛 Biome (1.9.4)

[error] 170-170: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

apps/web/app/api/links/upsert/route.ts (1)

146-163: LGTM: Simplified error handling.

Removing the try-catch blocks and letting errors propagate naturally from the underlying updateLink function is a good simplification that aligns with the improved error handling strategy.

apps/web/lib/planetscale/get-random-key.ts (1)

3-17: LGTM: Performance improvement through simplification.

The conversion from async to sync function and removal of existence checks is an excellent performance optimization. This eliminates unnecessary database roundtrips during key generation, relying instead on the retry mechanism in createLinkWithKeyRetry to handle conflicts.

The prefix handling logic remains correct and the function is now more efficient.

apps/web/lib/api/links/create-link.ts (1)

55-153: LGTM: Well-implemented error handling for retry mechanism.

The try-catch block properly handles Prisma unique constraint violations (P2002) and converts them to DubApiError with appropriate codes. This enables the retry mechanism in createLinkWithKeyRetry to detect conflicts and retry with new keys.

The error handling is comprehensive and follows good practices by:

  • Specifically catching known Prisma errors
  • Providing meaningful error messages
  • Falling back to generic error handling for unexpected cases
🧰 Tools
🪛 Biome (1.9.4)

[error] 136-136: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

apps/web/lib/api/links/create-link-with-key-retry.ts (2)

23-59: LGTM: Well-implemented retry mechanism with good error handling.

The retry logic correctly handles unique constraint violations and distinguishes between user-specified and randomly generated keys. The implementation includes proper safeguards:

  • Only retries for randomly generated keys
  • Respects max retry limits
  • Provides meaningful error messages
  • Handles unexpected errors appropriately

61-62: Good defensive programming.

The fallback error case provides good protection against unexpected control flow, even though it should theoretically never be reached due to the while loop condition.

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: 0

🧹 Nitpick comments (1)
apps/web/tests/links/bulk-create-link.test.ts (1)

125-134: Thorough error response validation.

The error assertion comprehensively validates the expected response structure for duplicate key conflicts. The test checks:

  • Error code and message match expected values
  • Link details are preserved in the error response
  • Proper error categorization as "conflict"

One suggestion for future enhancement: Consider extracting the error message "Duplicate key: This short link already exists." into a constant to improve maintainability if this error format is used elsewhere.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3b1ca1a and a58deca.

📒 Files selected for processing (1)
  • apps/web/tests/links/bulk-create-link.test.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
apps/web/tests/links/bulk-create-link.test.ts (1)
apps/web/tests/utils/helpers.ts (1)
  • randomId (4-4)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (4)
apps/web/tests/links/bulk-create-link.test.ts (4)

71-84: LGTM! Well-structured test setup for duplicate key scenario.

The test correctly creates an initial link with a specific key that will be reused to test duplicate detection. The approach of extracting the key for later use is clean and follows good testing practices.


85-103: Comprehensive test coverage for bulk link creation scenarios.

The test data effectively covers all three important scenarios:

  1. Link without key (should auto-generate)
  2. Link with unique key (should succeed)
  3. Link with duplicate key (should fail)

This aligns well with the PR objective of improving duplicate detection handling.


111-115: Proper cleanup handling for the enhanced test.

The cleanup correctly includes both the initially created link and all bulk-created links, preventing test pollution and ensuring proper resource management.


119-124: Correctly adjusted verification logic.

The verification now only checks the first two successful links since the third is expected to be an error response. The use of slice(0, 2) is appropriate and maintains the existing verification logic for successful cases.

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.

2 participants