Skip to content

Conversation

@akar1ngo
Copy link

@akar1ngo akar1ngo commented Oct 8, 2025

Description

This change allows nix-installer-action etc. to avoid hard-coding a 10-second timeout for fetching Nix binaries.

Checklist
  • Tested changes against a test repository
  • Added or updated relevant documentation (leave unchecked if not applicable)
  • (If this PR is for a release) Updated README to point to the new tag (leave unchecked if not applicable)

Summary by CodeRabbit

  • New Features
    • Introduced configurable request timeouts across network operations, allowing per-call overrides of the default timeout.
    • Timeout settings now propagate consistently through client requests, artifact retrieval, and file downloads.
    • Improves control over long-running downloads and connectivity-sensitive tasks by letting users tailor timeout behavior to their environment.

This change allows nix-installer-action etc. to avoid hard-coding a
10-second timeout for fetching Nix binaries.
@coderabbitai
Copy link

coderabbitai bot commented Oct 8, 2025

Walkthrough

Introduces an optional timeout parameter across HTTP client creation and artifact download flows. The timeout propagates from public APIs through internal methods to ids-host’s Got client construction, overriding the default request timeout when provided.

Changes

Cohort / File(s) Summary of changes
HTTP client timeout support
src/ids-host.ts
Added optional timeout?: number to getGot(...); wired to got.extend({ timeout }), falling back to DEFAULT_TIMEOUT when undefined. Updated method signature and internal flow to apply per-call timeout.
Timeout propagation across artifact workflow
src/index.ts
Added optional timeout?: number to fetchExecutable, getClient, and private methods fetchArtifact and downloadFile. Propagated timeout through calls, ensuring client creation and downloads use the provided timeout.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant App as Caller
  participant Index as index.ts (Public API)
  participant Host as ids-host.ts (getGot)
  participant Got as got client

  App->>Index: fetchExecutable(timeout?)
  activate Index
  Index->>Index: fetchArtifact(timeout?)
  Index->>Index: getClient(timeout?)
  Index->>Host: getGot(callback?, timeout?)
  activate Host
  Host->>Got: got.extend({ timeout: timeout or DEFAULT_TIMEOUT })
  deactivate Host
  Index->>Got: HTTP requests (download/version) with client
  deactivate Index

  Note over App,Got: If timeout provided, it overrides default during client initialization.
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I nibbled the clocks till they learned to wait,
A hop, a skip—timeouts propagate! ⏱️
From burrow to host, the wires align,
Each request now keeps better time.
Thump-thump—downloads race, then rest—
A rabbit’s code runs at its best.
(_/)>

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title accurately and concisely summarizes the primary change, which is the addition of an optional timeout parameter to the HTTP client API, directly reflecting the modifications in IdsHost and related request methods.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@netlify
Copy link

netlify bot commented Oct 8, 2025

Deploy Preview for detsys-ts-docs ready!

Name Link
🔨 Latest commit 1084b25
🔍 Latest deploy log https://app.netlify.com/projects/detsys-ts-docs/deploys/68e5b27ef0bb110008a70a20
😎 Deploy Preview https://deploy-preview-111--detsys-ts-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

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

🧹 Nitpick comments (1)
src/index.ts (1)

737-809: Add optional timeout parameter to unpackClosure and pass it to fetchArtifact

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 285768c and 1084b25.

⛔ Files ignored due to path filters (3)
  • dist/index.d.ts is excluded by !**/dist/**
  • dist/index.js is excluded by !**/dist/**
  • dist/index.js.map is excluded by !**/dist/**, !**/*.map
