dns: refactor dns.resolve
Checklist
-
tests and code linting passes -
a test and/or benchmark is included -
documentation is changed or added -
the commit message follows commit guidelines
Affected core subsystem(s)
dns
Description of change
This is in-progress and still needs additional work and review before it can land.
This seeks to address issue https://github.com/nodejs/node/issues/1071 in a couple of ways.
- An internal ref counter is used to count the number of outstanding dns.resolve() requests are still pending. If this number is > 0 when dns.setServers() is called, an error will be thrown.
- dns.resolve() will now return an EventEmitter that can emit three
possible events:
'error'
,'resolve'
and'complete'
.
Previously, if there were any errors reported while setting up the
dns.resolve operation, they would be thrown immediately. However, any
errors that occur during the dns.operation would be passed to the
callback function as the first argument. Now, all errors are routed
through the 'error'
event on the EventEmitter. This makes the error
handling more consistent but changes the flow since dns.resolve*()
will no longer throw immediately.
If a callback is passed to dns.resolve*()
, which is the current
usage pattern, it is set as the handler for both the 'resolve'
and 'error'
events.
Alternatively, it is now possible to omit the callback and add
listeners directly to the EventEmitter returned by dns.resolve_().
The 'resolve'
listener is passed *only_ the results of the
resolve (errors are passed to 'error'
).
So, for example, you can continue to do this:
dns.resolve('www.example.org', 'A', (err, addresses) => {
if (err) { /** ... **/ }
// do stuff
});
Or you can do:
dns.resolve('www.example.org', 'A')
.on('resolve', (addresses) => {
// do stuff
})
.on('error', (error) => {
// handle it
})
.on('complete', () => {
// do this here because otherwise it'll throw.
dns.setServers([]);
}).
On the dns.setServers()
part, the 'complete'
event is emitted using
setImmediate()
. This ensures that the event is not emitted until after
c-ares has an opportunity to clean up. This avoids the assert that brings
down the Node process if setServers is called at the wrong time.
/cc @mscdex @silverwind @nodejs/ctc