-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
129 lines (108 loc) · 4.33 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
const counties = {};
const GeoJsonGeometriesLookup = require('geojson-geometries-lookup');
const async = require('async');
const geohash = require('ngeohash');
const localCache = {};
exports.handler = (event, context, callback) => {
const now = new Date().getTime();
let filesRead = 0;
const done = (err, res) => {
const later = new Date().getTime();
const time = (later - now);
if (err) {
err.responseTimeMs = time;
err.filesRead = filesRead;
} else {
res.responseTimeMs = time;
res.filesRead = filesRead;
}
const returnObj = {
statusCode: err ? '400' : '200',
body: err ? JSON.stringify(err) : JSON.stringify(res),
headers:
{
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
};
console.log('Returning object ' + JSON.stringify(returnObj));
return callback(null, returnObj);
};
console.log(event);
if (!event.queryStringParameters) {
return done(null, {});
}
const lat = Number(event.queryStringParameters.lat);
const long = Number(event.queryStringParameters.long);
if (!lat || !long) {
return done({ error: 'lat/long not specified' });
}
const bigHash = geohash.encode(lat, long, 6);
if (localCache[bigHash]) {
console.log('Returning from cache');
return done(null, localCache[bigHash]);
}
//Assuming our results are not in the in-memory cache, we need to geohash the lat & long:
const hash = geohash.encode(lat, long, 3);
//We not only cache direct results in memory, but we also cache the geohash files.
if (!counties[hash]) {
console.log('Reading geohash-' + hash + ' into memory');
try {
filesRead++;
counties[hash] = JSON.parse(require('fs').readFileSync('./geohash-' + hash + '.json'));
} catch (e) {
console.log('File not found, skipping');
}
}
async.series([
(cb) => {
if (counties[hash]) {
const glookup = new GeoJsonGeometriesLookup(counties[hash]);
const point1 = { type: 'Point', coordinates: [long, lat] };
const final = glookup.getContainers(point1);
console.log('Trying ' + hash);
if (final.features && final.features[0] && final.features[0].properties) {
const returnObj = { county: final.features[0].properties.name };
localCache[bigHash] = returnObj;
return done(null, returnObj);
} else {
console.log('Results not in this hash file.');
return cb();
}
} else {
console.log('Could not read hash file.');
return cb();
}
},
(cb) => {
//find neighbors
const neighbors = geohash.neighbors(hash);
async.eachSeries(neighbors, (it, cb) => {
if (!counties[it]) {
console.log('Reading geohash-' + it + ' into memory');
try {
counties[it] = JSON.parse(require('fs').readFileSync('./geohash-' + it + '.json'));
filesRead++;
} catch (e) {
console.log('File not found, skipping');
}
}
if (counties[it]) {
const glookup = new GeoJsonGeometriesLookup(counties[it]);
const point1 = { type: 'Point', coordinates: [long, lat] };
const final = glookup.getContainers(point1);
console.log('Trying ' + it);
if (final.features && final.features[0] && final.features[0].properties) {
const returnObj = { county: final.features[0].properties.name };
localCache[bigHash] = returnObj;
return done(null, returnObj);
}
}
return cb();
}, () => {
console.log('Returning error, county not found');
return done({ error: 'county not found' });
});
}
]);
};