2013-09-01 52 views
1

獲取我們用這個來從外部API值:Rails的緩存與故障轉移

def get_value 
    Rails.cache.fetch "some_key", expires_in: 15.second do 
    # hit some external API 
    end 
end 

但有時候外部API下降,當我們嘗試打它,它會引發異常。

爲了解決這個問題,我們想:

  1. 嘗試更新它每15秒
  2. 但是,如果它脫機,使用舊的價值達5分鐘,重試每隔15秒左右
  3. ,如果它已經過期超過5分鐘,然後再開始引發異常

有一個方便的包裝/庫這或會是什麼好的解決辦法?我們可以編寫一些自定義的代碼,但它似乎是一個常見的用例,應該在這裏進行一些測試。謝謝!

回答

2

最終沒有找到什麼好的解決方案,使最終使用這樣的:

# 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(在收益率)。