Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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
You can’t perform that action at this time.