Skip to content
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

enhance(server): use native AbortController and AbortSignal #2031

Merged
merged 4 commits into from
Feb 5, 2025

Conversation

ardatan
Copy link
Owner

@ardatan ardatan commented Feb 5, 2025

Apparently in the benchmarks, no need to use a custom implementation for AbortSignal in the server-side Request.signal.
Also we don't need to introduce signals lazily as they are not expensive anymore.

Summary by CodeRabbit

  • Chores

    • Updated core dependencies for improved stability and performance.
  • Refactor

    • Streamlined request and stream cancellation handling by adopting a standardized native approach, ensuring more consistent and reliable behavior.
    • Simplified abort signal management across various components, enhancing clarity and efficiency.

Copy link

coderabbitai bot commented Feb 5, 2025

Walkthrough

The changes update dependency versions and streamline request cancellation across the project. Customized abort signal implementations have been removed in favor of the native AbortController. In the node-fetch package, the signal handling has been simplified by replacing lazy-initialized private properties with a public, consistently available signal. Similarly, server-side modules now adopt AbortController for managing abort events by updating interfaces, function signatures, and event listeners. These modifications result in a more uniform and concise approach to managing request cancellation and error handling.

Changes

File(s) Change Summary
.changeset/metal-moles-care.md Updated dependencies: @whatwg-node/server (minor) and @whatwg-node/node-fetch (patch); removed custom AbortSignal implementation.
packages/node-fetch/src/Request.ts, .../WritableStream.ts, .../fetchCurl.ts, .../fetchNodeHttp.ts Refactored signal handling: replaced lazy _signal getter with a public signal property, removed custom abort logic, and adopted AbortController for cancellation.
packages/server/src/createServerAdapter.ts, .../utils.ts, .../uwebsockets.ts Removed custom abort signal classes/methods; transitioned to using AbortController, updated function signatures, interface properties, and event listeners.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant ServerAdapter
    participant AbortController
    participant RequestHandler

    Client->>ServerAdapter: Send Request
    ServerAdapter->>AbortController: Create/assign controller
    AbortController-->>RequestHandler: Provide signal for processing
    RequestHandler->>Stream: Process request with signal
    Stream-->>AbortController: On error/close, trigger abort
    AbortController-->>ServerAdapter: Notify abort event
Loading

Poem

I'm a little rabbit, hopping through the code,
Leaving custom signals behind on the road.
With AbortController shining oh so bright,
Our requests now dance in streamlined light,
Carrots and clean code—it's a bouncy delight! 🥕✨

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

🪧 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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. (Beta)
  • @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

github-actions bot commented Feb 5, 2025

🚀 Snapshot Release (alpha)

The latest changes of this PR are available as alpha on npm (based on the declared changesets):

Package Version Info
@whatwg-node/node-fetch 0.7.8-alpha-20250205113213-1ddf37bf9cb93e796a62ac800ea0b4100bb2eaa4 npm ↗︎ unpkg ↗︎
@whatwg-node/server 0.10.0-alpha-20250205113213-1ddf37bf9cb93e796a62ac800ea0b4100bb2eaa4 npm ↗︎ unpkg ↗︎
@whatwg-node/server-plugin-cookies 2.0.0-alpha-20250205113213-1ddf37bf9cb93e796a62ac800ea0b4100bb2eaa4 npm ↗︎ unpkg ↗︎

Copy link
Contributor

github-actions bot commented Feb 5, 2025

