geolocation api rate-limit: split cache instance, one for each provider

This commit is contained in:
sedum
2023-01-21 01:18:16 +01:00
parent c50d369de9
commit ad3ace1e7e
3 changed files with 26 additions and 18 deletions

View File

@@ -4,7 +4,6 @@ const nominatim = require('../../services/geocoding/nominatim')
const photon = require('../../services/geocoding/photon') const photon = require('../../services/geocoding/photon')
const axios = require('axios') const axios = require('axios')
const { version } = require('../../../package.json') const { version } = require('../../../package.json')
const cache = require('memory-cache');
let d = 0 // departure time let d = 0 // departure time
let h = 0 // hit geocoding provider time (aka Latency) let h = 0 // hit geocoding provider time (aka Latency)
@@ -27,7 +26,7 @@ const geocodingController = {
* - Note that the usage limits above apply per website/application: the sum of traffic by all your users should not exceed the limits. * - Note that the usage limits above apply per website/application: the sum of traffic by all your users should not exceed the limits.
* - If at all possible, set up a proxy and also enable caching of requests. * - If at all possible, set up a proxy and also enable caching of requests.
*/ */
providerRateLimit (req, res, next, providerCommonName) { providerRateLimit (req, res, next, providerCache) {
let a = Date.now(); // arrival time let a = Date.now(); // arrival time
let dprev = d let dprev = d
d = dprev + 1000 + h d = dprev + 1000 + h
@@ -37,7 +36,7 @@ const geocodingController = {
// console.log('d: ' + d) // console.log('d: ' + d)
// if the same request was already cached skip the delay mechanism // if the same request was already cached skip the delay mechanism
if (cache.get(providerCommonName + '_' + req.params.place_details)) { if (providerCache.get(req.params.place_details)) {
if (a < d) { if (a < d) {
log.warn('More than 1 request per second to geocoding api. This from ' + req.ip + ' . The response data is served from memory-cache.') log.warn('More than 1 request per second to geocoding api. This from ' + req.ip + ' . The response data is served from memory-cache.')
} }
@@ -67,19 +66,18 @@ const geocodingController = {
}, },
async nominatimRateLimit(req, res, next) { async nominatimRateLimit(req, res, next) {
geocodingController.providerRateLimit(req, res, next, nominatim.commonName) geocodingController.providerRateLimit(req, res, next, nominatim.cache)
}, },
async photonRateLimit(req, res, next) { async photonRateLimit(req, res, next) {
geocodingController.providerRateLimit(req, res, next, photon.commonName) geocodingController.providerRateLimit(req, res, next, photon.cache)
}, },
async checkInCache (req, res, details, providerCommonName) { async checkInCache (req, res, details, providerCache) {
if (cache.get(providerCommonName + '_' + details)) { const ret = await providerCache.get(details)
const ret = await cache.get(providerCommonName + '_' + details) if (ret) {
return ret return ret
} else { } else {
// console.log('Not in cache')
return return
} }
}, },
@@ -102,7 +100,7 @@ const geocodingController = {
} }
// Cache the response data // Cache the response data
cache.put(provider.commonName + '_' + details, ret.data, 1000 * 60 * 60 * 24); provider.cache.put(details, ret.data, 1000 * 60 * 60 * 24);
// console.log(cache.keys()) // console.log(cache.keys())
// console.log(cache.exportJson()) // console.log(cache.exportJson())
return ret.data return ret.data
@@ -112,7 +110,7 @@ const geocodingController = {
async _nominatim (req, res) { async _nominatim (req, res) {
const details = req.params.place_details const details = req.params.place_details
const ret = await geocodingController.checkInCache(req, res, details, nominatim.commonName) || const ret = await geocodingController.checkInCache(req, res, details, nominatim.cache) ||
await geocodingController.queryProvider(req, res, details, nominatim) await geocodingController.queryProvider(req, res, details, nominatim)
return res.json(ret) return res.json(ret)
@@ -122,7 +120,7 @@ const geocodingController = {
async _photon (req, res) { async _photon (req, res) {
const details = req.params.place_details const details = req.params.place_details
const ret = await geocodingController.checkInCache(req, res, details, photon.commonName) || const ret = await geocodingController.checkInCache(req, res, details, photon.cache) ||
await geocodingController.queryProvider(req, res, details, photon) await geocodingController.queryProvider(req, res, details, photon)
return res.json(ret) return res.json(ret)

View File

@@ -1,10 +1,13 @@
const cache = require('memory-cache')
const providerCache = new cache.Cache()
module.exports = { const nominatim = {
commonName: 'Nominatim', commonName: 'Nominatim',
DEFAULT_ENDPOINT: 'https://nominatim.openstreetmap.org/search', DEFAULT_ENDPOINT: 'https://nominatim.openstreetmap.org/search',
endpoint: (req, res) => { endpoint: (req, res) => {
return res.locals.settings.geocoding_provider || this.DEFAULT_ENDPOINT return res.locals.settings.geocoding_provider || nominatim.DEFAULT_ENDPOINT
}, },
cache: providerCache,
getParams (req, res) { getParams (req, res) {
const countrycodes = res.locals.settings.geocoding_countrycodes || [] const countrycodes = res.locals.settings.geocoding_countrycodes || []
@@ -20,4 +23,6 @@ module.exports = {
} }
}, },
} }
module.exports = nominatim

View File

@@ -1,10 +1,13 @@
const cache = require('memory-cache')
const providerCache = new cache.Cache()
module.exports = { const photon = {
commonName: 'Photon', commonName: 'Photon',
DEFAULT_ENDPOINT: 'https://photon.komoot.io/api/', DEFAULT_ENDPOINT: 'https://photon.komoot.io/api/',
endpoint: (req, res) => { endpoint: (req, res) => {
return res.locals.settings.geocoding_provider || this.DEFAULT_ENDPOINT return res.locals.settings.geocoding_provider || photon.DEFAULT_ENDPOINT
}, },
cache: providerCache,
getParams (req, res) { getParams (req, res) {
const details = req.params.place_details const details = req.params.place_details
@@ -15,4 +18,6 @@ module.exports = {
} }
} }
} }
module.exports = photon