Skip to content

Commit

Permalink
Add support for distributed caching
Browse files Browse the repository at this point in the history
  • Loading branch information
freshlogic committed Jul 5, 2019
1 parent 9f2ad3d commit 0cd4fff
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 38 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,8 @@ notifications:
- secure: "SOyb1L7KTf/NxLj+lunFnq4UJxXVIHHwFdPwIe4c3VbBZOeUR/0x+b2swNgJ+/rnra0Th+RCZTZ99LrBGpFchFI6hYXjLVdGGL8LhyfUuREG2tW7/MsQfTQuZwqqc6cc0trn4VGSJYVHDW428XUPc3VIJyrV1KP8NBsmMl499AY="
on_success: always

services:
- redis-server

script:
- npm run coveralls
2 changes: 1 addition & 1 deletion carriers/pitneyBowes.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function PitneyBowes(options) {

// Lookup each location
async.mapLimit(locations, 10, function(location, callback) {
geography.parseLocation(location, function(err, address) {
geography.parseLocation(location, options, function(err, address) {
if (err || !address) {
return callback(err, address);
}
Expand Down
6 changes: 3 additions & 3 deletions carriers/usps.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ function USPS(options) {
const locations = Array.from(new Set(scanDetailsList.map(scanDetail => scanDetail.location)));

// Lookup each location
async.mapLimit(locations, 10, function (location, callback) {
geography.parseLocation(location, function (err, address) {
async.mapLimit(locations, 10, function(location, callback) {
geography.parseLocation(location, options, function(err, address) {
if (err || !address) {
return callback(err, address);
}
Expand All @@ -132,7 +132,7 @@ function USPS(options) {

callback(null, address);
});
}, function (err, addresses) {
}, function(err, addresses) {
if (err) {
return callback(err);
}
Expand Down
10 changes: 10 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ const FedEx = require('./carriers/fedEx');
const USPS = require('./carriers/usps');

function Bloodhound(options) {
// Allow PitneyBowes to cache geocode results in Redis (via petty-cache)
if (options && options.pettyCache && options.pitneyBowes) {
options.pitneyBowes.pettyCache = options.pettyCache;
}

// Allow USPS to cache geocode results in Redis (via petty-cache)
if (options && options.pettyCache && options.usps) {
options.usps.pettyCache = options.pettyCache;
}

const fedEx = new FedEx(options && options.fedEx);
const pitneyBowes = new PitneyBowes(options && options.pitneyBowes);
const usps = new USPS(options && options.usps);
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"async": "~3.1.0",
"moment-timezone": "~0.5.25",
"node-geocoder": "~3.23.0",
"petty-cache": "~2.4.1",
"pitney-bowes": "~0.1.0",
"shipping-fedex": "0.2.0",
"tz-lookup": "~6.1.18",
Expand Down Expand Up @@ -35,5 +36,5 @@
"type": "git",
"url": "https://github.com/mediocre/bloodhound.git"
},
"version": "0.2.2"
"version": "0.3.0"
}
1 change: 1 addition & 0 deletions test/carriers/pitneyBowes.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ describe('Newgistics', function() {

it('should return an error for invalid base URL', function(done) {
const bloodhound = new Bloodhound({
pettyCache: {},
pitneyBowes: {
baseUrl: 'https://httpbin.org/status/500#'
}
Expand Down
17 changes: 17 additions & 0 deletions test/util/geography.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,21 @@ describe('geography.parseLocation', function() {
done();
});
});
});

describe('petty-cache', function() {
it('should store results in Redis (via petty-cache)', function(done) {
geography.parseLocation('Carrollton, TX', { pettyCache: {} }, function(err, actual) {
assert.ifError(err);

const expected = {
city: 'Carrollton',
state: 'TX',
timezone: 'America/Chicago'
};

assert.deepStrictEqual(actual, expected);
done();
});
});
});
90 changes: 57 additions & 33 deletions util/geography.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,59 @@
const async = require('async');
const NodeGeocoder = require('node-geocoder');
const normalize = require('us-states-normalize');
const PettyCache = require('petty-cache');
const tzlookup = require('tz-lookup');

const geocoder = NodeGeocoder({ provider: 'openstreetmap' });
var pettyCache;

function geocode(location, callback) {
// Geocode the location
async.retry(function(callback) {
geocoder.geocode(location, callback);
async.auto({
geocode: function(callback) {
// Geocode the location
async.retry(function(callback) {
geocoder.geocode(location, callback);
}, function(err, results) {
if (err) {
return callback(err);
}

if (!results.length) {
return callback();
}

const firstResult = results[0];

// Check to see if the first result has the data we need
if (firstResult.city && firstResult.state && firstResult.zipcode) {
return callback(null, firstResult);
}

// Reverse geocode to ensure we get a city, state, and zip
async.retry(function(callback) {
geocoder.reverse({ lat: firstResult.latitude, lon: firstResult.longitude }, callback);
}, function(err, results) {
if (err) {
return callback(err);
}

callback(null, results[0]);
});
});
}
}, function(err, results) {
if (err) {
return callback(err);
}

if (!results.length) {
if (!results.geocode) {
return callback();
}

const firstResult = results[0];

// Check to see if the first result has the data we need
if (firstResult.city && firstResult.state && firstResult.zipcode) {
return callback(null, firstResult);
}

// Reverse geocode to ensure we get a city, state, and zip
async.retry(function(callback) {
geocoder.reverse({ lat: firstResult.latitude, lon: firstResult.longitude }, callback);
}, function(err, results) {
if (err) {
return callback(err);
}

callback(null, results[0]);
callback(null, {
city: results.geocode.city,
state: normalize(results.geocode.state),
timezone: tzlookup(results.geocode.latitude, results.geocode.longitude)
});
});
}
Expand Down Expand Up @@ -68,20 +88,24 @@ exports.addressToString = function(address) {
return value.trim();
};

exports.parseLocation = async.memoize(function(location, callback) {
geocode(location, function(err, result) {
if (err) {
return callback(err);
}
exports.parseLocation = async.memoize(function(location, options, callback) {
// Options are optional
if (typeof options === 'function') {
callback = options;
options = undefined;
}

if (!result) {
return callback();
// Use Redis (via Petty Cache)
if (options && options.pettyCache) {
if (!pettyCache) {
pettyCache = new PettyCache(options.pettyCache.port, options.pettyCache.host, options.pettyCache.options);
}

callback(null, {
city: result.city,
state: normalize(result.state),
timezone: tzlookup(result.latitude, result.longitude)
});
});
// Cache between 1-2 months
return pettyCache.fetch(`bloodhound.geocode:${location}`, function(callback) {
geocode(location, callback);
}, { ttl: { min: 2592000000, max: 5184000000 } }, callback);
}

geocode(location, callback);
});

0 comments on commit 0cd4fff

Please sign in to comment.