summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorick Peterse <yorickpeterse@gmail.com>2016-10-04 14:09:54 +0200
committerYorick Peterse <yorickpeterse@gmail.com>2016-10-04 18:42:32 +0200
commit03c220ba688a11e9fecc8bb4505d448af9651215 (patch)
tree1e6a989356194120660da38a57ed02804ca79489
parent706737a004b67303f15ccbd1f8630b0d80f481e9 (diff)
downloadgitlab-ce-trending-caching.tar.gz
Refactor TrendingProjectsFinder to support cachingtrending-caching
== Public Projects This finder class now _only_ returns public projects. Previously this finder would also return private and internal projects. Including these projects makes caching data much harder and less efficient. Meanwhile including this data isn't very useful as very few users would be interested in seeing projects they have access to as trending. That is, the feature is more useful when you want to see what _other_ popular projects there are. == Caching The data returned by TrendingProjectsFinder is now cached for a day based on the number of months the data should be restricted to. The cache is not flushed explicitly, instead it's rebuilt whenever it expires. == Timings To measure the impact I changed the finder code to use the last 24 months instead of the last month. I then executed and measured 10 requests to the explore page. On the current "master" branch (commit 88fa5916ffa0aea491cd339272ed7437c3f52dc7) this would take an average of 2.43 seconds. Using the changes of this commit this was reduced to around 1.7 seconds. Fixes gitlab-org/gitlab-ce#22164
-rw-r--r--CHANGELOG1
-rw-r--r--app/controllers/explore/projects_controller.rb2
-rw-r--r--app/finders/trending_projects_finder.rb13
-rw-r--r--spec/finders/trending_projects_finder_spec.rb53
4 files changed, 44 insertions, 25 deletions
diff --git a/CHANGELOG b/CHANGELOG
index a47ec511452..11141b38a0e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -31,6 +31,7 @@ v 8.13.0 (unreleased)
- Take filters in account in issuable counters. !6496
- Use custom Ruby images to test builds (registry.dev.gitlab.org/gitlab/gitlab-build-images:*)
- Append issue template to existing description !6149 (Joseph Frazier)
+ - Trending projects now only show public projects and the list of projects is cached for a day
- Revoke button in Applications Settings underlines on hover.
- Add missing values to linter !6276 (Katarzyna Kobierska Ula Budziszewska)
- Fix Long commit messages overflow viewport in file tree
diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb
index 88a0c18180b..38e5943eb76 100644
--- a/app/controllers/explore/projects_controller.rb
+++ b/app/controllers/explore/projects_controller.rb
@@ -21,7 +21,7 @@ class Explore::ProjectsController < Explore::ApplicationController
end
def trending
- @projects = TrendingProjectsFinder.new.execute(current_user)
+ @projects = TrendingProjectsFinder.new.execute
@projects = filter_projects(@projects)
@projects = @projects.page(params[:page])
diff --git a/app/finders/trending_projects_finder.rb b/app/finders/trending_projects_finder.rb
index 81a12403801..48c98731cbc 100644
--- a/app/finders/trending_projects_finder.rb
+++ b/app/finders/trending_projects_finder.rb
@@ -1,6 +1,11 @@
+# Finder for retrieving public trending projects in a given time range.
class TrendingProjectsFinder
- def execute(current_user, start_date = 1.month.ago)
- projects_for(current_user).trending(start_date)
+ # current_user - The currently logged in User, if any.
+ # last_months - The number of months to limit the trending data to.
+ def execute(months_limit = 1)
+ Rails.cache.fetch(cache_key_for(months_limit), expires_in: 1.day) do
+ Project.public_only.trending(months_limit.months.ago)
+ end
end
private
@@ -8,4 +13,8 @@ class TrendingProjectsFinder
def projects_for(current_user)
ProjectsFinder.new.execute(current_user)
end
+
+ def cache_key_for(months)
+ "trending_projects/#{months}"
+ end
end
diff --git a/spec/finders/trending_projects_finder_spec.rb b/spec/finders/trending_projects_finder_spec.rb
index a49cbfd5160..cfe15b9defa 100644
--- a/spec/finders/trending_projects_finder_spec.rb
+++ b/spec/finders/trending_projects_finder_spec.rb
@@ -1,39 +1,48 @@
require 'spec_helper'
describe TrendingProjectsFinder do
- let(:user) { build(:user) }
+ let(:user) { create(:user) }
+ let(:public_project1) { create(:empty_project, :public) }
+ let(:public_project2) { create(:empty_project, :public) }
+ let(:private_project) { create(:empty_project, :private) }
+ let(:internal_project) { create(:empty_project, :internal) }
+
+ before do
+ 3.times do
+ create(:note_on_commit, project: public_project1)
+ end
- describe '#execute' do
- describe 'without an explicit start date' do
- subject { described_class.new }
+ 2.times do
+ create(:note_on_commit, project: public_project2, created_at: 5.weeks.ago)
+ end
- it 'returns the trending projects' do
- relation = double(:ar_relation)
+ create(:note_on_commit, project: private_project)
+ create(:note_on_commit, project: internal_project)
+ end
- allow(subject).to receive(:projects_for)
- .with(user)
- .and_return(relation)
+ describe '#execute', caching: true do
+ context 'without an explicit time range' do
+ it 'returns public trending projects' do
+ projects = described_class.new.execute
- allow(relation).to receive(:trending)
- .with(an_instance_of(ActiveSupport::TimeWithZone))
+ expect(projects).to eq([public_project1])
end
end
- describe 'with an explicit start date' do
- let(:date) { 2.months.ago }
+ context 'with an explicit time range' do
+ it 'returns public trending projects' do
+ projects = described_class.new.execute(2)
- subject { described_class.new }
+ expect(projects).to eq([public_project1, public_project2])
+ end
+ end
- it 'returns the trending projects' do
- relation = double(:ar_relation)
+ it 'caches the list of projects' do
+ projects = described_class.new
- allow(subject).to receive(:projects_for)
- .with(user)
- .and_return(relation)
+ expect(Project).to receive(:trending).once
- allow(relation).to receive(:trending)
- .with(date)
- end
+ 2.times { projects.execute }
end
end
end