Skip to content

Commit 6278da6

Browse files
George Kampitakisgkampitakis
authored andcommitted
support selecting resolver via env
1 parent c3d073b commit 6278da6

File tree

1 file changed

+38
-20
lines changed

1 file changed

+38
-20
lines changed

packages/grpc-js/src/resolver-dns.ts

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import {
2020
registerResolver,
2121
registerDefaultScheme,
2222
} from './resolver';
23-
import { AnyRecord } from 'dns';
2423
import * as dns from 'dns/promises';
2524
import { extractAndSelectServiceConfig, ServiceConfig } from './service-config';
2625
import { Status } from './constants';
@@ -45,7 +44,8 @@ function trace(text: string): void {
4544
*/
4645
export const DEFAULT_PORT = 443;
4746

48-
const DEFAULT_MIN_TIME_BETWEEN_RESOLUTIONS_MS = 30_000;
47+
const DEFAULT_MIN_TIME_BETWEEN_RESOLUTIONS_MS = 30_000,
48+
DNS_RESOLUTION_ENV = 'GRPC_DNS_RESOLVER_TODO';
4949

5050
/**
5151
* Resolver implementation that handles DNS names and IP addresses.
@@ -60,7 +60,7 @@ class DnsResolver implements Resolver {
6060
* Failures are handled by the backoff timer.
6161
*/
6262
private readonly minTimeBetweenResolutionsMs: number;
63-
private pendingLookupPromise: Promise<AnyRecord[]> | null = null;
63+
private pendingLookupPromise: Promise<TcpSubchannelAddress[]> | null = null;
6464
private pendingTxtPromise: Promise<string[][]> | null = null;
6565
private latestLookupResult: Endpoint[] | null = null;
6666
private latestServiceConfig: ServiceConfig | null = null;
@@ -73,7 +73,7 @@ class DnsResolver implements Resolver {
7373
private isNextResolutionTimerRunning = false;
7474
private isServiceConfigEnabled = true;
7575
private returnedIpResult = false;
76-
private resolver = new dns.Resolver();
76+
private independentResolver = new dns.Resolver();
7777

7878
constructor(
7979
private target: GrpcUri,
@@ -82,7 +82,7 @@ class DnsResolver implements Resolver {
8282
) {
8383
trace('Resolver constructed for target ' + uriToString(target));
8484
if (target.authority) {
85-
this.resolver.setServers([target.authority]);
85+
this.independentResolver.setServers([target.authority]);
8686
}
8787
const hostPort = splitHostPort(target.path);
8888
if (hostPort === null) {
@@ -187,11 +187,7 @@ class DnsResolver implements Resolver {
187187
* revert to an effectively blank one. */
188188
this.latestLookupResult = null;
189189
const hostname: string = this.dnsHostname;
190-
/* We lookup both address families here and then split them up later
191-
* because when looking up a single family, dns.lookup outputs an error
192-
* if the name exists but there are no records for that family, and that
193-
* error is indistinguishable from other kinds of errors */
194-
this.pendingLookupPromise = this.resolver.resolveAny(hostname);
190+
this.pendingLookupPromise = this.lookup(hostname);
195191
this.pendingLookupPromise.then(
196192
addressList => {
197193
if (this.pendingLookupPromise === null) {
@@ -200,19 +196,12 @@ class DnsResolver implements Resolver {
200196
this.pendingLookupPromise = null;
201197
this.backoff.reset();
202198
this.backoff.stop();
203-
const subchannelAddresses: TcpSubchannelAddress[] = addressList
204-
.filter(addr => {
205-
addr.type === 'A' || addr.type === 'AAAA';
206-
})
207-
.map(addr => ({ host: addr.address, port: +this.port! }));
208-
this.latestLookupResult = subchannelAddresses.map(address => ({
199+
this.latestLookupResult = addressList.map(address => ({
209200
addresses: [address],
210201
}));
211202
const allAddressesString: string =
212203
'[' +
213-
subchannelAddresses
214-
.map(addr => addr.host + ':' + addr.port)
215-
.join(',') +
204+
addressList.map(addr => addr.host + ':' + addr.port).join(',') +
216205
']';
217206
trace(
218207
'Resolved addresses for target ' +
@@ -257,7 +246,7 @@ class DnsResolver implements Resolver {
257246
/* We handle the TXT query promise differently than the others because
258247
* the name resolution attempt as a whole is a success even if the TXT
259248
* lookup fails */
260-
this.pendingTxtPromise = this.resolver.resolveTxt(hostname);
249+
this.pendingTxtPromise = this.resolveTxt(hostname);
261250
this.pendingTxtPromise.then(
262251
txtRecord => {
263252
if (this.pendingTxtPromise === null) {
@@ -306,6 +295,35 @@ class DnsResolver implements Resolver {
306295
}
307296
}
308297

298+
private async lookup(hostname: string): Promise<TcpSubchannelAddress[]> {
299+
if (process.env[DNS_RESOLUTION_ENV] === 'true') {
300+
const records = await this.independentResolver.resolveAny(hostname);
301+
const addressList = records.filter(addr => {
302+
addr.type === 'A' || addr.type === 'AAAA';
303+
}) as unknown as { address: string }[];
304+
305+
return addressList.map(addr => ({
306+
host: addr.address,
307+
port: +this.port!,
308+
}));
309+
}
310+
311+
/* We lookup both address families here and then split them up later
312+
* because when looking up a single family, dns.lookup outputs an error
313+
* if the name exists but there are no records for that family, and that
314+
* error is indistinguishable from other kinds of errors */
315+
const addressList = await dns.lookup(hostname, { all: true });
316+
return addressList.map(addr => ({ host: addr.address, port: +this.port! }));
317+
}
318+
319+
private async resolveTxt(hostname: string): Promise<string[][]> {
320+
if (process.env[DNS_RESOLUTION_ENV] === 'true') {
321+
return this.independentResolver.resolveTxt(hostname);
322+
}
323+
324+
return dns.resolveTxt(hostname);
325+
}
326+
309327
private startNextResolutionTimer() {
310328
clearTimeout(this.nextResolutionTimer);
311329
this.nextResolutionTimer = setTimeout(() => {

0 commit comments

Comments
 (0)