Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Heroku Cedar Stack - Rack Cache Headers

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

!

like image 552
Brandon Avatar asked May 24 '12 06:05

Brandon


1 Answers

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.

like image 170
kwerle Avatar answered Oct 05 '22 23:10

kwerle