introduce rack:cache as a default, so users don't need to configure apache or nginx

under rack cache we are able to serve 620reqs a second per thin (on my machine) before it 12 (on my machine)

reorganised so mini profilers can be cleanly disabled from config file

added caching for categories index

move production.rb to production.sample.rb
This commit is contained in:
Sam 2013-04-11 16:24:08 +10:00
parent edd25e01a8
commit 850b042cab
16 changed files with 100 additions and 64 deletions

View File

@ -112,8 +112,12 @@ gem 'fast_blank' #, github: "SamSaffron/fast_blank"
# IMPORTANT: mini profiler monkey patches, so it better be required last # IMPORTANT: mini profiler monkey patches, so it better be required last
# If you want to amend mini profiler to do the monkey patches in the railstie # If you want to amend mini profiler to do the monkey patches in the railstie
# we are open to it. # we are open to it. by deferring require to the initializer we can configure disourse installs without it
gem 'rack-mini-profiler' #, git: 'git://github.com/SamSaffron/MiniProfiler' gem 'rack-mini-profiler', require: false # require: false #, git: 'git://github.com/SamSaffron/MiniProfiler'
# used for caching, optional
gem 'redis-rack-cache', require: false
gem 'rack-cache', require: false
# perftools only works on 1.9 atm # perftools only works on 1.9 atm
group :profile do group :profile do

View File

@ -319,7 +319,7 @@ GEM
rack (1.4.5) rack (1.4.5)
rack-cache (1.2) rack-cache (1.2)
rack (>= 0.4) rack (>= 0.4)
rack-mini-profiler (0.1.25) rack-mini-profiler (0.1.26)
rack (>= 1.1.3) rack (>= 1.1.3)
rack-openid (1.3.1) rack-openid (1.3.1)
rack (>= 1.1.0) rack (>= 1.1.0)
@ -367,6 +367,9 @@ GEM
redis-rack (1.4.2) redis-rack (1.4.2)
rack (~> 1.4.1) rack (~> 1.4.1)
redis-store (~> 1.1.0) redis-store (~> 1.1.0)
redis-rack-cache (1.2.1)
rack-cache (~> 1.2)
redis-store (~> 1.1.0)
redis-rails (3.2.3) redis-rails (3.2.3)
redis-actionpack (~> 3.2.3) redis-actionpack (~> 3.2.3)
redis-activesupport (~> 3.2.3) redis-activesupport (~> 3.2.3)
@ -514,6 +517,7 @@ DEPENDENCIES
openid-redis-store openid-redis-store
pg pg
pry-rails pry-rails
rack-cache
rack-mini-profiler rack-mini-profiler
rails rails
rails_multisite! rails_multisite!
@ -522,6 +526,7 @@ DEPENDENCIES
rb-inotify (~> 0.8.8) rb-inotify (~> 0.8.8)
redcarpet redcarpet
redis redis
redis-rack-cache
redis-rails redis-rails
rest-client rest-client
rinku rinku

View File

@ -140,7 +140,7 @@ class ApplicationController < ActionController::Base
def can_cache_content? def can_cache_content?
# Don't cache unless we're in production mode # Don't cache unless we're in production mode
return false unless Rails.env.production? return false unless Rails.env.production? || Rails.env == "profile"
# Don't cache logged in users # Don't cache logged in users
return false if current_user.present? return false if current_user.present?

View File

@ -6,6 +6,7 @@ class CategoriesController < ApplicationController
def index def index
list = CategoryList.new(current_user) list = CategoryList.new(current_user)
discourse_expires_in 1.minute
render_serialized(list, CategoryListSerializer) render_serialized(list, CategoryListSerializer)
end end

View File

@ -16,21 +16,11 @@
<%# load the selected locale before any other scripts %> <%# load the selected locale before any other scripts %>
<%= javascript_include_tag "locales/#{I18n.locale}" %> <%= javascript_include_tag "locales/#{I18n.locale}" %>
<%= javascript_include_tag "application" %>
<%- if mini_profiler_enabled? %> <%= javascript_include_tag "admin"%>
<%- Rack::MiniProfiler.step "application" do %> <%- if admin? %>
<%= javascript_include_tag "application" %> <%= javascript_include_tag "admin"%>
<%-end%> <%- end %>
<%- Rack::MiniProfiler.step "admin" do %>
<%= javascript_include_tag "admin"%>
<%-end%>
<%- else %>
<%= javascript_include_tag "application" %>
<%- if admin? %>
<%= javascript_include_tag "admin"%>
<%- end %>
<%- end%>
<script> <script>
Discourse.CDN = '<%= Rails.configuration.action_controller.asset_host %>'; Discourse.CDN = '<%= Rails.configuration.action_controller.asset_host %>';

View File

