Skip to content

Commit

Permalink
speed up startup (avoid loading some gems on startup)
Browse files Browse the repository at this point in the history
correct group permission leaks
add Discourse.cache for richer caching support
  • Loading branch information
SamSaffron committed May 13, 2013
1 parent 9b33e82 commit b6bf95e
Show file tree
Hide file tree
Showing 21 changed files with 250 additions and 66 deletions.
29 changes: 15 additions & 14 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ gem 'sinatra', require: nil
gem 'slim' # required for sidekiq-web
gem 'therubyracer', require: 'v8'
gem 'thin'
gem 'diffy'
gem 'diffy', require: false

# Gem that enables support for plugins. It is required.
gem 'discourse_plugin', path: 'vendor/gems/discourse_plugin'
Expand All @@ -86,26 +86,27 @@ group :assets do
end

group :test do
gem 'fakeweb', '~> 1.3.0'
gem 'minitest'
gem 'fakeweb', '~> 1.3.0', require: false
gem 'minitest', require: false
end

group :test, :development do
gem 'jshint_on_rails'
gem 'guard-jshint-on-rails'
gem 'certified'
gem 'fabrication'
gem 'guard-jasmine'
gem 'guard-rspec'
gem 'guard-spork'
gem 'listen', require: false
gem 'guard-jshint-on-rails', require: false
gem 'certified', require: false
gem 'fabrication', require: false
gem 'guard-jasmine', require: false
gem 'guard-rspec', require: false
gem 'guard-spork', require: false
gem 'jasminerice'
gem 'mocha', require: false
gem 'rb-fsevent'
gem 'rb-inotify', '~> 0.9', require: RUBY_PLATFORM.include?('linux') && 'rb-inotify'
gem 'rspec-rails'
gem 'shoulda'
gem 'rb-fsevent', require: false
gem 'rb-inotify', '~> 0.9', require: false
gem 'rspec-rails', require: false
gem 'shoulda', require: false
gem 'simplecov', require: false
gem 'terminal-notifier-guard', require: RUBY_PLATFORM.include?('darwin') && 'terminal-notifier-guard'
gem 'terminal-notifier-guard', require: false
end

group :development do
Expand Down
1 change: 1 addition & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ DEPENDENCIES
jquery-rails
jshint_on_rails
librarian (>= 0.0.25)
listen
lru_redux
message_bus!
minitest
Expand Down
4 changes: 4 additions & 0 deletions Guardfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
require 'rb-inotify' if RUBY_PLATFORM.include?('linux')
require 'terminal-notifier-guard' if RUBY_PLATFORM.include?('darwin')

phantom_path = File.expand_path('~/phantomjs/bin/phantomjs')
phantom_path = nil unless File.exists?(phantom_path)

Expand Down Expand Up @@ -27,6 +30,7 @@ guard 'jshint-on-rails', config_path: 'config/jshint.yml' do
end

unless ENV["USING_AUTOSPEC"]

puts "Sam strongly recommends you Run: `bundle exec rake autospec` in favor of guard for specs, set USING_AUTOSPEC in .rvmrc to disable from Guard"
guard :spork, wait: 120 do
watch('config/application.rb')
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def preload_json
guardian.current_user.sync_notification_channel_position
end

store_preloaded("site", Site.cached_json)
store_preloaded("site", Site.cached_json(current_user))

if current_user.present?
store_preloaded("currentUser", MultiJson.dump(CurrentUserSerializer.new(current_user, root: false)))
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/search_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
class SearchController < ApplicationController

def query
search_result = Search.query(params[:term], current_user, params[:type_filter], SiteSetting.min_search_term_length)
search_result = Search.query(params[:term], guardian, params[:type_filter], SiteSetting.min_search_term_length)
render_json_dump(search_result.as_json)
end

Expand Down
10 changes: 10 additions & 0 deletions app/models/category.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ class Category < ActiveRecord::Base

scope :latest, ->{ order('topic_count desc') }

scope :secured, lambda { |guardian|
ids = nil
ids = guardian.secure_category_ids if guardian
if ids.present?
where("categories.secure ='f' or categories.id = :cats ", cats: ids)
else
where("categories.secure ='f'")
end
}

delegate :post_template, to: 'self.class'

# Internal: Update category stats: # of topics in past year, month, week for
Expand Down
15 changes: 5 additions & 10 deletions app/models/category_list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,14 @@ class CategoryList

attr_accessor :categories, :topic_users, :uncategorized

def initialize(current_user)
def initialize(guardian)
@categories = Category
.includes(featured_topics: [:category])
.includes(:featured_users)
.where('topics.visible' => true)
.secured(guardian)
.order('categories.topics_week desc, categories.topics_month desc, categories.topics_year desc')

allowed_ids = current_user ? current_user.secure_category_ids : nil
if allowed_ids.present?
@categories = @categories.where("categories.secure = 'f' OR categories.id in (?)", allowed_ids)
else
@categories = @categories.where("categories.secure = 'f'")
end

@categories = @categories.to_a

Expand Down Expand Up @@ -56,7 +51,7 @@ def initialize(current_user)
@categories.insert(insert_at || @categories.size, uncategorized)
end

