Skip to content

Instantly share code, notes, and snippets.

@joho
Created September 13, 2012 01:30
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save joho/3711251 to your computer and use it in GitHub Desktop.
Save joho/3711251 to your computer and use it in GitHub Desktop.
How to serve emergency "signed out" views from page cache without affecting signed in users in rails.

Webscale in an emergency for Rails

Lets say hypothetically your app makes the front page of reddit, and you've got no caching in place yet. Lets say that the page is "static enough" for signed out users, and you want them off your rails stack.

This cap task/nginx conf combo will let you do that in a hurry.

Essentially:

  • the nginx config will preferentially serve files from a public/cache_zone folder ahead of regular public lookups for static content
  • the nginx config will also set the cache zone depending on if you have an auth cookie ("remember_user_token" in our case)
  • the cap task ssh's to your app box and curls the content into the public/signed_out folder
  • now all users without an auth cookie will get the static html
  • voila, webscale
set :path_to_repo, "/path_to_repo/"
set :running_app_user, "appusername"
namespace :webscale do
desc "Cache a signed out version of the path. Usage: cap webscale:signed_out_cache_page -s path_to_cache=/films/on_netflix"
task :signed_out_cache, roles: :app do
cache_base_path = "#{path_to_repo}/public/signed_out"
cached_destination_path = "#{cache_base_path}#{path_to_cache}.html"
working_path = "#{cached_destination_path}.tmp"
commands = [
# ensure path to store the cached file exists
"#{sudo} mkdir -p #{File.dirname(cached_destination_path)}",
# curl the current page contents into a temporary file
"#{sudo} sh -c \"curl -H 'host: YOURHOSTNAME.COM' localhost#{path_to_cache} > #{working_path}\"",
# echo a html comment with debug info into the cache
"#{sudo} sh -c \"echo '<!-- cached at #{Time.now} -->' >> #{working_path}\"",
# move the tmp file into it's proper place
"#{sudo} mv -f #{working_path} #{cached_destination_path}",
# make sure the permissions are all good again
"#{sudo} chown -R #{running_app_user}:#{running_app_user} #{File.dirname(cache_base_path)}"
]
# run them all in a big and chain
run commands.join(' && ')
end
end
root /path_to_repo/public;
set $cache_zone "signed_out";
if ($http_cookie ~* "remember_user_token") {
set $cache_zone "signed_in";
}
add_header "X-YourApp-Cache-Zone" $cache_zone;
try_files /system/maintenance.html /$cache_zone$uri/index.html /$cache_zone$uri.html /$cache_zone$uri $uri/index.html $uri.html $uri @app;
location @app {
proxy_pass http://app.upstream;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment