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

fix: set opaque on request #560

Merged
merged 1 commit into from
Dec 7, 2024
Merged

fix: set opaque on request #560

merged 1 commit into from
Dec 7, 2024

Conversation

fengmk2
Copy link
Member

@fengmk2 fengmk2 commented Dec 7, 2024

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced timing metrics for HTTP requests, now including dnslookup.
    • Improved logging format for better clarity in debug outputs.
  • Bug Fixes

    • Refined error handling for various timeout errors, improving granularity in error reporting.
    • Enhanced error handling in fetch operations with detailed logging of request IDs and errors.
  • Tests

    • Updated test cases for fetch functionality to include timing assertions and improved error handling checks.
    • Enhanced clarity in assertions within timing tests.
  • Chores

    • Added a new symbol for representing internal opaque request values.

Copy link

coderabbitai bot commented Dec 7, 2024

Walkthrough

The pull request introduces several modifications across multiple files, primarily enhancing error handling, timing metrics, and logging functionalities. Key changes include the addition of a dnslookup property to the timing metrics in the HttpClient and fetch methods, refined error handling for specific timeout errors, and updates to the diagnostics logging format. The test suite has also been updated to improve assertions related to timing and error handling. Overall, these changes aim to improve the robustness and clarity of the HTTP client and fetch functionalities.

Changes

File Change Summary
src/HttpClient.ts Added dnslookup property to timing metrics; refined error handling for specific timeout errors.
src/Response.ts Uncommented dnslookup property in Timing type definition.
src/diagnosticsChannel.ts Updated debug logging format; modified getRequestOpaque method for opaque data retrieval; updated destroySocket function for error logging.
src/fetch.ts Enhanced error handling and logging in FetchFactory; added dnslookup property to timing metrics.
src/symbols.ts Added new symbol kRequestInternalOpaque.
test/fetch.test.ts Updated test cases for fetch to include timing assertions and improved error handling checks.
test/options.timing.test.ts Changed assertions to use assert.equal for clarity in timing-related tests.

Possibly related PRs

Suggested labels

bug, enhancement

🐰 In the meadow, where bunnies play,
New metrics bloom, brightening the day.
Errors caught, like leaves in a breeze,
Fetching data with newfound ease.
With each hop, our code takes flight,
Debugging's clearer, all feels right! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 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 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

pkg-pr-new bot commented Dec 7, 2024

Open in Stackblitz

npm i https://pkg.pr.new/node-modules/urllib@560

commit: 2409681

Copy link

codecov bot commented Dec 7, 2024

Codecov Report

Attention: Patch coverage is 95.00000% with 1 line in your changes missing coverage. Please review.

Project coverage is 94.65%. Comparing base (dec6b12) to head (2409681).
Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
src/diagnosticsChannel.ts 90.90% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #560      +/-   ##
==========================================
+ Coverage   94.62%   94.65%   +0.03%     
==========================================
  Files          11       11              
  Lines        1227     1235       +8     
  Branches      296      298       +2     
==========================================
+ Hits         1161     1169       +8     
  Misses         62       62              
  Partials        4        4              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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

🧹 Outside diff range and nitpick comments (5)
test/options.timing.test.ts (1)

55-55: Remove commented console.log.

Instead of keeping commented debug code, consider removing it entirely.

-    // console.log(res.timing);
src/fetch.ts (1)

250-251: Consider structuring debug log for better readability

The debug log combines multiple objects which might be hard to read in logs.

Consider splitting into multiple log lines:

-    debug('Request#%d got response, status: %s, headers: %j, timing: %j, socket: %j',
-      requestId, urllibResponse.status, urllibResponse.headers, timing, urllibResponse.socket);
+    debug('Request#%d got response, status: %s', requestId, urllibResponse.status);
+    debug('Request#%d headers: %j', requestId, urllibResponse.headers);
+    debug('Request#%d timing: %j', requestId, timing);
+    debug('Request#%d socket: %j', requestId, urllibResponse.socket);
src/HttpClient.ts (3)

Line range hint 1009-1019: Consider enhancing error messages with more context

The error handling could be more informative by including the request URL and timeout values in the error messages.

