Skip to content

Instantly share code, notes, and snippets.

@joshuacronemeyer
Last active June 28, 2016 21:52
Show Gist options
  • Save joshuacronemeyer/15babefaaf67df66a5e6fb01623adf22 to your computer and use it in GitHub Desktop.
Save joshuacronemeyer/15babefaaf67df66a5e6fb01623adf22 to your computer and use it in GitHub Desktop.
Emergency cache middleware
class EmergencyCache
CACHE_WAS_USED_VERY_RECENTLY_KEY = "event-document-emergency-cache-was-used-recently"
def is_in_emergency_mode?
Rails.cache.exists(CACHE_WAS_USED_VERY_RECENTLY_KEY)
end
def enable_emergency_mode
Rails.logger.error("[EventDocumentEmergencyCache] Using emergency event document cache for next 15 seconds")
Rails.cache.setex(CACHE_WAS_USED_VERY_RECENTLY_KEY, 15, "set");
end
def write(key, event_document)
Rails.cache.write(key, event_document, expires_in: 24.hours)
end
def read(key)
Rails.logger.error("[EventDocumentEmergencyCache] Reading from emergency event document cache")
Rails.cache.read(key)
end
end
#i would like to have the emergency cache be in middleware. it doesn't need to understand our domain and could be an HTTP level concept
#this is untested but potentially realistic pseudocode i created by studying faraday-http-cache gem and faraday
class EmergencyCacheMiddleware < Faraday::Middleware
def call(env)
#if emergency cache is on, respond from the cache
if event_document_emergency_cache.is_in_emergency_mode?
cache_payload = event_document_emergency_cache.read(cache_key(env))
if cache_payload
env.update(payload)
return Faraday::Response.new(env)
end
end
@app.call(env).on_complete do |response|
case response.status
when 200
#if we got a good response save it for a rainy day
event_document_emergency_cache = EmergencyCache.new
event_document_emergency_cache.write(cache_key(env), response)
when 404
when 400..599
#if we got an error response we trigger the emergency cache circuit breaker and respond with last known value
event_document_emergency_cache = EmergencyCache.new
event_document_emergency_cache.enable_emergency_mode
cache_payload = event_document_emergency_cache.read(cache_key(env))
if cache_payload
#change this error response into something successful
#not sure if this is the right way to do
response.status = 200
response.update(payload)
end
end
end
end
def cache_key(env)
hash = env.to_hash
{ method: hash[:method], url: hash[:url] }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment