'Why won't Rails.cache store API responses?
I am trying to cache the results of API calls. My application makes multiple calls with the same result and I would like it to use the cache to save time. When I use Rails.cache.fetch the block of code (with the API request) is executed every time even though the keys are the same. I have enabled caching in the development environment using rails dev:cache.
I tried to test in the rails console but my local rails console also won't store any keys in the cache. On heroku, the console works for caching but the application still sends every API request.
I have tried to use both memory and file-based caching locally.
Here is the method in application_record.rb
I am removing the parameters that are not consistent or important for my purpose and then using the parameters and path as the cache key.
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
def send_request(params,path)
key = params.except(:token, :start_date, :end_date)
key[:path] = path
puts key.to_s
Rails.cache.fetch(key, expires_in: 5.minutes) do
if (!$token || $token == '') then self.authenticate end
params[:token] = $token
url = URI("https://<api-domain>/"+path+"/?"+params.to_query)
puts '**** sending request *****'
begin
Net::HTTP.start(url.host, url.port, :use_ssl => url.scheme == 'https') do |http|
request = Net::HTTP::Get.new(url)
request["cache-control"] = 'no-cache'
response = http.request(request)
if response.code == "200"
return response
elsif response.code[0] == "4"
puts "recursive = "+response.code
puts response.read_body
$token = nil
send_request(params,path)
else
puts "request_report server error"
puts response.code
puts JSON.parse(response.read_body)
response
end
end
rescue
response = "SocketError: check that the server allows outbound https and that the bucksense API is live"
end
end
end
The log shows that requests are made every time. The first and second requests for both of these campaigns are exactly the same.
Entering new campaign: Show********************************
{:metrics=>"wins,win_rate,ctr,clicks_global", :timezone=>"UTC", :type=>"1", :method=>"getdata", :groupby=>"P1D", :dimensions=>"advertiser_name,campaign_name", :path=>"3.0/report/thirdpart"}
**** sending request *****
{:metrics=>"wins,win_rate,ctr,clicks_global", :timezone=>"UTC", :type=>"1", :method=>"getdata", :groupby=>"P1M", :dimensions=>"advertiser_name,campaign_name", :path=>"3.0/report/thirdpart"}
**** sending request *****
Campaign finished: ********************************
Entering new campaign: ********************************
{:metrics=>"wins,win_rate,ctr,clicks_global", :timezone=>"UTC", :type=>"1", :method=>"getdata", :groupby=>"P1D", :dimensions=>"advertiser_name,campaign_name", :path=>"3.0/report/thirdpart"}
**** sending request *****
{:metrics=>"wins,win_rate,ctr,clicks_global", :timezone=>"UTC", :type=>"1", :method=>"getdata", :groupby=>"P1M", :dimensions=>"advertiser_name,campaign_name", :path=>"3.0/report/thirdpart"}
**** sending request *****
Campaign finished: ********************************
I expect this to make API calls only when the same request has not been made within 5 minutes. Instead, it makes the API call every single time.
Thanks for the help, let me know if I'm making a stupid mistake, or if this is a poor way to achieve my desired results.
Solution 1:[1]
HTTP::Response objects are not serializable, so they can't be stored in the cache. (See this Rails comment.)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |