Skip to content
This repository has been archived by the owner on Feb 8, 2023. It is now read-only.

Commit

Permalink
feat: support lookup with timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
fengmk2 committed Sep 26, 2016
1 parent 00f3417 commit cc72e13
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 5 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
sudo: false
language: node_js
node_js:
- 6
- 4
- '6'
- '4'
script:
- npm run ci
after_script:
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ failover-dns

Use local cache dns query result when dns query fail.

- Support dns lookup with `options.timeout`.

## Installation

```bash
Expand All @@ -37,7 +39,7 @@ const dns = require('failover-dns');
// must listen `error` event to logging by yourself
dns.on('error', err => console.error(err));

dns.lookup('cnpmjs.org', { family: 4 }, (err, ip, family) => {
dns.lookup('cnpmjs.org', { family: 4, timeout: 2000 }, (err, ip, family) => {
if (err) throw err;
console.log(ip, family);
});
Expand Down
29 changes: 27 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ exports.lookup = function lookup(hostname, options, callback) {
callback = options;
options = {};
}
options = options || {};

// don't failover on `options.all = true`
if (options.all) {
// don't failover on options.all
return dns.lookup(hostname, options, callback);
}

const cacheKey = `${hostname}_${options.family}_${options.hints}`;
dns.lookup(hostname, options, (err, ip, family) => {
exports._lookupWithTimeout(hostname, options, (err, ip, family) => {
if (err) {
const address = DNS_LOOKUP_CACHE[cacheKey];
if (address) {
Expand Down Expand Up @@ -49,3 +51,26 @@ exports.lookup = function lookup(hostname, options, callback) {
callback(null, ip, family);
});
};

exports._lookupWithTimeout = function lookupWithTimeout(hostname, options, callback) {
if (!options.timeout) {
return dns.lookup(hostname, options, callback);
}
let timer = setTimeout(() => {
timer = null;
const cb = callback;
callback = null;
const err = new Error(`getaddrinfo TIMEOUT ${hostname}`);
err.options = options;
err.code = 'TIMEOUT';
cb(err);
}, options.timeout);

dns.lookup(hostname, options, (err, ip, family) => {
timer && clearTimeout(timer);
if (!callback) {
return;
}
callback(err, ip, family);
});
};
60 changes: 60 additions & 0 deletions test/failover-dns.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,26 @@ describe('test/failover-dns.test.js', () => {
});
});

it('should lookup with options=null from dns server', done => {
dns.lookup('a.alipayobjects.com', null, (err, ip, family) => {
console.log(err, ip, family);
assert(err == null);
assert((/^\d+\.\d+\.\d+\.\d+$/).test(ip));
assert(family === 4);
done();
});
});

it('should lookup with options.timeout', done => {
dns.lookup('as.alipayobjects.com', { timeout: 5000 }, (err, ip, family) => {
console.log(err, ip, family);
assert(err == null);
assert((/^\d+\.\d+\.\d+\.\d+$/).test(ip));
assert(family === 4);
done();
});
});

it('should lookup with options.family from dns server', done => {
dns.lookup('cnpmjs.org', { family: 4 }, (err, ip, family) => {
console.log(err, ip, family);
Expand Down Expand Up @@ -66,6 +86,46 @@ describe('test/failover-dns.test.js', () => {
});
});

it('should mock timeout then return address from local cache', done => {
done = pedding(2, done);
mm(require('dns'), 'lookup', (hostname, options, callback) => {
setTimeout(() => {
callback(null, '127.0.0.1', 4);
}, 600);
});

dns.once('error', err => {
console.log(err);
assert(err.message === 'getaddrinfo TIMEOUT a.alipayobjects.com');
done();
});
dns.lookup('a.alipayobjects.com', { family: 4, timeout: 500 }, (err, ip, family) => {
console.log('lookup result', err, ip, family);
assert(err == null);
assert((/^\d+\.\d+\.\d+\.\d+$/).test(ip));
assert(family === 4);
// wait for dns.lookup() done and ignore callback
setTimeout(done, 200);
});
});

it('should mock timeout and local cache missing', done => {
mm(require('dns'), 'lookup', (hostname, options, callback) => {
setTimeout(() => {
callback(null, '127.0.0.1', 4);
}, 600);
});

dns.lookup('foo.cnpmjs.org', { family: 4, timeout: 500 }, (err, ip, family) => {
console.log('lookup result', err, ip, family);
assert(err);
assert(err.message === 'getaddrinfo TIMEOUT foo.cnpmjs.org');
assert(err.code === 'TIMEOUT');
// wait for dns.lookup() done and ignore callback
setTimeout(done, 200);
});
});

it('should lookup with options.all from dns server', done => {
dns.lookup('a.alipayobjects.com', { all: true }, (err, ips) => {
console.log(err, ips);
Expand Down

0 comments on commit cc72e13

Please sign in to comment.