@benchmarks/node-fetch results (consumeBody)

   ✓ active_handles.................: avg=140.941456 min=30      med=141     max=181     p(90)=159     p(95)=164    
     data_received..................: 20 MB  673 kB/s
     data_sent......................: 13 MB  431 kB/s
     http_req_blocked...............: avg=3µs        min=621ns   med=1.28µs  max=3.79ms  p(90)=2.03µs  p(95)=2.27µs 
     http_req_connecting............: avg=1.26µs     min=0s      med=0s      max=3.71ms  p(90)=0s      p(95)=0s     
     http_req_duration..............: avg=22.66ms    min=4.39ms  med=22.1ms  max=1.14s   p(90)=28.15ms p(95)=29.76ms
       { expected_response:true }...: avg=22.66ms    min=4.39ms  med=22.1ms  max=1.14s   p(90)=28.15ms p(95)=29.76ms
     http_req_failed................: 0.00%  ✓ 0           ✗ 131974
     http_req_receiving.............: avg=33.49µs    min=9.3µs   med=23.56µs max=15.27ms p(90)=37.43µs p(95)=43.98µs
     http_req_sending...............: avg=10.62µs    min=3.13µs  med=5.99µs  max=18.69ms p(90)=9.67µs  p(95)=13.32µs
     http_req_tls_handshaking.......: avg=0s         min=0s      med=0s      max=0s      p(90)=0s      p(95)=0s     
     http_req_waiting...............: avg=22.61ms    min=4.36ms  med=22.06ms max=1.14s   p(90)=28.11ms p(95)=29.7ms 
     http_reqs......................: 131974 4398.637708/s
     iteration_duration.............: avg=45.42ms    min=17.99ms med=43.86ms max=1.16s   p(90)=48.8ms  p(95)=54.34ms
     iterations.....................: 65968  2198.685592/s
     vus............................: 100    min=100       max=100 
     vus_max........................: 100    min=100       max=100 

Copy link
Contributor

github-actions bot commented Feb 5, 2025

@benchmarks/server results (ponyfill)

     ✓ no-errors
     ✓ expected-result

   ✓ checks.........................: 100.00% ✓ 297442      ✗ 0     
     data_received..................: 29 MB   977 kB/s
     data_sent......................: 12 MB   397 kB/s
     http_req_blocked...............: avg=1.39µs   min=891ns    med=1.18µs   max=330.85µs p(90)=1.84µs   p(95)=2µs     
     http_req_connecting............: avg=0ns      min=0s       med=0s       max=145.15µs p(90)=0s       p(95)=0s      
     http_req_duration..............: avg=138.44µs min=91.38µs  med=134µs    max=6.95ms   p(90)=155.51µs p(95)=162.25µs
       { expected_response:true }...: avg=138.44µs min=91.38µs  med=134µs    max=6.95ms   p(90)=155.51µs p(95)=162.25µs
     http_req_failed................: 0.00%   ✓ 0           ✗ 148721
     http_req_receiving.............: avg=24.49µs  min=12.61µs  med=22.98µs  max=2.71ms   p(90)=30.14µs  p(95)=32.89µs 
     http_req_sending...............: avg=6.34µs   min=4.07µs   med=5.5µs    max=541.31µs p(90)=8.05µs   p(95)=8.8µs   
     http_req_tls_handshaking.......: avg=0s       min=0s       med=0s       max=0s       p(90)=0s       p(95)=0s      
     http_req_waiting...............: avg=107.6µs  min=64.85µs  med=102.72µs max=6.9ms    p(90)=121.42µs p(95)=126.98µs
     http_reqs......................: 148721  4957.203248/s
     iteration_duration.............: avg=197.21µs min=140.51µs med=192.1µs  max=7.06ms   p(90)=216.62µs p(95)=225.26µs
     iterations.....................: 148721  4957.203248/s
     vus............................: 1       min=1         max=1   
     vus_max........................: 1       min=1         max=1   

Copy link
Contributor

github-actions bot commented Feb 5, 2025

