Skip to content

Improving performance with caching

Moncef Belyamani edited this page Mar 9, 2018 · 9 revisions

Depending on how many visitors your app gets, you might want to improve the performance of the app by configuring two types of caching: one is caching the API requests via Faraday::HttpCache in config/initializers/ohanapi.rb, and the other is caching the entire results page and/or location details page in cacheable.rb and locations_controller.rb

API request caching is turned on by default, and will prevent the app from making the same API request for a period of time specified by the API. By default, that is set to 1 minute. That means that if a location's info has changed on the API side, if Ohana Web Search had already requested that same location, the latest data changes won't appear in Ohana Web Search until 1 minute has passed since the first request was made.

As for page caching, it is disabled by default. If you determine that you need to cache pages, you can turn it on by setting the ENABLE_CACHING environment variable on your production server to true. If you're using Heroku, you can set it like this:

$ heroku config:set ENABLE_CACHING=true -a your_heroku_app_name

When page caching is enabled, it will store the page in Memcached via the MemCachier add-on on Heroku (by default) so that the next time any browser requests that same page, it will be served from cache instead of the server. In addition to the app storing the page in Memcached, most modern browsers will also store the page in their cache, and will send an If-Modified-Since date and an If-None-Match Etag in the Request Headers to ask the server if a newer version exists.

The server will determine whether or not a newer version of the page is available by comparing both the updated_at fields in the API response, and the current Git commit's SHA-1. This means that if you push changes to the page, the browser cache will be automatically invalidated.

One way to set the LAST_COMMIT_HASH environment variable to the latest commit hash is to create a shell script called pre-push in your .git/hooks directory. For example:

#!/bin/sh

url="$2"

if [[ "$url" =~ heroku ]]; then
  appname=your_heroku_app_name # make sure to replace this with your actual app name
  hash_name=LATEST_COMMIT_HASH
  hash=$(git rev-parse HEAD)
  echo "Setting $hash_name to $hash on app $appname"
  heroku config:set $hash_name="$hash" --app $appname
fi

exit 0

You'll then need to make it executable:

chmod 755 .git/hooks/pre-push

Note that this will only work if you deploy to Heroku with git push heroku master from the local repository that contains the pre-push git hook.

Other similar and some more robust solutions:

https://github.com/n8/bust_rails_etags

http://stackoverflow.com/questions/27453054/get-heroku-release-number-code-version-from-a-running-dyno

http://stackoverflow.com/a/22702304

Note that this is only one caching solution. For other caching strategies, visit the following resources:

https://robots.thoughtbot.com/a-guide-to-caching-your-rails-application-with-fastly

https://devcenter.heroku.com/articles/http-caching-ruby-rails

https://devcenter.heroku.com/articles/caching-strategies

http://railscasts.com/episodes/321-http-caching

Testing caching in development

You'll need to install Memcached if you don't already have it. On OS X, the easiest way to install it is via Homebrew:

brew install memcached

For other operating systems, visit the Memcached website.

Also make sure to set the following key in the development section of your config/application.yml file:

ENABLE_CACHING: 'true'

Then uncomment lines 22-28 in development.rb, save the file, and restart the server.