@ -1,12 +1,8 @@
<%- unless SiteCustomization.override_default_style(session[:preview_style]) %> <%- unless SiteCustomization.override_default_style(session[:preview_style]) %>
<%=stylesheet_link_tag "application"%> <%=stylesheet_link_tag "application"%>
<%- end %> <%- end %>
<%- if mini_profiler_enabled? %> <%- if admin? %>
<%- Rack::MiniProfiler.step "stylsheet" do%> <%= stylesheet_link_tag "admin"%>
<%= stylesheet_link_tag "admin"%> <%-end%>
<%-end%> <%=SiteCustomization.custom_stylesheet(session[:preview_style])%>
<%- elsif admin? %>
<%= stylesheet_link_tag "admin"%>
<%-end%>
<%=SiteCustomization.custom_stylesheet(session[:preview_style])%>

View File

@ -8,21 +8,9 @@
<meta content="" name="author"> <meta content="" name="author">
<link rel="icon" type="image/png" href=<%=SiteSetting.favicon_url%>> <link rel="icon" type="image/png" href=<%=SiteSetting.favicon_url%>>
<%- if mini_profiler_enabled? %> <%=stylesheet_link_tag "application"%>
<%- Rack::MiniProfiler.step "stylsheet" do%> <%- if current_user.try(:admin) %>
<%=stylesheet_link_tag "application"%> <%= stylesheet_link_tag "admin"%>
<%- end %>
<%- if current_user.try(:admin) %>
<%- Rack::MiniProfiler.step "stylsheet" do%>
<%= stylesheet_link_tag "admin"%>
<%-end%>
<%- end %>
<%- else %>
<%=stylesheet_link_tag "application"%>
<%- if current_user.try(:admin) %>
<%= stylesheet_link_tag "admin"%>
<%- end %>
<%- end %> <%- end %>
<%=csrf_meta_tags%> <%=csrf_meta_tags%>

View File

@ -92,9 +92,15 @@ module Discourse
# Use redis for our cache # Use redis for our cache
config.cache_store = DiscourseRedis.new_redis_store config.cache_store = DiscourseRedis.new_redis_store
# Test with rack::cache disabled. Nginx does this for us # we configure rack cache on demand in an initializer
# our setup does not use rack cache and instead defers to nginx
config.action_dispatch.rack_cache = nil config.action_dispatch.rack_cache = nil
# ember stuff only used for asset precompliation, production variant plays up
config.ember.variant = :development
config.ember.ember_location = "#{Rails.root}/app/assets/javascripts/external_production/ember.js"
config.ember.handlebars_location = "#{Rails.root}/app/assets/javascripts/external/handlebars-1.0.rc.3.js"
# So open id logs somewhere sane # So open id logs somewhere sane
config.after_initialize do config.after_initialize do
OpenID::Util.logger = Rails.logger OpenID::Util.logger = Rails.logger

View File

@ -29,15 +29,15 @@ Discourse::Application.configure do
config.watchable_dirs['lib'] = [:rb] config.watchable_dirs['lib'] = [:rb]
config.sass.debug_info = false config.sass.debug_info = false
config.ember.variant = :development
config.ember.handlebars_location = "#{Rails.root}/app/assets/javascripts/external/handlebars-1.0.rc.3.js"
config.ember.ember_location = "#{Rails.root}/app/assets/javascripts/external/ember.js"
config.handlebars.precompile = false config.handlebars.precompile = false
# we recommend you use mailcatcher https://github.com/sj26/mailcatcher
config.action_mailer.delivery_method = :smtp config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = { address: "localhost", port: 1025 } config.action_mailer.smtp_settings = { address: "localhost", port: 1025 }
config.action_mailer.raise_delivery_errors = true config.action_mailer.raise_delivery_errors = true
BetterErrors::Middleware.allow_ip! ENV['TRUSTED_IP'] if ENV['TRUSTED_IP'] BetterErrors::Middleware.allow_ip! ENV['TRUSTED_IP'] if ENV['TRUSTED_IP']
config.enable_mini_profiler = true
end end

View File

