我们使用它来从外部API获取值:
def get_value
Rails.cache.fetch "some_key", expires_in: 15.second do
# hit some external API
end
end
但有时外部API会下降,当我们试图点击它时,会引发异常。
为了解决这个问题,我们想:
是否有一个方便的包装/库,或者什么是一个好的解决方案?我们可以编写一些自定义的东西,但它似乎是一个常见的用例,应该有一些战斗测试。谢谢!
答案 0 :(得分:4)
没有找到任何好的解决方案,所以最终使用了这个:
# This helper is useful for caching a response from an API, where the API is unreliable
# It will try to refresh the value every :expires_in seconds, but if the block throws an exception it will use the old value for up to :fail_in seconds before actually raising the exception
def cache_with_failover key, options=nil
key_fail = "#{key}_fail"
options ||= {}
options[:expires_in] ||= 15.seconds
options[:fail_in] ||= 5.minutes
val = Rails.cache.read key
return val if val
begin
val = yield
Rails.cache.write key, val, expires_in: options[:expires_in]
Rails.cache.write key_fail, val, expires_in: options[:fail_in]
return val
rescue Exception => e
val = Rails.cache.read key_fail
return val if val
raise e
end
end
# Demo
fail = 10.seconds.from_now
a = cache_with_failover('test', expires_in: 5.seconds, fail_in: 10.seconds) do
if Time.now < fail
Time.now
else
p 'failed'
raise 'a'
end
end
更好的解决方案可能会在第一次失败后以指数方式退出重试。正如它目前所写的那样,它会在第一次失败后重试(在收益率方面)击败api。