在我的Rails应用程序中,我试图从外部服务获取许多货币汇率并将它们存储在缓存中:
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
这在开发中很有用,但我担心生产环境.如果外部服务不可用,如何防止整个事件被缓存?如何确保ExchangeRate.all始终包含数据,即使它已经过时且由于外部服务故障而无法更新?
解决方法
如果您担心外部服务不够可靠,无法每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).这样,货币将在后台加载,客户将始终拥有数据,您将始终知道货币是否不起作用.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。