How to deal with an external service failure in Open-Uri?

In my Rails application, I am trying to extract several exchange rates from an external service and store them in the cache:

require 'open-uri'

module ExchangeRate

  def self.all
    Rails.cache.fetch("exchange_rates", :expires_in => 24.hours) { load_all }
  end

  private

    def self.load_all
      hashes = {}
      CURRENCIES.each do |currency|
        begin
          hash = JSON.parse(open(URI("http://api.fixer.io/latest?base=#{currency}")).read) #what if not available?
          hashes[currency] = hash["rates"]
        rescue Timeout::Error
          puts "Timeout"
        rescue OpenURI::Error => e
          puts e.message
        end
      end
      hashes
    end

end

This works great in development, but the production environment bothers me. How can I prevent caching of all this if the external service is unavailable? How can I guarantee that it ExchangeRate.allalways contains data, even if it is old and cannot be updated due to an external service failure?

I tried to add basic error handling, but I'm afraid this is not enough.

+4
source share
1 answer

, , 24 , , - , load_all.

:

  • , ExchangeRate.all ( nil, ):

    module ExchangeRate
      def self.all
        rates = Rails.cache.fetch("exchange_rates")
        UpdateCurrenciesJob.perform_later if rates.nil?
        rates
      end
    end
    
  • ActiveJob, :

    class UpdateCurrenciesJob < ApplicationJob
      queue_as :default
    
      def perform(*_args)
        hashes = {}
        CURRENCIES.each do |currency|
          begin
            hash = JSON.parse(open(URI("http://api.fixer.io/latest?base=#{currency}")).read) # what if not available?
            hashes[currency] = hash['rates'].merge('updated_at' => Time.current)
          rescue Timeout::Error
            puts 'Timeout'
          rescue OpenURI::Error => e
            puts e.message
          end
    
          if hashes[currency].blank? || hashes[currency]['updated_at'] < Time.current - 24.hours
            # send a mail saying "this currency hasn't been updated"
          end
        end
    
        Rails.cache.write('exchange_rates', hashes)
      end
    end
    
  • (4, 8, 12, 24). , , , , .

0
source

Source: https://habr.com/ru/post/1676629/


All Articles