1# frozen_string_literal: true
2
3require "cbor"
4require "json"
5
6require_relative "geo_code"
7
8class GeoCodeRepo
9 def initialize(memcache: MEMCACHE)
10 @memcache = memcache
11 end
12
13 def find(q)
14 cache(q) {
15 EM::HttpRequest.new(
16 "https://geocoder.ca/",
17 tls: { verify_peer: true }
18 ).aget(query: { json: 1, locate: q }).then { |res|
19 json = JSON.parse(res.response)
20 raise "Geocode Failure" unless json["latt"] && json["longt"]
21
22 json
23 }
24 }.then(&GeoCode.method(:for))
25 end
26
27protected
28
29 def cache(k, &blk)
30 k = "geocode_#{k.gsub(/ /, '%20')}"
31 promise = EMPromise.new
32 @memcache.get(k, &promise.method(:fulfill))
33 promise.then { |cbor|
34 CBOR.decode(cbor)
35 }.catch(&blk).then { |result|
36 @memcache.set(k, result.to_cbor)
37 result
38 }
39 end
40end