summaryrefslogtreecommitdiff
path: root/app/services
diff options
context:
space:
mode:
authorYorick Peterse <yorickpeterse@gmail.com>2017-11-15 15:47:10 +0100
committerYorick Peterse <yorickpeterse@gmail.com>2017-11-16 14:59:38 +0100
commit3e561736b2eb4866b75c57c01769586f058a2f8d (patch)
tree6e136d37d558b14bfbc2505f8b8f564fa96eab6f /app/services
parent81e94ce1761b48b73be2a8d71938dfe934921e35 (diff)
downloadgitlab-ce-3e561736b2eb4866b75c57c01769586f058a2f8d.tar.gz
Cache the number of user SSH keyscache-user-keys-count
By caching the number of personal SSH keys we reduce the number of queries necessary on pages such as ProjectsController#show (which can end up querying this data multiple times). The cache is refreshed/flushed whenever an SSH key is added, removed, or when a user is removed.
Diffstat (limited to 'app/services')
-rw-r--r--app/services/base_count_service.rb34
-rw-r--r--app/services/projects/count_service.rb25
-rw-r--r--app/services/projects/forks_count_service.rb2
-rw-r--r--app/services/projects/open_issues_count_service.rb2
-rw-r--r--app/services/projects/open_merge_requests_count_service.rb2
-rw-r--r--app/services/users/keys_count_service.rb27
6 files changed, 65 insertions, 27 deletions
diff --git a/app/services/base_count_service.rb b/app/services/base_count_service.rb
new file mode 100644
index 00000000000..99cc9a196e6
--- /dev/null
+++ b/app/services/base_count_service.rb
@@ -0,0 +1,34 @@
+# Base class for services that count a single resource such as the number of
+# issues for a project.
+class BaseCountService
+ def relation_for_count
+ raise(
+ NotImplementedError,
+ '"relation_for_count" must be implemented and return an ActiveRecord::Relation'
+ )
+ end
+
+ def count
+ Rails.cache.fetch(cache_key, raw: raw?) { uncached_count }.to_i
+ end
+
+ def refresh_cache
+ Rails.cache.write(cache_key, uncached_count, raw: raw?)
+ end
+
+ def uncached_count
+ relation_for_count.count
+ end
+
+ def delete_cache
+ Rails.cache.delete(cache_key)
+ end
+
+ def raw?
+ false
+ end
+
+ def cache_key
+ raise NotImplementedError, 'cache_key must be implemented and return a String'
+ end
+end
diff --git a/app/services/projects/count_service.rb b/app/services/projects/count_service.rb
index aa034315280..7e575b2d6f3 100644
--- a/app/services/projects/count_service.rb
+++ b/app/services/projects/count_service.rb
@@ -1,7 +1,7 @@
module Projects
# Base class for the various service classes that count project data (e.g.
# issues or forks).
- class CountService
+ class CountService < BaseCountService
# The version of the cache format. This should be bumped whenever the
# underlying logic changes. This removes the need for explicitly flushing
# all caches.
@@ -11,29 +11,6 @@ module Projects
@project = project
end
- def relation_for_count
- raise(
- NotImplementedError,
- '"relation_for_count" must be implemented and return an ActiveRecord::Relation'
- )
- end
-
- def count
- Rails.cache.fetch(cache_key) { uncached_count }
- end
-
- def refresh_cache
- Rails.cache.write(cache_key, uncached_count)
- end
-
- def uncached_count
- relation_for_count.count
- end
-
- def delete_cache
- Rails.cache.delete(cache_key)
- end
-
def cache_key_name
raise(
NotImplementedError,
diff --git a/app/services/projects/forks_count_service.rb b/app/services/projects/forks_count_service.rb
index 3a0fa84b868..d9bdf3a8ad7 100644
--- a/app/services/projects/forks_count_service.rb
+++ b/app/services/projects/forks_count_service.rb
@@ -1,6 +1,6 @@
module Projects
# Service class for getting and caching the number of forks of a project.
- class ForksCountService < CountService
+ class ForksCountService < Projects::CountService
def relation_for_count
@project.forks
end
diff --git a/app/services/projects/open_issues_count_service.rb b/app/services/projects/open_issues_count_service.rb
index 3c0d186a73c..25de97325e2 100644
--- a/app/services/projects/open_issues_count_service.rb
+++ b/app/services/projects/open_issues_count_service.rb
@@ -1,7 +1,7 @@
module Projects
# Service class for counting and caching the number of open issues of a
# project.
- class OpenIssuesCountService < CountService
+ class OpenIssuesCountService < Projects::CountService
def relation_for_count
# We don't include confidential issues in this number since this would
# expose the number of confidential issues to non project members.
diff --git a/app/services/projects/open_merge_requests_count_service.rb b/app/services/projects/open_merge_requests_count_service.rb
index 2a90f78b90d..77e6448fd5e 100644
--- a/app/services/projects/open_merge_requests_count_service.rb
+++ b/app/services/projects/open_merge_requests_count_service.rb
@@ -1,7 +1,7 @@
module Projects
# Service class for counting and caching the number of open merge requests of
# a project.
- class OpenMergeRequestsCountService < CountService
+ class OpenMergeRequestsCountService < Projects::CountService
def relation_for_count
@project.merge_requests.opened
end
diff --git a/app/services/users/keys_count_service.rb b/app/services/users/keys_count_service.rb
new file mode 100644
index 00000000000..f82d27eded9
--- /dev/null
+++ b/app/services/users/keys_count_service.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Users
+ # Service class for getting the number of SSH keys that belong to a user.
+ class KeysCountService < BaseCountService
+ attr_reader :user
+
+ # user - The User for which to get the number of SSH keys.
+ def initialize(user)
+ @user = user
+ end
+
+ def relation_for_count
+ user.keys
+ end
+
+ def raw?
+ # Since we're storing simple integers we don't need all of the additional
+ # Marshal data Rails includes by default.
+ true
+ end
+
+ def cache_key
+ "users/key-count-service/#{user.id}"
+ end
+ end
+end