mazing
mazing

Reputation: 743

Rails 5 caching isn't working locally or in production

I'm trying to get data from this external data source and display it in my app locally and in production, and since requesting the data fresh every time can be resource-intensive, I want to cache it for a relative amount of time which could be 15 minutes, 1 hour, etc. I wrote this code, but it doesn't show any kind of caching at all.

covid_controller.rb

require "net/http"
class Covid19::CovidController < ApplicationController
  def index
    @covid_news_posts = CovidNewsPost.published.limit(10).order("created_at DESC").includes([:user])
    cache_key_with_version = CovidNewsPost.last
        @cache = Rails.cache.fetch("#{cache_key_with_version}", expires_in: 15.minutes) do
            covid_api_url = "https://bing.com/covid/data"
            resp = Net::HTTP.get_response(URI.parse(covid_api_url))
            covidapi = JSON.parse(resp.body)
        end
  end
end

production.rb

  ## CACHING RELATED THINGS
  config.action_controller.perform_caching = true

  # Use a different cache store in production.
  config.cache_store = :memory_store, { size: 64.megabytes }

development.rb

  # Enable/disable caching. By default caching is disabled.
  if Rails.root.join('tmp/caching-dev.txt').exist?
    config.action_controller.perform_caching = true

    config.cache_store = :memory_store
    config.public_file_server.headers = {
      'Cache-Control' => "public, max-age=#{2.days.seconds.to_i}"
    }
  else
    config.action_controller.perform_caching = false

    config.cache_store = :null_store
  end

Not sure what to do here, just want to load the request server side once and then serve it cached for however long is needed.

Here's a request from production not showing any caching

I, [2020-04-13T20:46:40.057029 #2088]  INFO -- : [aee0a42a-0d29-432d-af0e-0f21bb5253d9] Started GET "/covid19" for 71.113.156.118 at 2020-04-13 20:46:40 +0000
I, [2020-04-13T20:46:40.060499 #2088]  INFO -- : [aee0a42a-0d29-432d-af0e-0f21bb5253d9] Processing by Covid19::CovidController#index as HTML
D, [2020-04-13T20:46:40.063881 #2088] DEBUG -- : [aee0a42a-0d29-432d-af0e-0f21bb5253d9]   User Load (0.7ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 1], ["LIMIT", 1]]
D, [2020-04-13T20:46:40.065930 #2088] DEBUG -- : [aee0a42a-0d29-432d-af0e-0f21bb5253d9]   CovidNewsPost Load (0.6ms)  SELECT  "covid_news_posts".* FROM "covid_news_posts" ORDER BY "covid_news_posts"."id" DESC LIMIT $1  [["LIMIT", 1]]
I, [2020-04-13T20:46:40.458451 #2088]  INFO -- : [aee0a42a-0d29-432d-af0e-0f21bb5253d9]   Rendering layouts/application.html.erb
I, [2020-04-13T20:46:40.458928 #2088]  INFO -- : [aee0a42a-0d29-432d-af0e-0f21bb5253d9]   Rendering covid19/covid/index.html.erb within layouts/application
I, [2020-04-13T20:46:40.460280 #2088]  INFO -- : [aee0a42a-0d29-432d-af0e-0f21bb5253d9]   Rendered covid19/_covid19_menu.html.erb (0.3ms)
D, [2020-04-13T20:46:40.462798 #2088] DEBUG -- : [aee0a42a-0d29-432d-af0e-0f21bb5253d9]   CovidNewsPost Load (1.7ms)  SELECT  "covid_news_posts".* FROM "covid_news_posts" WHERE "covid_news_posts"."published" = $1 ORDER BY created_at DESC LIMIT $2  [["published", true], ["LIMIT", 10]]
D, [2020-04-13T20:46:40.465690 #2088] DEBUG -- : [aee0a42a-0d29-432d-af0e-0f21bb5253d9]   User Load (0.9ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN ($1, $2, $3, $4, $5, $6)  [["id", 251], ["id", 3], ["id", 860], ["id", 208], ["id", 1985], ["id", 2794]]
I, [2020-04-13T20:46:40.476577 #2088]  INFO -- : [aee0a42a-0d29-432d-af0e-0f21bb5253d9]   Rendered static/global/_footer.html.erb (1.6ms)
I, [2020-04-13T20:46:40.476792 #2088]  INFO -- : [aee0a42a-0d29-432d-af0e-0f21bb5253d9]   Rendered covid19/covid/index.html.erb within layouts/application (17.8ms)
I, [2020-04-13T20:46:40.477422 #2088]  INFO -- : [aee0a42a-0d29-432d-af0e-0f21bb5253d9]   Rendered application/_favicon.html.erb (0.4ms)
I, [2020-04-13T20:46:40.478655 #2088]  INFO -- : [aee0a42a-0d29-432d-af0e-0f21bb5253d9]   Rendered layouts/application.html.erb (20.1ms)
I, [2020-04-13T20:46:40.479248 #2088]  INFO -- : [aee0a42a-0d29-432d-af0e-0f21bb5253d9] Completed 200 OK in 419ms (Views: 18.4ms | ActiveRecord: 3.9ms)

Upvotes: 0

Views: 1376

Answers (1)

Chris Heald
Chris Heald

Reputation: 62698

cache_key_with_version is assigned to CovidNewsPost.last, which is probably an ActiveRecord instance. This is then cast to a string and used as the cache key. Any variation in this string will cause a new cache entry to be fetched and populated, and the string representation of the record is not necessarily guaranteed to be consistent in any particular way.

You probably want to use a more specific string, like "#{cache_key_with_version.id}-#{cache_key_with_version.version}" to ensure that only the fields you intend to be a part of the cache key are in fact part of the cache key.

That aside, you can verify if caching is configured correctly at all with a Rails console:

2.times.map { Rails.cache.fetch("test", expires_in: 1) { rand } }.uniq.length == 1

If caching is configured and working correctly, you'll see true. If not, you'll get false.

Upvotes: 1

Related Questions