# frozen_string_literal: true require 'json' require 'cgi' require 'typhoeus' module JDX module Geocoder module Base attr_reader :data def search !fetch_data ? nil : self end private def fetch_data cache_data = redis_fetch @data = if cache_data == '' nil elsif cache_data @cache_hit = true parse_json(cache_data) else @cache_hit = false make_api_request end end def make_api_request is_response_success, parsed_data = handle_response return unless is_response_success serialize_data(parsed_data).tap do |data| if !!data && data.any? cache_data(data) else blacklist_term end end end def typhoeus_get Typhoeus.get(url, timeout: 10) end def handle_request_error(response) if response.timed_out? error_handler.warning("Geocoding #{self.class} Failed: Request Timeout Error") elsif response.code.zero? error_handler.warning("Geocoding #{self.class} Failed: #{response.return_message}") else error_handler.warning("Geocoding #{self.class} Failed: #{response.code}") end end def parse_json(raw_data) JSON.parse(raw_data) end def redis_fetch script = <<~LUA local cache = redis.call("GET", KEYS[1]) if cache == false then cache = redis.call("GET", KEYS[2]) end return cache LUA cache_redis.eval(script, [wterm, bterm]) end def blacklist_term cache_redis.set(bterm, '', ex: 3600, nx: true) end def cache_data(serialized_data) cache_redis.set(wterm, JSON.dump(serialized_data)) end def escape_term ::CGI.escape(@term) end def cache_redis raise GeoError, "Can't call on base module" end def wterm "w:#{@term}" end def bterm "b:#{@term}" end def error_handler @error_handler ||= JDX::Geocoder.configuration.error_handler end end end end