Rails.cache.fetch with expires_in only expire if n

2019-08-01 02:09发布

问题:

I want to do a simple Rails.cache.fetch and expire it after about 10 minutes. The cache gets filled with json data from an external API. However the external API is not reachable sometimes. So when the cache expires and tries to fetch new json data, the cache content gets invalid.

How can I make Rails.cache.fetch ONLY EXPIRE the cache if the fetch_json returns valid data? However the cache should expire after 10 minutes if it receives new valid data.

This is how I tried to do it, but it does not work. Better Code highlighting in this Gist: https://gist.github.com/i42n/6094528

Any tips how I can get this work?

module ExternalApiHelper

    require 'timeout'
    require 'net/http'

    def self.fetch_json(url)
        begin
            result = Timeout::timeout(2) do # 2 seconds
                # operation that may cause a timeout
                uri = URI.parse(url)
                http = Net::HTTP.new(uri.host, uri.port)
                request = Net::HTTP::Get.new(uri.request_uri)
                response = http.request(request)
                return JSON.parse(response.body)
            end
            return result
        rescue
            # if any error happens in the block above, return empty string
            # this will result in fetch_json_with_cache using the last value in cache
            # as long as no new data arrives
            return ""
        end
    end

    def self.fetch_json_with_cache(url, expire_time)
        cache_backup = Rails.cache.read(url)
        api_data = Rails.cache.fetch(url, :expires_in => expire_time) do
            new_data = fetch_json(url)
            if new_data.blank?
                # if API fetch did not return valid data, return the old cache state
                cache_backup
            else
                new_data
            end
        end
        return api_data
    end

end

回答1:

Solved it like this. Maybe not the most elegant way to do it, but works: https://github.com/ReliveRadio/reliveradio-website/blob/4874cf4158361c73a693e65643d9e7f11333d9d6/app/helpers/external_api_helper.rb