Heroku Cedar Stack - Rack Cache Headers
Asked Answered
L

1

8

I can't figure this out for the life of me. Trying to use Rack::Cache to cache some of my static public pages on Heroku, in addition to doing action caching in case it gets past the reverse proxy.

For example, here's the code in my "home" action:

class StaticPagesController < ApplicationController
  layout 'public'

  caches_action :about, :contact, ......, :home, .....

  ......

  def home
    last_modified = File.mtime("#{Rails.root}/app/views/static_pages/home.html.haml")
    fresh_when last_modified: last_modified , public: true, etag: last_modified
    expires_in 10.seconds, :public => true       
  end

For all intents and purposes, this should have a public cache-control tag with max-age 10 no?

$ curl -I http://myapp-staging.herokuapp.com/

HTTP/1.1 200 OK
Cache-Control: max-age=0, private, must-revalidate
Content-Type: text/html; charset=utf-8
Date: Thu, 24 May 2012 06:50:45 GMT
Etag: "997dacac05aa4c73f5a6861c9f5a9db0"
Status: 200 OK
Vary: Accept-Encoding
X-Rack-Cache: stale, invalid
X-Request-Id: 078d86423f234da1ac41b418825618c2
X-Runtime: 0.005902
X-Ua-Compatible: IE=Edge,chrome=1
Connection: keep-alive

Am I doing something horribly wrong? I feel like there is something up with that stale, invalid cache response... that is about the 4th time I've hit the page.

Config Info:

# Use a different cache store in production
config.cache_store = :dalli_store

config.action_dispatch.rack_cache = {
  :verbose      => true,
  :metastore => "memcached://#{ENV['MEMCACHE_SERVERS']}",
  :entitystore => "memcached://#{ENV['MEMCACHE_SERVERS']}"#,
}

# OLD : Disable Rails's static asset server (Apache or nginx will already do this)
config.serve_static_assets = true
config.static_cache_control = "public, max-age=2592000"

(Maybe there's a way to manually set the cache-control header? Seems like there should be an easier way though).

UPDATE

I have even tried taking the controller action down to the bare minimum :

def home
  expires_in 10.seconds, :public => true
  #last_modified = File.mtime("#{Rails.root}/app/views/static_pages/home.html.haml")
  #fresh_when last_modified: last_modified , public: true, etag: last_modified
end

And it doesn't work...

HTTP/1.1 200 OK
Server: nginx
Date: Thu, 24 May 2012 19:15:18 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Status: 200 OK
X-Ua-Compatible: IE=Edge,chrome=1
Etag: "733798214c652f39ae79b4037e9111dc"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: b33087fe0c2ae986c4cac88f14420b7c
X-Runtime: 0.006000
X-Rack-Cache: stale, invalid
Vary: Accept-Encoding
X-Varnish: 349105873
Age: 0
Via: 1.1 varnish

!

Lowell answered 24/5, 2012 at 6:53 Comment(5)
Is this even possible with action caching? Have you tested it with page caching just to see how the headers differ?Amarillas
hmmm I see your point. If Rack::Cache is properly set up to serve pages (not the cleanest method, but best you can do on Heroku), I really shouldn't have anything in there for caching actions. I suppose I just had that in there for good measure. I'll try taking that out and seeing what happens. Will get back to you.Lowell
So it appears you are right. When I took the action caching out, the headers were correctly set. I don't know that I necessarily understand this though. Shouldn't setting HTTP response headers be separate from caching the results of an action? I.e., shouldn't I be able to cache the response of my rails app (action cache) but still set the HTTP headers such that if a user re-requests a page, they don't hit the server at all (provided correct settings on the max-age header?)Lowell
Yeah, I'm not completely sure. My impression is that the whole point of action caching is to hit app server – you might have filters (for authentication, or whatever) – regardless of the request headers. Otherwise, how could you rely on your before_filter appropriately being called?Amarillas
You should probably take a look at these three articles on Heroku's Dev Center, regarding caching: devcenter.heroku.com/articles/… devcenter.heroku.com/articles/caching-strategies devcenter.heroku.com/articles/http-caching-ruby-railsKania
K
1

Maybe rethink the whole thing and just use rails caching. The new cache_digests gem should make it trivial to do what you want at the rails level: https://github.com/rails/cache_digests

I'm willing to bet this will beat your method that includes doing a filesystem call to check the file timestamp every 10 seconds.

Kbp answered 8/3, 2013 at 18:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.