📒 Files selected for processing (2)
  • src/ids-host.ts (1 hunks)
  • src/index.ts (7 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/ids-host.ts (1)
dist/index.js (1)
  • DEFAULT_TIMEOUT (412-412)
src/index.ts (1)
dist/index.js (4)
  • binaryPath (914-914)
  • versionCheckup (1074-1074)
  • correlatedUrl (1071-1071)
  • client (1114-1114)
🔇 Additional comments (3)
src/index.ts (3)

489-493: LGTM! Timeout parameter correctly propagated.

The fetchExecutable method now accepts an optional timeout and passes it through to fetchArtifact, enabling per-call timeout customization.


575-587: LGTM! Client creation with timeout support.

The getClient method correctly accepts and propagates the timeout parameter to idsHost.getGot, allowing customization of request timeouts.


821-870: LGTM! Download file with timeout support.

The downloadFile method correctly accepts the timeout parameter and uses it when creating the Got client for streaming the download.

Comment on lines +49 to +54
timeout?: number,
): Promise<Got> {
if (this.client === undefined) {
this.client = got.extend({
timeout: {
request: DEFAULT_TIMEOUT,
request: timeout ?? DEFAULT_TIMEOUT,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Client caching breaks per-call timeout customization.

The client is cached in this.client (line 51) and reused for all subsequent calls. Once created with a specific timeout, that timeout persists for all future requests, ignoring any different timeout values passed to later getGot calls.

For example:

  • First call: getGot(undefined, 5000) creates client with 5s timeout
  • Second call: getGot(undefined, 30000) reuses the same client (still 5s timeout)

This defeats the purpose of the timeout parameter.

Solution: Remove the client caching or make the cache timeout-aware:

Option 1 (Recommended): Remove caching

   async getGot(
     recordFailoverCallback?: (
       incitingError: unknown,
       prevUrl: URL,
       nextUrl: URL,
     ) => void,
     timeout?: number,
   ): Promise<Got> {
-    if (this.client === undefined) {
-      this.client = got.extend({
+    return got.extend({
         timeout: {
           request: timeout ?? DEFAULT_TIMEOUT,
         },
 
         retry: {
           limit: Math.max((await this.getUrlsByPreference()).length, 3),
           methods: ["GET", "HEAD"],
         },
 
         hooks: {
           beforeRetry: [
             async (error, retryCount) => {
               const prevUrl = await this.getRootUrl();
               this.markCurrentHostBroken();
               const nextUrl = await this.getRootUrl();
 
               if (recordFailoverCallback !== undefined) {
                 recordFailoverCallback(error, prevUrl, nextUrl);
               }
 
               actionsCore.info(
                 `Retrying after error ${error.code}, retry #: ${retryCount}`,
               );
             },
           ],
 
           beforeRequest: [
             async (options) => {
               // The getter always returns a URL, even though the setter accepts a string
               const currentUrl: URL = options.url as URL;
 
               if (this.isUrlSubjectToDynamicUrls(currentUrl)) {
                 const newUrl: URL = new URL(currentUrl);
 
                 const url: URL = await this.getRootUrl();
                 newUrl.host = url.host;
 
                 options.url = newUrl;
                 actionsCore.debug(`Transmuted ${currentUrl} into ${newUrl}`);
               } else {
                 actionsCore.debug(`No transmutations on ${currentUrl}`);
               }
             },
           ],
         },
       });
-    }
-
-    return this.client;
   }

Remove the client field from the constructor as well:

   constructor(
     idsProjectName: string,
     diagnosticsSuffix: string | undefined,
     runtimeDiagnosticsUrl: string | undefined,
   ) {
     this.idsProjectName = idsProjectName;
     this.diagnosticsSuffix = diagnosticsSuffix;
     this.runtimeDiagnosticsUrl = runtimeDiagnosticsUrl;
-    this.client = undefined;
   }

And remove the field declaration:

 export class IdsHost {
   private idsProjectName: string;
   private diagnosticsSuffix?: string;
   private runtimeDiagnosticsUrl?: string;
   private prioritizedURLs?: URL[];
-  private client?: Got;

Option 2: Make cache timeout-aware (more complex)

Use a Map to cache clients by timeout value, but this adds complexity and may not be worth it if clients are lightweight to create.

🤖 Prompt for AI Agents
In src/ids-host.ts around lines 49 to 54, the method caches a single got client
on this.client and reuses it for all calls so a client created with one timeout
will incorrectly apply that timeout to subsequent calls; remove the persistent
client cache and instantiate a new got client per getGot call (or, if you prefer
caching, implement a timeout-aware cache keyed by timeout values) so that the
passed timeout parameter is respected for each request; also remove the client
field from the class (or change its type to a Map keyed by timeout) and update
any constructor references accordingly.

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