-
Notifications
You must be signed in to change notification settings - Fork 30.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dns: refactor dns.resolve #6285
Conversation
Part 1 seems reasonable. I see that you seek to address the issue of the user calling Would it be unreasonable to ask the user to use |
Would it be possible to just call automatically |
@silverwind ... Asking the user to use That is, this works: dns.resolve('www.example.org', 'A', (err, addrs) => {
setImmediate(() => dns.setServers([]));
}); But this doesn't: 'use strict';
const dns = require('dns');
dns.resolve('www.example.org', 'A', (err, addrs) => {
console.log(addrs);
});
setImmediate(() => {
dns.setServers([]);
}); While it is reasonable to ask the user to only call @mscdex ... possibly but I think that would also put us into a race condition again, which I'm trying to avoid. I plan to keep looking at it tho as time allows. I'm definitely not saying that the approach taken in this PR is the "right* approach. I will say that this revised version has a couple of things going for it:
|
This seeks to address issue nodejs#1071 in a couple of ways: 1. 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. 2. 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: ```js dns.resolve('www.example.org', 'A', (err, addresses) => { if (err) { /** ... **/ } // do stuff }); ``` Or you can do: ```js 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.
ceadfb5
to
3066845
Compare
Sigh... the original push missed a few edits that I forgot to |
026c9ac
to
4571b86
Compare
7da4fd4
to
c7066fb
Compare
Checklist
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 #1071 in a couple of ways.
dns.resolve() requests are still pending. If this number is > 0
when dns.setServers() is called, an error will be thrown.
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 errorhandling 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 currentusage 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 theresolve (errors are passed to
'error'
).So, for example, you can continue to do this:
Or you can do:
On the
dns.setServers()
part, the'complete'
event is emitted usingsetImmediate()
. This ensures that the event is not emitted until afterc-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