Consider this improvement:

 if (err.name === 'HeadersTimeoutError') {
-  err = new HttpClientRequestTimeoutError(headersTimeout, { cause: err });
+  err = new HttpClientRequestTimeoutError(
+    `Headers timeout of ${headersTimeout}ms exceeded for ${requestUrl.href}`,
+    { cause: err }
+  );
 } else if (err.name === 'BodyTimeoutError') {
-  err = new HttpClientRequestTimeoutError(bodyTimeout, { cause: err });
+  err = new HttpClientRequestTimeoutError(
+    `Body timeout of ${bodyTimeout}ms exceeded for ${requestUrl.href}`,
+    { cause: err }
+  );
 }

Line range hint 1020-1027: Consider implementing exponential backoff for retries

The current retry mechanism could be enhanced with exponential backoff to prevent overwhelming the server during issues.

Consider adding exponential backoff:

 if (args.socketErrorRetry > 0 && requestContext.socketErrorRetries < args.socketErrorRetry) {
   requestContext.socketErrorRetries++;
+  const backoffDelay = Math.min(1000 * Math.pow(2, requestContext.socketErrorRetries - 1), 10000);
+  await sleep(backoffDelay);
   debug('Request#%d retry on socket error, socketErrorRetries: %d',
     requestId, requestContext.socketErrorRetries);
   return await this.#requestInternal(url, options, requestContext);
 }

Line range hint 1028-1056: Ensure response body is always consumed

There's a potential memory leak when errors occur. The response body should be consumed even in error cases to properly clean up resources.