@benchmarks/node-fetch results (noConsumeBody)

   ✓ active_handles.................: avg=140.012934 min=23      med=138     max=187     p(90)=161     p(95)=166    
     data_received..................: 21 MB  711 kB/s
     data_sent......................: 14 MB  460 kB/s
     http_req_blocked...............: avg=2.96µs     min=661ns   med=1.3µs   max=5.45ms  p(90)=1.97µs  p(95)=2.21µs 
     http_req_connecting............: avg=1.23µs     min=0s      med=0s      max=5.24ms  p(90)=0s      p(95)=0s     
     http_req_duration..............: avg=21.45ms    min=5.01ms  med=20.89ms max=1.12s   p(90)=27.14ms p(95)=28.75ms
       { expected_response:true }...: avg=21.45ms    min=5.01ms  med=20.89ms max=1.12s   p(90)=27.14ms p(95)=28.75ms
     http_req_failed................: 0.00%  ✓ 0           ✗ 139375
     http_req_receiving.............: avg=32.63µs    min=8.75µs  med=22.2µs  max=11.16ms p(90)=36.19µs p(95)=42.87µs
     http_req_sending...............: avg=10.67µs    min=3.2µs   med=5.99µs  max=9.41ms  p(90)=9.37µs  p(95)=12.45µs
     http_req_tls_handshaking.......: avg=0s         min=0s      med=0s      max=0s      p(90)=0s      p(95)=0s     
     http_req_waiting...............: avg=21.41ms    min=4.98ms  med=20.85ms max=1.12s   p(90)=27.1ms  p(95)=28.67ms
     http_reqs......................: 139375 4644.063735/s
     iteration_duration.............: avg=43.01ms    min=17.07ms med=41.41ms max=1.15s   p(90)=47.25ms p(95)=52.25ms
     iterations.....................: 69664  2321.248833/s
     vus............................: 0      min=0         max=100 
     vus_max........................: 100    min=100       max=100 

Copy link
Contributor

github-actions bot commented Feb 5, 2025

@benchmarks/server results (undici)

     ✓ no-errors
     ✓ expected-result

   ✓ checks.........................: 100.00% ✓ 196114      ✗ 0    
     data_received..................: 20 MB   657 kB/s
     data_sent......................: 7.8 MB  262 kB/s
     http_req_blocked...............: avg=1.43µs   min=882ns    med=1.22µs   max=261.43µs p(90)=1.92µs   p(95)=2.1µs   
     http_req_connecting............: avg=1ns      min=0s       med=0s       max=114.7µs  p(90)=0s       p(95)=0s      
     http_req_duration..............: avg=242.87µs min=187.47µs med=230.3µs  max=26.57ms  p(90)=257.79µs p(95)=268.1µs 
       { expected_response:true }...: avg=242.87µs min=187.47µs med=230.3µs  max=26.57ms  p(90)=257.79µs p(95)=268.1µs 
     http_req_failed................: 0.00%   ✓ 0           ✗ 98057
     http_req_receiving.............: avg=25.67µs  min=13.37µs  med=23.92µs  max=2.39ms   p(90)=31.09µs  p(95)=33.76µs 
     http_req_sending...............: avg=6.5µs    min=4.1µs    med=5.71µs   max=285.16µs p(90)=8.31µs   p(95)=9µs     
     http_req_tls_handshaking.......: avg=0s       min=0s       med=0s       max=0s       p(90)=0s       p(95)=0s      
     http_req_waiting...............: avg=210.69µs min=160.5µs  med=198.01µs max=26.5ms   p(90)=222.53µs p(95)=231.72µs
     http_reqs......................: 98057   3268.443058/s
     iteration_duration.............: avg=301.38µs min=230.83µs med=288.14µs max=26.7ms   p(90)=318.86µs p(95)=330.93µs
     iterations.....................: 98057   3268.443058/s
     vus............................: 1       min=1         max=1  
     vus_max........................: 1       min=1         max=1  

Copy link
Contributor

github-actions bot commented Feb 5, 2025