@ -27,17 +27,32 @@ Discourse::Application.configure do
# the I18n.default_locale when a translation can not be found) # the I18n.default_locale when a translation can not be found)
config.i18n.fallbacks = true config.i18n.fallbacks = true
# you may use other configuration here for mail eg: sendgrid
# config.action_mailer.delivery_method = :smtp
# config.action_mailer.smtp_settings = {
# :address => "smtp.sendgrid.net",
# :port => 587,
# :domain => 'YOUR DOMAIN',
# :user_name => 'YOUR_USER',
# :password => 'YOUR_PASSWORD',
# :authentication => 'plain',
# :enable_starttls_auto => true }
config.action_mailer.delivery_method = :sendmail config.action_mailer.delivery_method = :sendmail
config.action_mailer.sendmail_settings = {arguments: '-i'} config.action_mailer.sendmail_settings = {arguments: '-i'}
# Send deprecation notices to registered listeners # Send deprecation notices to registered listeners
config.active_support.deprecation = :notify config.active_support.deprecation = :notify
# I dunno ... perhaps the built-in minifier is using closure # this will cause all handlebars templates to be pre-compiles, making your page faster
# regardless it is blowing up
config.ember.variant = :development
config.ember.ember_location = "#{Rails.root}/app/assets/javascripts/external_production/ember.js"
config.ember.handlebars_location = "#{Rails.root}/app/assets/javascripts/external/handlebars-1.0.rc.3.js"
config.handlebars.precompile = true config.handlebars.precompile = true
# this setting enables rack_cache so it caches various requests in redis
config.enable_rack_cache = true
# allows admins to use mini profiler
config.enable_mini_profiler = true
end end

View File

@ -33,13 +33,15 @@ Discourse::Application.configure do
# Send deprecation notices to registered listeners # Send deprecation notices to registered listeners
config.active_support.deprecation = :notify config.active_support.deprecation = :notify
# I dunno ... perhaps the built-in minifier is using closure # precompile handlebar assets
# regardless it is blowing up
config.ember.variant = :development
config.ember.ember_location = "#{Rails.root}/app/assets/javascripts/external_production/ember.js"
config.ember.handlebars_location = "#{Rails.root}/app/assets/javascripts/external/handlebars-1.0.rc.3.js"
config.handlebars.precompile = true config.handlebars.precompile = true
# config.middleware.use ::Rack::PerftoolsProfiler, default_printer: 'gif' # this setting enable rack_cache so it caches various requests in redis
config.enable_rack_cache = false
# allows users to use mini profiler
config.enable_mini_profiler = false
# for profiling with perftools
# config.middleware.use ::Rack::PerftoolsProfiler, default_printer: 'gif'
end end

View File

@ -1,4 +1,10 @@
# If Mini Profiler is included via gem # If Mini Profiler is included via gem
if Rails.configuration.respond_to?(:enable_mini_profiler) && Rails.configuration.enable_mini_profiler
require 'rack-mini-profiler'
# initialization is skipped so trigger it
Rack::MiniProfilerRails.initialize!(Rails.application)
end
if defined?(Rack::MiniProfiler) if defined?(Rack::MiniProfiler)
# note, we may want to add some extra security here that disables mini profiler in a multi hosted env unless user global admin # note, we may want to add some extra security here that disables mini profiler in a multi hosted env unless user global admin

View File

@ -0,0 +1,11 @@
if Rails.configuration.respond_to?(:enable_rack_cache) && Rails.configuration.enable_rack_cache
require 'rack-cache'
require 'redis-rack-cache'
url = DiscourseRedis.url
Rails.configuration.middleware.insert 0, Rack::Cache,
metastore: "#{url}/metastore",
entitystore: "#{url}/entitystore",
verbose: !Rails.env.production?
end

View File

@ -1,5 +1,11 @@
module CurrentUser module CurrentUser
def self.has_auth_cookie?(env)
request = Rack::Request.new(env)
cookie = request.cookies["_t"]
!cookie.nil? && cookie.length == 32
end
def self.lookup_from_env(env) def self.lookup_from_env(env)
request = Rack::Request.new(env) request = Rack::Request.new(env)
lookup_from_auth_token(request.cookies["_t"]) lookup_from_auth_token(request.cookies["_t"])

View File

@ -11,7 +11,12 @@ class DiscourseRedis
end end
def self.config def self.config
YAML.load(ERB.new(File.new("#{Rails.root}/config/redis.yml").read).result)[Rails.env] @config ||= YAML.load(ERB.new(File.new("#{Rails.root}/config/redis.yml").read).result)[Rails.env]
end
def self.url(config=nil)
config ||= self.config
"redis://#{(':' + config['password'] + '@') if config['password']}#{config['host']}:#{config['port']}/#{config['db']}"
end end
def initialize def initialize
@ -19,6 +24,10 @@ class DiscourseRedis
@redis = DiscourseRedis.raw_connection(@config) @redis = DiscourseRedis.raw_connection(@config)
end end
def url
self.class.url(@config)
end
# prefix the key with the namespace # prefix the key with the namespace
def method_missing(meth, *args, &block) def method_missing(meth, *args, &block)
if @redis.respond_to?(meth) if @redis.respond_to?(meth)
@ -52,8 +61,5 @@ class DiscourseRedis
redis_store redis_store
end end
def url
"redis://#{(':' + @config['password'] + '@') if @config['password']}#{@config['host']}:#{@config['port']}/#{@config['db']}"
end
end end