Add response body cleanup in the error handling:

 } catch (rawError: any) {
   debug('Request#%d throw error: %s, socketErrorRetry: %s, socketErrorRetries: %s',
     requestId, rawError, args.socketErrorRetry, requestContext.socketErrorRetries);
   let err = rawError;
+  // Ensure response body is consumed even in error cases
+  if (response?.body) {
+    try {
+      await response.body.arrayBuffer();
+    } catch (consumeError) {
+      debug('Error consuming response body: %s', consumeError);
+    }
+  }
   // ... rest of error handling
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ed6868b and 2409681.

📒 Files selected for processing (7)
  • src/HttpClient.ts (1 hunks)
  • src/Response.ts (1 hunks)
  • src/diagnosticsChannel.ts (8 hunks)
  • src/fetch.ts (6 hunks)
  • src/symbols.ts (1 hunks)
  • test/fetch.test.ts (3 hunks)
  • test/options.timing.test.ts (2 hunks)
🧰 Additional context used
🪛 GitHub Check: codecov/patch
src/diagnosticsChannel.ts

[warning] 122-122: src/diagnosticsChannel.ts#L122
Added line #L122 was not covered by tests

🔇 Additional comments (9)
src/symbols.ts (1)

20-20: LGTM! Verify symbol usage across codebase.

The new symbol follows the established naming pattern and aligns with the PR's objective of fixing opaque request handling.

✅ Verification successful

Let me check the usage context in diagnosticsChannel.ts to ensure proper implementation.


Symbol is correctly implemented and used consistently

The symbol is properly used throughout diagnosticsChannel.ts for managing request opaque data across different diagnostic events (sendHeaders, bodySent, headers, trailers). The implementation follows a consistent pattern:

  • Setting opaque data using Reflect.set
  • Retrieving opaque data using Reflect.get
  • Proper null checks and request ID validation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of the new kRequestInternalOpaque symbol
# Expected: Should find references in request handling code

rg "kRequestInternalOpaque" --type ts

Length of output: 601


Script:

#!/bin/bash
# Get the context around the symbol usage in diagnosticsChannel.ts
rg "kRequestInternalOpaque" -B 3 -A 3 --type ts src/diagnosticsChannel.ts

Length of output: 2128

test/fetch.test.ts (2)

57-63: LGTM: Keep-alive test implementation

Good addition of keep-alive testing by adding a sleep between requests and validating socket reuse through handledRequests and handledResponses counters.


88-96: Improved error handling test pattern

Good refactoring to use assert.rejects instead of try-catch, making the test more concise and focused on the expected error conditions.

src/fetch.ts (2)

143-143: LGTM: Added DNS lookup timing metric

Good addition of the dnslookup timing metric to track DNS resolution performance.


224-226: Enhanced error handling with debug logging

Good improvement in error handling by updating socket info and adding debug logging before re-throwing the error.

src/diagnosticsChannel.ts (3)

92-94: LGTM: Improved opaque data handling

Good improvement using Reflect.set to store the opaque data on the request object, making it accessible throughout the request lifecycle.


147-147: LGTM: Consistent opaque data access

Good refactoring to use Reflect.get(request, symbols.kRequestInternalOpaque) consistently across all event handlers.

Also applies to: 172-172, 186-186, 211-211


119-124: Verify error logging coverage

The error logging path at line 122 is not covered by tests according to codecov.

Would you like me to help create a test case that covers this error scenario?

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 122-122: src/diagnosticsChannel.ts#L122
Added line #L122 was not covered by tests

src/HttpClient.ts (1)

303-303: LGTM: Enhanced timing metrics with DNS lookup timing

The addition of dnslookup timing metric improves observability by providing insights into DNS resolution performance.

@@ -28,7 +28,7 @@ export type Timing = {
// socket assigned
queuing: number;
// dns lookup time
// dnslookup: number;
dnslookup: number;
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Based on the search results, I can now generate the final response:

DNS lookup timing metric is not properly implemented

While the dnslookup property is added to the Timing type, there's no actual implementation to measure and set this value. The codebase shows:

  • Timing measurements are done using performance.now()
  • DNS lookup is performed in HttpAgent.ts using the lookup function
  • However, there's no code connecting the DNS lookup duration to the timing object

The following locations need attention:

  • src/HttpAgent.ts: Add timing measurement around the DNS lookup operation
  • src/fetch.ts and src/HttpClient.ts: Ensure the DNS lookup timing is properly propagated
🔗 Analysis chain

Verify dnslookup timing implementation.

The dnslookup timing property has been properly added to the Timing type. Its position in the interface correctly reflects the chronological order of HTTP request phases.


Let me gather more information to verify the timing implementation.


Let me try one more search pattern to find the timing implementation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation of dnslookup timing
# Expected: Should find where this timing metric is calculated

# Search for dnslookup timing calculation
rg "dnslookup.*=|timing\.dnslookup" --type ts

# Search for DNS-related code that might set this timing
ast-grep --pattern 'lookup($$$)' 

Length of output: 1593


Script:

#!/bin/bash
# Search for timing-related code around DNS lookup
rg "timing.*dns|dns.*timing" -B 2 -A 2 --type ts

# Look for timing initialization and calculation patterns
ast-grep --pattern 'timing = {
  $$$
}'

# Search for timing-related code in the HttpAgent
rg "timing" --type ts src/HttpAgent.ts -B 2 -A 2

Length of output: 141


Script:

#!/bin/bash
# Search for files that might contain timing implementation
rg "new Date\(\)|performance\.now\(\)" -B 2 -A 2 --type ts

# Look for timing-related code in the client implementation
fd "client" --type f --extension ts --exec rg "timing" -B 2 -A 2 {}

# Search for timing property assignments
ast-grep --pattern '$_.$_.timing = $_'

Length of output: 7594

@@ -32,7 +32,7 @@ describe('options.timing.test.ts', () => {
assert(res.timing.contentDownload > 0);
assert(res.timing.contentDownload > res.timing.waiting);
assert(res.timing.contentDownload <= res.rt);
assert(res.socket.handledResponses === 1);
assert.equal(res.socket.handledResponses, 1);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add assertions for dnslookup timing.

While the assertion changes improve precision, consider adding assertions for the newly added dnslookup timing property to ensure it's working as expected.

Add these assertions after the existing timing checks:

 assert(res.timing.queuing > 0);
+assert(res.timing.dnslookup >= 0);
 assert(res.timing.connected > 0);

Also applies to: 48-48, 54-54

@fengmk2 fengmk2 merged commit 8cf5c3b into master Dec 7, 2024
24 checks passed
@fengmk2 fengmk2 deleted the state branch December 7, 2024 10:55
fengmk2 pushed a commit that referenced this pull request Dec 7, 2024
[skip ci]

## [4.6.5](v4.6.4...v4.6.5) (2024-12-07)

### Bug Fixes

* set opaque on request ([#560](#560)) ([8cf5c3b](8cf5c3b))
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.

1 participant