@@ -32,6 +32,7 @@ import { SubchannelAddress, TcpSubchannelAddress } from './subchannel-address';
32
32
import { GrpcUri , uriToString , splitHostPort } from './uri-parser' ;
33
33
import { isIPv6 , isIPv4 } from 'net' ;
34
34
import { ChannelOptions } from './channel-options' ;
35
+ import { BackoffOptions , BackoffTimeout } from './backoff-timeout' ;
35
36
36
37
const TRACER_NAME = 'dns_resolver' ;
37
38
@@ -85,6 +86,8 @@ class DnsResolver implements Resolver {
85
86
private latestServiceConfigError : StatusObject | null = null ;
86
87
private percentage : number ;
87
88
private defaultResolutionError : StatusObject ;
89
+ private backoff : BackoffTimeout ;
90
+ private continueResolving = false ;
88
91
constructor (
89
92
private target : GrpcUri ,
90
93
private listener : ResolverListener ,
@@ -119,6 +122,18 @@ class DnsResolver implements Resolver {
119
122
details : `Name resolution failed for target ${ uriToString ( this . target ) } ` ,
120
123
metadata : new Metadata ( ) ,
121
124
} ;
125
+
126
+ const backoffOptions : BackoffOptions = {
127
+ initialDelay : channelOptions [ 'grpc.initial_reconnect_backoff_ms' ] ,
128
+ maxDelay : channelOptions [ 'grpc.max_reconnect_backoff_ms' ] ,
129
+ } ;
130
+
131
+ this . backoff = new BackoffTimeout ( ( ) => {
132
+ if ( this . continueResolving ) {
133
+ this . startResolutionWithBackoff ( ) ;
134
+ }
135
+ } , backoffOptions ) ;
136
+ this . backoff . unref ( ) ;
122
137
}
123
138
124
139
/**
@@ -140,6 +155,7 @@ class DnsResolver implements Resolver {
140
155
return ;
141
156
}
142
157
if ( this . dnsHostname === null ) {
158
+ trace ( 'Failed to parse DNS address ' + uriToString ( this . target ) ) ;
143
159
setImmediate ( ( ) => {
144
160
this . listener . onError ( {
145
161
code : Status . UNAVAILABLE ,
@@ -148,6 +164,7 @@ class DnsResolver implements Resolver {
148
164
} ) ;
149
165
} ) ;
150
166
} else {
167
+ trace ( 'Looking up DNS hostname ' + this . dnsHostname ) ;
151
168
/* We clear out latestLookupResult here to ensure that it contains the
152
169
* latest result since the last time we started resolving. That way, the
153
170
* TXT resolution handler can use it, but only if it finishes second. We
@@ -164,6 +181,7 @@ class DnsResolver implements Resolver {
164
181
this . pendingLookupPromise . then (
165
182
( addressList ) => {
166
183
this . pendingLookupPromise = null ;
184
+ this . backoff . reset ( ) ;
167
185
const ip4Addresses : dns . LookupAddress [ ] = addressList . filter (
168
186
( addr ) => addr . family === 4
169
187
) ;
@@ -263,10 +281,21 @@ class DnsResolver implements Resolver {
263
281
}
264
282
}
265
283
284
+ private startResolutionWithBackoff ( ) {
285
+ this . startResolution ( ) ;
286
+ this . backoff . runOnce ( ) ;
287
+ }
288
+
266
289
updateResolution ( ) {
267
- trace ( 'Resolution update requested for target ' + uriToString ( this . target ) ) ;
290
+ /* If there is a pending lookup, just let it finish. Otherwise, if the
291
+ * backoff timer is running, do another lookup when it ends, and if not,
292
+ * do another lookup immeidately. */
268
293
if ( this . pendingLookupPromise === null ) {
269
- this . startResolution ( ) ;
294
+ if ( this . backoff . isRunning ( ) ) {
295
+ this . continueResolving = true ;
296
+ } else {
297
+ this . startResolutionWithBackoff ( ) ;
298
+ }
270
299
}
271
300
}
272
301
0 commit comments