From 3d647a4b412bea1313af1d3c866b9052e6702772 Mon Sep 17 00:00:00 2001 From: Sam Date: Wed, 16 Oct 2013 16:39:18 +1100 Subject: [PATCH] remove rack cache, it has been causing trouble instead implement an aggressive anonymous cache that is stored in redis this cache is sitting in the front of the middleware stack enabled only in production TODO: expire it more intelligently when stuff is created --- Gemfile | 4 - Gemfile.lock | 10 -- Gemfile_rails4.lock | 16 +--- app/controllers/application_controller.rb | 24 +---- app/controllers/list_controller.rb | 32 +++---- app/controllers/topics_controller.rb | 33 ++++--- config/environments/development.rb | 2 + config/environments/production.rb.sample | 3 - config/environments/profile.rb | 3 - config/initializers/99-rack-cache.rb | 35 ++----- lib/middleware/anonymous_cache.rb | 92 +++++++++++++++++++ .../middleware/anonymous_cache_spec.rb | 41 +++++++++ 12 files changed, 180 insertions(+), 115 deletions(-) create mode 100644 lib/middleware/anonymous_cache.rb create mode 100644 spec/components/middleware/anonymous_cache_spec.rb diff --git a/Gemfile b/Gemfile index 56c042a5127..b27401ad4e7 100644 --- a/Gemfile +++ b/Gemfile @@ -192,10 +192,6 @@ gem 'flamegraph', git: 'https://github.com/SamSaffron/flamegraph.git', require: gem 'rack-mini-profiler', git: 'https://github.com/MiniProfiler/rack-mini-profiler.git', require: false # used for caching, optional -# redis-rack-cache is missing a sane expiry policy, it hogs redis -# https://github.com/jodosha/redis-store/pull/183 -gem 'redis-rack-cache', git: 'https://github.com/SamSaffron/redis-rack-cache.git', require: false -gem 'rack-cache', require: false gem 'rack-cors', require: false gem 'unicorn', require: false gem 'puma', require: false diff --git a/Gemfile.lock b/Gemfile.lock index c48647492cd..c27c426bfdb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -54,14 +54,6 @@ GIT redis thin -GIT - remote: https://github.com/SamSaffron/redis-rack-cache.git - revision: 379ef30e31d4e185cb1d7f8badca0cc06403eba2 - specs: - redis-rack-cache (1.2.1) - rack-cache (~> 1.2) - redis-store (~> 1.1.0) - GIT remote: https://github.com/SamSaffron/sprockets.git revision: bacf2ec4d4d10cd8d1ab25a6360740314c512237 @@ -526,7 +518,6 @@ DEPENDENCIES pry-rails puma qunit-rails - rack-cache rack-cors rack-mini-profiler! rails (= 3.2.12) @@ -536,7 +527,6 @@ DEPENDENCIES rb-inotify (~> 0.9) redcarpet redis - redis-rack-cache! redis-rails rest-client rinku diff --git a/Gemfile_rails4.lock b/Gemfile_rails4.lock index a0d4531c615..62abe0984b9 100644 --- a/Gemfile_rails4.lock +++ b/Gemfile_rails4.lock @@ -23,7 +23,7 @@ GIT GIT remote: git://github.com/rails/rails.git - revision: cfd9186e34a25a29f7cd2018e91548f5d1be22af + revision: 0785008a64f4af8d09379683303d49d160cd444d branch: 4-0-stable specs: actionmailer (4.0.0) @@ -111,14 +111,6 @@ GIT redis thin -GIT - remote: https://github.com/SamSaffron/redis-rack-cache.git - revision: 379ef30e31d4e185cb1d7f8badca0cc06403eba2 - specs: - redis-rack-cache (1.2.1) - rack-cache (~> 1.2) - redis-store (~> 1.1.0) - GIT remote: https://github.com/callahad/omniauth-browserid.git revision: af62d667626c1622de6fe13b60849c3640765ab1 @@ -281,7 +273,7 @@ GEM mocha (0.14.0) metaclass (~> 0.0.1) mock_redis (0.9.0) - multi_json (1.8.1) + multi_json (1.8.2) multipart-post (1.2.0) mustache (0.99.4) net-scp (1.1.2) @@ -340,8 +332,6 @@ GEM qunit-rails (0.0.4) railties (>= 3.2.3) rack (1.5.2) - rack-cache (1.2) - rack (>= 0.4) rack-cors (0.2.8) rack rack-openid (1.3.1) @@ -531,7 +521,6 @@ DEPENDENCIES pry-rails puma qunit-rails - rack-cache rack-cors rack-mini-profiler! rails! @@ -542,7 +531,6 @@ DEPENDENCIES rb-inotify (~> 0.9) redcarpet redis - redis-rack-cache! redis-rails! rest-client rinku diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1223f00a031..3715481ce17 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -155,35 +155,15 @@ class ApplicationController < ActionController::Base end def can_cache_content? - # Don't cache unless we're in production mode - return false unless Rails.env.production? || Rails.env == "profile" - - # Don't cache logged in users - return false if current_user.present? - - true + !current_user.present? end # Our custom cache method def discourse_expires_in(time_length) return unless can_cache_content? - expires_in time_length, public: true + Middleware::AnonymousCache.anon_cache(request.env, 1.minute) end - # Helper method - if no logged in user (anonymous), use Rails' conditional GET - # support. Should be very fast behind a cache. - def anonymous_etag(*args) - if can_cache_content? - yield if stale?(*args) - - # Add a one minute expiry - expires_in 1.minute, public: true - else - yield - end - end - - def fetch_user_from_params username_lower = params[:username].downcase username_lower.gsub!(/\.json$/, '') diff --git a/app/controllers/list_controller.rb b/app/controllers/list_controller.rb index d9b32ed8656..dc3e329a707 100644 --- a/app/controllers/list_controller.rb +++ b/app/controllers/list_controller.rb @@ -22,14 +22,14 @@ class ListController < ApplicationController [:latest, :hot].each do |filter| define_method("#{filter}_feed") do - anonymous_etag(@category) do - @title = "#{filter.capitalize} Topics" - @link = "#{Discourse.base_url}/#{filter}" - @description = I18n.t("rss_description.#{filter}") - @atom_link = "#{Discourse.base_url}/#{filter}.rss" - @topic_list = TopicQuery.new(current_user).public_send("list_#{filter}") - render 'list', formats: [:rss] - end + discourse_expires_in 1.minute + + @title = "#{filter.capitalize} Topics" + @link = "#{Discourse.base_url}/#{filter}" + @description = I18n.t("rss_description.#{filter}") + @atom_link = "#{Discourse.base_url}/#{filter}.rss" + @topic_list = TopicQuery.new(current_user).public_send("list_#{filter}") + render 'list', formats: [:rss] end end @@ -99,14 +99,14 @@ class ListController < ApplicationController guardian.ensure_can_see!(@category) - anonymous_etag(@category) do - @title = @category.name - @link = "#{Discourse.base_url}/category/#{@category.slug}" - @description = "#{I18n.t('topics_in_category', category: @category.name)} #{@category.description}" - @atom_link = "#{Discourse.base_url}/category/#{@category.slug}.rss" - @topic_list = TopicQuery.new.list_new_in_category(@category) - render 'list', formats: [:rss] - end + discourse_expires_in 1.minute + + @title = @category.name + @link = "#{Discourse.base_url}/category/#{@category.slug}" + @description = "#{I18n.t('topics_in_category', category: @category.name)} #{@category.description}" + @atom_link = "#{Discourse.base_url}/category/#{@category.slug}.rss" + @topic_list = TopicQuery.new.list_new_in_category(@category) + render 'list', formats: [:rss] end def popular_redirect diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index 9c1068ff868..3a682334e05 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -40,22 +40,22 @@ class TopicsController < ApplicationController return redirect_to(topic.relative_url) end - anonymous_etag(@topic_view.topic) do - redirect_to_correct_topic && return if slugs_do_not_match + discourse_expires_in 1.minute - # render workaround pseudo-static HTML page for old crawlers which ignores