@benchmarks/server results (native)

     ✓ no-errors
     ✓ expected-result

   ✓ checks.........................: 100.00% ✓ 208292      ✗ 0     
     data_received..................: 21 MB   698 kB/s
     data_sent......................: 8.3 MB  278 kB/s
     http_req_blocked...............: avg=1.38µs   min=861ns    med=1.16µs   max=266.54µs p(90)=1.87µs   p(95)=2.03µs  
     http_req_connecting............: avg=1ns      min=0s       med=0s       max=141.47µs p(90)=0s       p(95)=0s      
     http_req_duration..............: avg=225.45µs min=168.21µs med=214.87µs max=11.32ms  p(90)=241.75µs p(95)=252.68µs
       { expected_response:true }...: avg=225.45µs min=168.21µs med=214.87µs max=11.32ms  p(90)=241.75µs p(95)=252.68µs
     http_req_failed................: 0.00%   ✓ 0           ✗ 104146
     http_req_receiving.............: avg=25.06µs  min=13.97µs  med=23.46µs  max=2.44ms   p(90)=30.27µs  p(95)=32.96µs 
     http_req_sending...............: avg=6.33µs   min=4.04µs   med=5.46µs   max=2.78ms   p(90)=8.12µs   p(95)=8.82µs  
     http_req_tls_handshaking.......: avg=0s       min=0s       med=0s       max=0s       p(90)=0s       p(95)=0s      
     http_req_waiting...............: avg=194.05µs min=147.1µs  med=183.29µs max=11.24ms  p(90)=207.49µs p(95)=217.76µs
     http_reqs......................: 104146  3471.419747/s
     iteration_duration.............: avg=283.56µs min=210.15µs med=272.25µs max=11.51ms  p(90)=302.2µs  p(95)=315.33µs
     iterations.....................: 104146  3471.419747/s
     vus............................: 1       min=1         max=1   
     vus_max........................: 1       min=1         max=1   

Copy link

@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 (5)
packages/node-fetch/src/WritableStream.ts (1)

54-55: Distinguish between normal stream closure and error-based abort.

Calling abortCtrl.abort() on a normal close event could be unexpected, as abort often implies an abnormal termination. Consider differentiating the two scenarios if standard compliance or consumer expectations require that a normal close not raise an abort signal.

packages/server/src/utils.ts (4)

111-116: Confirm Node request abort property usage.

Using Object.defineProperty(rawRequest, 'aborted', { value: true }) effectively enforces an aborted state, but note that Node commonly manages req.aborted itself. Double-check that this manual override won't conflict with built-in Node request behavior or external libraries that rely on the existing property.


149-149: Repeating identical request construction logic.

Multiple request objects with the same signal: controller.signal usage appear throughout the function. Consider abstracting the shared logic into a helper to reduce duplication.


155-155: Same cancellation signal pattern.

This usage is identical to other request blocks. Reiterating that a helper function might improve maintainability.


211-215: Handling rawRequest as body with a TS exception.

Passing the raw incoming request stream and adding the @ts-expect-error comment is workable, but consider revisiting if TypeScript adds proper types for async streams. Meanwhile, ensure the stream isn’t already consumed or curtailed.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 45d5bd4 and c9a7e9a.

📒 Files selected for processing (8)
  • .changeset/metal-moles-care.md (1 hunks)
  • packages/node-fetch/src/Request.ts (2 hunks)
  • packages/node-fetch/src/WritableStream.ts (1 hunks)
  • packages/node-fetch/src/fetchCurl.ts (3 hunks)
  • packages/node-fetch/src/fetchNodeHttp.ts (2 hunks)
  • packages/server/src/createServerAdapter.ts (5 hunks)
  • packages/server/src/utils.ts (6 hunks)
  • packages/server/src/uwebsockets.ts (7 hunks)
🔇 Additional comments (20)
packages/node-fetch/src/fetchNodeHttp.ts (3)

50-50: LGTM! Clean signal property access.

The change to use direct property access for the signal is cleaner and aligns well with the move to native AbortController/AbortSignal.


57-57: LGTM! Consistent signal handling.

The signal property access is consistently updated in both request creation paths.


109-111: LGTM! Proper signal propagation to stream pipeline.

The signal is correctly propagated to the stream pipeline, ensuring proper cancellation handling throughout the request lifecycle.

Let's verify that the abort signal is properly handled in the pipeline:

✅ Verification successful

🏁 Script executed:

#!/bin/bash
# Search for other pipeline usages to ensure consistent signal handling
rg "pipeline.*signal" -A 5

