Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update caching #280

Merged
merged 3 commits into from
Nov 30, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,13 @@ gem 'friendly_id', '~> 5.0.3'

gem 'rack-timeout'

group :production, :staging do
# Caching
gem 'rack-cache'
gem 'dalli'
gem 'kgio'
gem 'memcachier'

group :production do
# Heroku recommended
gem 'rails_12factor'
end
Expand Down
8 changes: 8 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ GEM
simplecov (>= 0.7)
term-ansicolor
thor
dalli (2.7.2)
database_cleaner (1.3.0)
debug_inspector (0.0.2)
devise (3.4.1)
Expand Down Expand Up @@ -124,6 +125,7 @@ GEM
rb-kqueue (>= 0.2)
mail (2.6.3)
mime-types (>= 1.16, < 3)
memcachier (0.0.2)
mime-types (2.4.3)
mini_portile (0.6.1)
minitest (5.4.3)
Expand Down Expand Up @@ -153,6 +155,8 @@ GEM
quiet_assets (1.0.3)
railties (>= 3.1, < 5.0)
rack (1.5.2)
rack-cache (1.2)
rack (>= 0.4)
rack-cors (0.2.9)
rack-test (0.6.2)
rack (>= 1.0)
Expand Down Expand Up @@ -281,6 +285,7 @@ DEPENDENCIES
capybara
coffee-rails (~> 4.1.0)
coveralls
dalli
database_cleaner (>= 1.0.0.RC1)
devise (~> 3.4)
enumerize
Expand All @@ -292,13 +297,16 @@ DEPENDENCIES
haml-rails (~> 0.5.3)
jquery-rails
kaminari
kgio
listen (~> 1.0)
memcachier
pg
pg_search
poltergeist
protected_attributes
pundit
quiet_assets (>= 1.0.2)
rack-cache
rack-cors
rack-timeout
rails (~> 4.1.1)
Expand Down
5 changes: 3 additions & 2 deletions app/controllers/api/v1/locations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ class LocationsController < ApplicationController
include CustomErrors
include Cacheable

after_action :set_cache_control, only: [:index, :show]

def index
locations = Location.includes(:organization, :address, :phones).
page(params[:page]).per(params[:per_page]).
Expand All @@ -21,8 +23,7 @@ def show
services: [:categories, :contacts, :phones, :regular_schedules,
:holiday_schedules]
).find(params[:id])
render json: location, status: 200
expires_in cache_time, public: true
render json: location, status: 200 if stale?(location, public: true)
end

def update
Expand Down
21 changes: 13 additions & 8 deletions app/controllers/api/v1/search_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ class SearchController < ApplicationController
include CustomErrors
include Cacheable

after_action :set_cache_control, only: :index

def index
locations = Location.search(params).page(params[:page]).
per(params[:per_page])

render json: locations.preload(tables), each_serializer: LocationsSerializer, status: 200
generate_pagination_headers(locations)
expires_in cache_time, public: true
if stale?(etag: cache_key(locations), public: true)
generate_pagination_headers(locations)
render json: locations.preload(tables), each_serializer: LocationsSerializer, status: 200
end
end

def nearby
Expand All @@ -26,17 +29,19 @@ def nearby
private

def tables
if params[:org_name].present? && params[:location].present?
[:address, :phones]
else
[:organization, :address, :phones]
end
[:organization, :address, :phones]
end

def locations_near(location)
location.nearbys(params[:radius]).status('active').
page(params[:page]).per(params[:per_page]).includes(:address)
end

def cache_key(scope)
Digest::MD5.hexdigest(
"#{scope.to_sql}-#{scope.maximum(:updated_at)}-#{scope.total_count}"
)
end
end
end
end
4 changes: 4 additions & 0 deletions app/controllers/concerns/cacheable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@ module Cacheable
def cache_time
ENV['EXPIRES_IN'].to_i.minutes
end

