Skip to content

refactor(NODE-7313): only use dns.resolve for all types#4846

Open
durran wants to merge 12 commits intomainfrom
NODE-7313
Open

refactor(NODE-7313): only use dns.resolve for all types#4846
durran wants to merge 12 commits intomainfrom
NODE-7313

Conversation

@durran
Copy link
Member

@durran durran commented Jan 22, 2026

Description

Refactors all dns resolution to only go through lookup and resolve.

Summary of Changes

  • Refactors dns resolution to only use lookup and resolves
  • Fixes all tests

What is the motivation for this change?

NODE-7313

Release Highlight

Release notes highlight

Double check the following

  • Lint is passing (npm run check:lint)
  • Self-review completed using the steps outlined here
  • PR title follows the correct format: type(NODE-xxxx)[!]: description
    • Example: feat(NODE-1234)!: rewriting everything in coffeescript
  • Changes are covered by tests
  • New TODOs have a related JIRA ticket

@tadjik1 tadjik1 marked this pull request as ready for review February 9, 2026 12:08
@tadjik1 tadjik1 requested a review from a team as a code owner February 9, 2026 12:08
Comment on lines 49 to 60
return async function dnsReqRetryTimeout(lookupAddress: string) {
try {
return await dns.promises[api](lookupAddress);
return (await dns.promises.resolve(lookupAddress, rrtype)) as dns.SrvRecord[] | string[][];
} catch (firstDNSError) {
if (firstDNSError.code === dns.TIMEOUT) {
return await dns.promises[api](lookupAddress);
return (await dns.promises.resolve(lookupAddress, rrtype)) as dns.SrvRecord[] | string[][];
} else {
throw firstDNSError;
}
}
};
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we choose an approach that doesn't necessitate casting? One approach would be something like:

Suggested change
return async function dnsReqRetryTimeout(lookupAddress: string) {
try {
return await dns.promises[api](lookupAddress);
return (await dns.promises.resolve(lookupAddress, rrtype)) as dns.SrvRecord[] | string[][];
} catch (firstDNSError) {
if (firstDNSError.code === dns.TIMEOUT) {
return await dns.promises[api](lookupAddress);
return (await dns.promises.resolve(lookupAddress, rrtype)) as dns.SrvRecord[] | string[][];
} else {
throw firstDNSError;
}
}
};
}
const resolve =
rrtype === 'SRV'
? (address: string) => dns.promises.resolve(address, 'SRV')
: (address: string) => dns.promises.resolve(address, 'TXT');
return async function dnsReqRetryTimeout(lookupAddress: string) {
try {
return await resolve(lookupAddress);
} catch (firstDNSError) {
if (firstDNSError.code === dns.TIMEOUT) {
return await resolve(lookupAddress);
} else {
throw firstDNSError;
}
}
};

Another would be modifying the function to instead accept a lookup function, which it then calls.

Copy link
Member

Choose a reason for hiding this comment

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

@PavelSafronov I have updated this block using generics (basically map rrtype to response). please let me know if this works

Copy link
Contributor

Choose a reason for hiding this comment

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

There's still a cast, it's just been moved to a different place

Copy link
Member

@tadjik1 tadjik1 Feb 18, 2026

Choose a reason for hiding this comment

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

In my view it's essentially the same as you suggested, but with the different mechanism: generics vs. runtime if-else:

const resolve =
    rrtype === 'SRV'
      ? (address: string) => dns.promises.resolve(address, 'SRV')
      : (address: string) => dns.promises.resolve(address, 'TXT');

// is effectively the same as (from the Typescript point of view)

interface DNSLookupMap {
  SRV: dns.SrvRecord[];
  TXT: string[][];
}

const resolve = () => dns.promises.resolve(lookupAddress, rrtype) as Promise<DNSLookupMap[T]>;

In other words, I don't want to add runtime check for the compilation step (it just feels wrong, however I'm not strongly against it).

Would you agree? Or is it casting in general that you would like to avoid?

Copy link
Contributor

Choose a reason for hiding this comment

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

Casting in general. I don't feel terribly strongly, but if we have the capability to write this in way that doesn't require casting, I guess I don't see why we wouldn't?

Runtime checks to have a perf cost (although in general I think an if-statement is effectively negligable). But regardless, this is a factory, so the perf cost is once per module instantiation per function.

Copy link
Member

Choose a reason for hiding this comment

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

agree! switched implementation back (with the resolve being defined with ternary condition)

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.

3 participants

Comments