Length of output: 28


🏁 Script executed:

#!/bin/bash
echo "Displaying snippet from packages/node-fetch/src/fetchNodeHttp.ts (lines 100-120):"
sed -n '100,120p' packages/node-fetch/src/fetchNodeHttp.ts

echo -e "\nSearching for 'fetchRequest.signal' usage:"
rg "fetchRequest\.signal" -n packages/node-fetch/src/fetchNodeHttp.ts

Length of output: 1134


LGTM – Signal propagation is consistently implemented.

The verification shows that in packages/node-fetch/src/fetchNodeHttp.ts, the fetchRequest.signal is correctly used in the pipeline options (line 110) and similarly applied at other relevant locations, ensuring proper cancellation handling.

packages/node-fetch/src/WritableStream.ts (1)

47-51: Adoption of native AbortController looks correct.

The new approach cleanly injects the AbortSignal into the controller and properly destroys the writable stream on error. One minor consideration: if multiple errors occur, abortCtrl.signal.reason may be overwritten. Confirm that this behavior is acceptable or consider preserving the first error encountered.

packages/server/src/utils.ts (6)

89-89: Ensure all references to removed parameters are updated.

The function signature for normalizeNodeRequest has changed. Verify that no callers are still passing the removed registerSignal parameter or relying on the old behavior.


132-132: Consistent usage of controller.signal.

Providing the signal for the fetchAPI.Request ensures correct cancellation logic, aligning with the new architecture. Looks good.


203-203: Unified abort handling is consistent.

Passing controller.signal again ensures the request can be aborted properly when using a Bun Node-compat or other streaming approach. No issues detected.


535-539: Immediate abort check is valid.

Throwing abortSignal.reason if the signal is already aborted preempts unnecessary processing. This is a good practice to fail early when the request cannot proceed.


543-546: Registering the abort listener with a once-option.

The code rejects the deferred promise immediately on abort. Coupled with a one-time listener, this approach is clean and prevents multiple rejections.


552-555: Cleaning up the event listener in finally.

Removing the abort listener ensures no leaking references or stale callbacks. Overall, the promise resolution path is well-handled.

packages/node-fetch/src/Request.ts (2)

76-76: Straightforward fallback to a new AbortController.

Using a user-provided signal when available, else creating a fresh one, aligns with typical fetch patterns. Good job simplifying the lazy initialization.


140-140: Public signal property is clearer.

Exposing AbortSignal plainly removes the complexity of a private _signal with lazy creation. This should improve maintainability and predictability.

packages/node-fetch/src/fetchCurl.ts (2)

33-33: LGTM! Improved signal access.

The change from private signal access to public signal property enhances code readability and aligns with native AbortController usage.


91-92: LGTM! Consistent signal handling.

The changes consistently update signal access across event listeners and pipeline configuration, improving code maintainability.

Also applies to: 100-101, 126-126

packages/server/src/uwebsockets.ts (3)

34-34: LGTM! Updated interface to use AbortController.

The change from signal: AbortSignal to controller: AbortController aligns with the PR objective.


78-84: LGTM! Improved event listener setup.

The event listener is now properly configured with { once: true } option, preventing potential memory leaks.


252-260: LGTM! Enhanced abort handling.

The abort event listener now properly cancels the body stream when aborted, improving resource cleanup.

packages/server/src/createServerAdapter.ts (2)

321-321: LGTM! Migrated to native AbortController.

The changes properly replace the custom abort signal implementation with native AbortController, improving standardization.

Also applies to: 330-330, 333-333


408-413: LGTM! Improved signal handling in fetchFn.

The signal handling is now more explicit and properly integrated with the native AbortController.

.changeset/metal-moles-care.md (1)

1-7: LGTM! Clear and concise changeset.

The changeset properly documents both the dependency updates and the migration to native AbortController/AbortSignal.

@ardatan ardatan force-pushed the use-native-abort-ctrl branch from c9a7e9a to 98b4d1e Compare February 5, 2025 11:24
Copy link

