Emi Matchu
6d343989de
Poking at the site, I didn't love that clicking any of the NC items on the homepage took a few seconds to load cuz of the OWLS request taking a couple seconds. If the request were faster to load I might decide otherwise, but for now, let's just keep that cache long. Another approach we could take would be to ask for an endpoint that returns all the values at once, so we could cache and update them all together, instead of having it all split into separate cache keys!
75 lines
1.9 KiB
Ruby
75 lines
1.9 KiB
Ruby
module OwlsValueGuide
|
|
include HTTParty
|
|
|
|
ITEMDATA_URL_TEMPLATE = Addressable::Template.new(
|
|
"https://neo-owls.net/itemdata/{item_name}"
|
|
)
|
|
|
|
def self.find_by_name(item_name)
|
|
# Load the itemdata, pulling from the Rails cache if possible.
|
|
cache_key = "OwlsValueGuide/itemdata/#{item_name}"
|
|
data = Rails.cache.fetch(cache_key, expires_in: 1.day) do
|
|
load_itemdata(item_name)
|
|
end
|
|
|
|
if data == :not_found
|
|
raise NotFound
|
|
end
|
|
|
|
# Owls has records of some items that it explicitly marks as having no
|
|
# listed value. We don't care about that distinction, just return nil!
|
|
return nil if data['owls_value'].blank?
|
|
|
|
Value.new(data['owls_value'], parse_last_updated(data['last_updated']))
|
|
end
|
|
|
|
Value = Struct.new(:value_text, :updated_at)
|
|
|
|
class Error < StandardError;end
|
|
class NetworkError < Error;end
|
|
class NotFound < Error;end
|
|
|
|
private
|
|
|
|
def self.load_itemdata(item_name)
|
|
Rails.logger.info "[OwlsValueGuide] Loading value for #{item_name.inspect}"
|
|
|
|
url = ITEMDATA_URL_TEMPLATE.expand(item_name: item_name)
|
|
begin
|
|
res = get(url)
|
|
rescue StandardError => error
|
|
raise NetworkError, "Couldn't connect to Owls: #{error.message}"
|
|
end
|
|
|
|
if res.code == 404
|
|
# Instead of raising immediately, return `:not_found` to save this
|
|
# result in the cache, then raise *after* we exit the cache block. That
|
|
# way, we won't make repeat requests for items we have that Owls
|
|
# doesn't.
|
|
return :not_found
|
|
end
|
|
|
|
if res.code != 200
|
|
raise NetworkError, "Owls returned status code #{res.code} (expected 200)"
|
|
end
|
|
|
|
begin
|
|
res.parsed_response
|
|
rescue HTTParty::Error => error
|
|
raise NetworkError, "Owls returned unsupported data format: #{error.message}"
|
|
end
|
|
end
|
|
|
|
def self.parse_last_updated(date_str)
|
|
return nil if date_str.blank?
|
|
|
|
begin
|
|
Date.strptime(date_str, '%Y-%m-%d')
|
|
rescue Date::Error
|
|
Rails.logger.error(
|
|
"[OwlsValueGuide] unexpected last_updated format: #{date_str.inspect}"
|
|
)
|
|
return nil
|
|
end
|
|
end
|
|
end
|