unless Guardian.new(current_user).can_create?(Category)
unless guardian.can_create?(Category)
# Remove categories with no featured topics unless we have the ability to edit one
@categories.delete_if { |c| c.featured_topics.blank? }
else
Expand All @@ -69,15 +64,15 @@ def initialize(current_user)
end

# Get forum topic user records if appropriate
if current_user.present?
if guardian.current_user
topics = []
@categories.each { |c| topics << c.featured_topics }
topics << @uncategorized

topics.flatten! if topics.present?
topics.compact! if topics.present?

topic_lookup = TopicUser.lookup_for(current_user, topics)
topic_lookup = TopicUser.lookup_for(guardian.current_user, topics)

# Attach some data for serialization to each topic
topics.each { |ft| ft.user_data = topic_lookup[ft.id] }
Expand Down
23 changes: 16 additions & 7 deletions app/models/site.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
class Site
include ActiveModel::Serialization

def initialize(guardian)
@guardian = guardian
end

def site_setting
SiteSetting
end
Expand All @@ -22,27 +26,32 @@ def trust_levels
end

def categories
Category.latest.includes(:topic_only_relative_url)
Category
.secured(@guardian)
.latest
.includes(:topic_only_relative_url)
end

def archetypes
Archetype.list.reject { |t| t.id == Archetype.private_message }
end

def self.cache_key
"site_json"
def cache_key
k ="site_json_cats_"
k << @guardian.secure_category_ids.join("_") if @guardian
end

def self.cached_json
def self.cached_json(guardian)
# Sam: bumping this way down, SiteSerializer will serialize post actions as well,
# On my local this was not being flushed as post actions types changed, it turn this
# broke local.
Rails.cache.fetch(Site.cache_key, expires_in: 1.minute) do
MultiJson.dump(SiteSerializer.new(Site.new, root: false))
site = Site.new(guardian)
Discourse.cache.fetch(site.cache_key, family: "site", expires_in: 1.minute) do
MultiJson.dump(SiteSerializer.new(site, root: false))
end
end

def self.invalidate_cache
Rails.cache.delete(Site.cache_key)
Discourse.cache.delete_by_family("site")
end
end
3 changes: 2 additions & 1 deletion app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -565,9 +565,10 @@ def update_topic_reply_count

def secure_category_ids
cats = self.staff? ? Category.select(:id).where(secure: true) : secure_categories.select('categories.id')
cats.map{|c| c.id}
cats.map{|c| c.id}.sort
end


protected

def cook
Expand Down
2 changes: 1 addition & 1 deletion app/serializers/site_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class SiteSerializer < ApplicationSerializer
:notification_types,
:post_types

has_many :categories, embed: :objects
has_many :categories, serializer: BasicCategorySerializer, embed: :objects
has_many :post_action_types, embed: :objects
has_many :trust_levels, embed: :objects
has_many :archetypes, embed: :objects, serializer: ArchetypeSerializer
Expand Down
55 changes: 55 additions & 0 deletions lib/cache.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Standard Rails.cache is lacking support for this interface, possibly yank all in from redis:cache and start using this instead
#

class Cache
def initialize(redis=nil)
@redis = redis
end

def redis
@redis || $redis
end

def fetch(key, options={})
result = redis.get key
if result.nil?
if expiry = options[:expires_in]
if block_given?
result = yield
redis.setex(key, expiry, result)
end
else
if block_given?
result = yield
redis.set(key, result)
end
end
end

if family = family_key(options[:family])
redis.sadd(family, key)
end

result
end

def delete(key)
redis.del(key)
end

def delete_by_family(key)
k = family_key(key)
redis.smembers(k).each do |member|
delete(member)
end
redis.del(k)
end

private

def family_key(name)
if name
"FAMILY_#{name}"
end
end
end
1 change: 1 addition & 0 deletions lib/diff_engine.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require 'diffy'
# This class is used to generate diffs, it will be consumed by the UI on
# on the client the displays diffs.
#
Expand Down
7 changes: 6 additions & 1 deletion lib/discourse.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require 'cache'

module Discourse

# When they try to do something they should be logged in for
Expand All @@ -12,6 +14,9 @@ class InvalidAccess < Exception; end
# When something they want is not found
class NotFound < Exception; end

def self.cache
@cache ||= Cache.new
end

# Get the current base URL for the current site
def self.current_hostname
Expand All @@ -20,7 +25,7 @@ def self.current_hostname

def self.base_uri default_value=""
if !ActionController::Base.config.relative_url_root.blank?
return ActionController::Base.config.relative_url_root
return ActionController::Base.config.relative_url_root
else
return default_value
end
Expand Down
4 changes: 2 additions & 2 deletions lib/guardian.rb
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ def can_see_category?(category)
return true unless category.secure
return false unless @user

@user.secure_category_ids.include?(category.id)
secure_category_ids.include?(category.id)
end

def can_vote?(post, opts={})
Expand Down Expand Up @@ -405,6 +405,6 @@ def post_can_act?(post, action_key, opts={})
end

def secure_category_ids
@user ? @user.secure_category_ids : []
@secure_category_ids ||= @user ? @user.secure_category_ids : []
end
end
Loading

0 comments on commit b6bf95e

Please sign in to comment.