@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)
packages/server/src/utils.ts (1)

111-126: Consider cleaning up the AbortController.

The AbortController instance should be cleaned up when it's no longer needed to prevent potential memory leaks. Consider removing the event listeners and aborting the controller when the response is finished.

 serverResponse.once('finish', () => {
   nodeResponse.removeListener('close', closeEventListener);
+  nodeResponse.removeListener('error', closeEventListener);
+  if (!controller.signal.aborted) {
+    controller.abort();
+  }
 });
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c9a7e9a and 98b4d1e.

📒 Files selected for processing (8)
  • .changeset/metal-moles-care.md (1 hunks)
  • packages/node-fetch/src/Request.ts (2 hunks)
  • packages/node-fetch/src/WritableStream.ts (1 hunks)
  • packages/node-fetch/src/fetchCurl.ts (3 hunks)
  • packages/node-fetch/src/fetchNodeHttp.ts (2 hunks)
  • packages/server/src/createServerAdapter.ts (5 hunks)
  • packages/server/src/utils.ts (6 hunks)
  • packages/server/src/uwebsockets.ts (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • .changeset/metal-moles-care.md
  • packages/node-fetch/src/fetchNodeHttp.ts
  • packages/node-fetch/src/fetchCurl.ts
⏰ Context from checks skipped due to timeout of 90000ms (20)
  • GitHub Check: unit / node 23
  • GitHub Check: unit / node 22
  • GitHub Check: unit / node 20
  • GitHub Check: unit / deno
  • GitHub Check: unit / node 18
  • GitHub Check: server (undici)
  • GitHub Check: unit / bun
  • GitHub Check: type check
  • GitHub Check: alpha / snapshot
  • GitHub Check: e2e / cloudflare-modules
  • GitHub Check: server (ponyfill)
  • GitHub Check: esm
  • GitHub Check: server (native)
  • GitHub Check: e2e / cloudflare-workers
  • GitHub Check: e2e / azure-function
  • GitHub Check: node-fetch (consumeBody)
  • GitHub Check: lint
  • GitHub Check: e2e / aws-lambda
  • GitHub Check: node-fetch (noConsumeBody)
  • GitHub Check: prettier
🔇 Additional comments (9)
packages/node-fetch/src/WritableStream.ts (1)

47-55: LGTM! Clean implementation using native AbortController.

The changes effectively replace the custom signal implementation with the native AbortController, making the code more maintainable and aligned with web standards. The implementation correctly:

  1. Creates an AbortController
  2. Passes its signal to the controller
  3. Sets up error and close event handlers to trigger abort
packages/node-fetch/src/Request.ts (1)

76-76: LGTM! Simplified signal initialization.

The changes effectively:

  1. Remove the lazy initialization pattern
  2. Make the signal property public and directly initialized
  3. Use native AbortController's signal by default

This aligns with the PR objectives stating that signals are no longer considered expensive enough to require lazy initialization.

Also applies to: 140-140

packages/server/src/uwebsockets.ts (3)

34-34: LGTM! Clean interface update.

The interface and function signature changes correctly reflect the transition to using AbortController, making the API more consistent with web standards.

Also applies to: 37-42


78-84: LGTM! Improved event listener setup.

The event listener setup is enhanced with:

  1. Direct use of AbortController's signal
  2. The once: true option to prevent memory leaks

252-260: LGTM! Robust abort handling.

The abort handling is improved with:

  1. Proper cancellation of the response body
  2. Single-use event listener to prevent memory leaks
  3. Proper propagation of the abort reason
packages/server/src/createServerAdapter.ts (2)

321-321: LGTM! Clean abort handling in handleUWS.

The changes effectively:

  1. Create a new AbortController for each request
  2. Set up proper abort handling with single-use event listeners
  3. Maintain proper cleanup through the once: true option

Also applies to: 330-334


408-413: LGTM! Simplified signal handling in fetchFn.

The signal handling is streamlined by:

  1. Directly accessing the signal from RequestInit
  2. Using the native AbortController signal
  3. Properly propagating the abort signal to the response promise
packages/server/src/utils.ts (2)

89-89: LGTM! Function signature simplified.

The removal of the registerSignal parameter simplifies the function signature while maintaining functionality through native AbortController.


533-559: LGTM! Improved abort signal handling.

The changes enhance the abort signal handling by:

  1. Using native AbortSignal type
  2. Adding proper event listener cleanup
  3. Using the standard reason property for error handling

@ardatan ardatan force-pushed the use-native-abort-ctrl branch from 98b4d1e to 1ddf37b Compare February 5, 2025 11:30
Copy link

@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 (2)
packages/server/src/createServerAdapter.ts (1)

351-363: Consider cleanup of abort event listener

While the implementation is correct, consider cleaning up the abort event listener when the response ends to prevent potential memory leaks.

 res.end = function (data: any) {
   resEnded = true;
+  controller.signal.removeEventListener('abort', cb);
   return originalResEnd(data);
 };
packages/server/src/utils.ts (1)

533-559: Consider enhancing error handling in abort signal management

While the implementation is correct, consider adding a type check for the abort reason to handle cases where it might be undefined.

 if (abortSignal?.aborted) {
-  throw abortSignal.reason;
+  throw abortSignal.reason instanceof Error ? abortSignal.reason : new Error('Request aborted');
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 98b4d1e and 1ddf37b.

📒 Files selected for processing (8)
  • .changeset/metal-moles-care.md (1 hunks)
  • packages/node-fetch/src/Request.ts (2 hunks)
  • packages/node-fetch/src/WritableStream.ts (1 hunks)
  • packages/node-fetch/src/fetchCurl.ts (3 hunks)
  • packages/node-fetch/src/fetchNodeHttp.ts (2 hunks)
  • packages/server/src/createServerAdapter.ts (5 hunks)
  • packages/server/src/utils.ts (6 hunks)
  • packages/server/src/uwebsockets.ts (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • .changeset/metal-moles-care.md
  • packages/node-fetch/src/fetchCurl.ts
  • packages/node-fetch/src/fetchNodeHttp.ts
  • packages/node-fetch/src/Request.ts
  • packages/server/src/uwebsockets.ts
⏰ Context from checks skipped due to timeout of 90000ms (14)
  • GitHub Check: unit / node 23
  • GitHub Check: unit / node 22
  • GitHub Check: unit / node 20
  • GitHub Check: unit / deno
  • GitHub Check: unit / bun
  • GitHub Check: e2e / cloudflare-modules
  • GitHub Check: server (undici)
  • GitHub Check: unit / node 18
  • GitHub Check: server (ponyfill)
  • GitHub Check: e2e / azure-function
  • GitHub Check: node-fetch (consumeBody)
  • GitHub Check: server (native)
  • GitHub Check: type check
  • GitHub Check: node-fetch (noConsumeBody)
🔇 Additional comments (3)
packages/node-fetch/src/WritableStream.ts (1)

47-55: Well-implemented transition to native AbortController!

The changes effectively replace custom signal handling with the native AbortController, providing a more standardized and maintainable implementation. The error and close event handling is properly integrated with the abort mechanism.

packages/server/src/createServerAdapter.ts (1)

321-334: Good implementation of native AbortController!

The transition to native AbortController is well implemented with proper event handling setup.

packages/server/src/utils.ts (1)

111-126: Well-implemented AbortController in request normalization!

The integration of native AbortController in the request normalization process is clean and properly handles all necessary events.

@ardatan ardatan merged commit b58b6d1 into master Feb 5, 2025
25 checks passed
Copy link
Collaborator

@enisdenjo enisdenjo left a comment

Choose a reason for hiding this comment

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

Approved. 👍

@enisdenjo enisdenjo deleted the use-native-abort-ctrl branch February 5, 2025 16:07
@coderabbitai coderabbitai bot mentioned this pull request Feb 24, 2025
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