def set_cache_control
expires_in cache_time, public: true
end
end
16 changes: 8 additions & 8 deletions config/application.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,13 @@
#
#############
# This setting defines how long, in minutes, API responses will be cached in
# a web client, such as Ohana Web Search:
# https://github.com/codeforamerica/ohana-web-search
# For example, if you set EXPIRES_IN to '5', when you do a search or
# visit a specific location in Ohana Web Search, the app won't make that same
# API request until 5 minutes have passed since the request was first made.
# This greatly improves the performance of Ohana Web Search, and also reduces
# the load on the API.
# Rack::Cache. During that time interval, any API requests for that same
# query (after the initial request) will be served by Rack::Cache instead
# of the app, thereby reducing the load on the API and serving responses
# quickly.
# Read more about HTTP Caching:
# http://railscasts.com/episodes/321-http-caching?view=asciicast
# https://devcenter.heroku.com/articles/http-caching-ruby-rails

######################################
#
Expand Down Expand Up @@ -189,7 +189,7 @@ production:
DEV_SUBDOMAIN:
DEFAULT_PER_PAGE: '30'
MAX_PER_PAGE: '50'
EXPIRES_IN: '5'
EXPIRES_IN: '1'
TLD_LENGTH: '2'
ENABLE_HTTPS: yes

Expand Down
13 changes: 12 additions & 1 deletion config/environments/development.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,18 @@

# Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false

# Uncomment the section below to test HTTP caching in development.
# You'll need to install memcached if you don't already have it:
# brew install memcached
#
# config.action_controller.perform_caching = true
# config.cache_store = :dalli_store
# client = Dalli::Client.new
# config.action_dispatch.rack_cache = {
# metastore: client,
# entitystore: client
# }

# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false
Expand Down
47 changes: 32 additions & 15 deletions config/environments/production.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,7 @@
config.eager_load = true

# Full error reports are disabled and caching is turned on.
config.consider_all_requests_local = false
config.action_controller.perform_caching = true

# Enable Rack::Cache to put a simple HTTP cache in front of your application
# Add `rack-cache` to your Gemfile before enabling this.
# For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid.
# config.action_dispatch.rack_cache = true

# Disable Rails's static asset server (Apache or nginx will already do this).
config.serve_static_assets = false
config.consider_all_requests_local = false

# Compress JavaScripts and CSS.
config.assets.js_compressor = :uglifier
Expand All @@ -33,9 +24,6 @@
# Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false

# Generate digests for assets URLs.
config.assets.digest = true

# `config.assets.version` and `config.assets.precompile` have moved to config/initializers/assets.rb

# Specifies the header that your server uses for sending files.
Expand All @@ -54,8 +42,37 @@
# Use a different logger for distributed setups.
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)

# Use a different cache store in production.
# config.cache_store = :mem_cache_store
# --------------------------------------------------------------------------
# CACHING SETUP FOR RACK:CACHE AND MEMCACHIER ON HEROKU
# https://devcenter.heroku.com/articles/rack-cache-memcached-rails31
# ------------------------------------------------------------------

config.serve_static_assets = true

# Generate digests for assets URLs.
config.assets.digest = true

config.action_controller.perform_caching = true

config.cache_store = :dalli_store
client = Dalli::Client.new((ENV['MEMCACHIER_SERVERS'] || '').split(','),
username: ENV['MEMCACHIER_USERNAME'],
password: ENV['MEMCACHIER_PASSWORD'],
failover: true,
socket_timeout: 1.5,
socket_failure_delay: 0.2,
value_max_bytes: 10_485_760)

# Enable Rack::Cache to put a simple HTTP cache in front of your application.
# Add `rack-cache` to your Gemfile before enabling this.
# For large-scale production use, consider using a caching reverse proxy like
# nginx, varnish or squid.
config.action_dispatch.rack_cache = {
metastore: client,
entitystore: client
}
config.static_cache_control = 'public, max-age=2592000'
# --------------------------------------------------------------------------

# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = "http://assets.example.com"
Expand Down
96 changes: 0 additions & 96 deletions config/environments/staging.rb

This file was deleted.

5 changes: 4 additions & 1 deletion script/setup_heroku
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ then
echo "Installing Mandrill by MailChimp"
heroku addons:add mandrill --app $herokuApp

echo "Installing Memcachier"
heroku addons:add memcachier --app $herokuApp

echo "All done setting up env vars and add-ons."
echo "Pushing code to Heroku now. This will take a few minutes..."
git push heroku master
Expand All @@ -38,4 +41,4 @@ then
else
echo "Please add your Heroku app name to the end of the command."
echo "Usage: setup_heroku your_app_name"
fi
fi