Merge branch 'improve-dashboard-caching' into 'master'

Refactor for cleaner caching in dashboards

See merge request gitlab-org/gitlab-ce!29444
This commit is contained in:
Douglas Barbosa Alexandre 2019-06-13 16:45:36 +00:00
commit 8934ddbb47
5 changed files with 54 additions and 26 deletions

View file

@ -164,7 +164,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController
if Feature.enabled?(:environment_metrics_show_multiple_dashboards, project) if Feature.enabled?(:environment_metrics_show_multiple_dashboards, project)
result = dashboard_finder.find(project, current_user, environment, params[:dashboard]) result = dashboard_finder.find(project, current_user, environment, params[:dashboard])
result[:all_dashboards] = project.repository.metrics_dashboard_paths result[:all_dashboards] = dashboard_finder.find_all_paths(project)
else else
result = dashboard_finder.find(project, current_user, environment) result = dashboard_finder.find(project, current_user, environment)
end end

View file

@ -7,18 +7,19 @@ module Gitlab
module Dashboard module Dashboard
class BaseService < ::BaseService class BaseService < ::BaseService
PROCESSING_ERROR = Gitlab::Metrics::Dashboard::Stages::BaseStage::DashboardProcessingError PROCESSING_ERROR = Gitlab::Metrics::Dashboard::Stages::BaseStage::DashboardProcessingError
NOT_FOUND_ERROR = Gitlab::Template::Finders::RepoTemplateFinder::FileNotFoundError
def get_dashboard def get_dashboard
return error("#{dashboard_path} could not be found.", :not_found) unless path_available?
success(dashboard: process_dashboard) success(dashboard: process_dashboard)
rescue NOT_FOUND_ERROR
error("#{dashboard_path} could not be found.", :not_found)
rescue PROCESSING_ERROR => e rescue PROCESSING_ERROR => e
error(e.message, :unprocessable_entity) error(e.message, :unprocessable_entity)
end end
# Summary of all known dashboards for the service. # Summary of all known dashboards for the service.
# @return [Array<Hash>] ex) [{ path: String, default: Boolean }] # @return [Array<Hash>] ex) [{ path: String, default: Boolean }]
def all_dashboard_paths(_project) def self.all_dashboard_paths(_project)
raise NotImplementedError raise NotImplementedError
end end
@ -38,7 +39,7 @@ module Gitlab
# Returns an un-processed dashboard from the cache. # Returns an un-processed dashboard from the cache.
def raw_dashboard def raw_dashboard
Rails.cache.fetch(cache_key) { get_raw_dashboard } Gitlab::Metrics::Dashboard::Cache.fetch(cache_key) { get_raw_dashboard }
end end
# @return [Hash] an unmodified dashboard # @return [Hash] an unmodified dashboard
@ -56,17 +57,6 @@ module Gitlab
def insert_project_metrics? def insert_project_metrics?
false false
end end
# Checks if dashboard path exists or should be rejected
# as a result of file-changes to the project repository.
# @return [Boolean]
def path_available?
available_paths = Gitlab::Metrics::Dashboard::Finder.find_all_paths(project)
available_paths.any? do |path_params|
path_params[:path] == dashboard_path
end
end
end end
end end
end end

View file

@ -0,0 +1,44 @@
# frozen_string_literal: true
require 'set'
module Gitlab
module Metrics
module Dashboard
class Cache
CACHE_KEYS = 'all_cached_metric_dashboards'
class << self
# Stores a dashboard in the cache, documenting the key
# so the cached can be cleared in bulk at another time.
def fetch(key)
register_key(key)
Rails.cache.fetch(key) { yield }
end
# Resets all dashboard caches, such that all
# dashboard content will be loaded from source on
# subsequent dashboard calls.
def delete_all!
all_keys.each { |key| Rails.cache.delete(key) }
Rails.cache.delete(CACHE_KEYS)
end
private
def register_key(key)
new_keys = all_keys.add(key).to_a.join('|')
Rails.cache.write(CACHE_KEYS, new_keys)
end
def all_keys
Set.new(Rails.cache.read(CACHE_KEYS)&.split('|'))
end
end
end
end
end
end

View file

@ -27,6 +27,8 @@ module Gitlab
# Summary of all known dashboards. Used to populate repo cache. # Summary of all known dashboards. Used to populate repo cache.
# Prefer #find_all_paths. # Prefer #find_all_paths.
def find_all_paths_from_source(project) def find_all_paths_from_source(project)
Gitlab::Metrics::Dashboard::Cache.delete_all!
system_service.all_dashboard_paths(project) system_service.all_dashboard_paths(project)
.+ project_service.all_dashboard_paths(project) .+ project_service.all_dashboard_paths(project)
end end

View file

@ -13,20 +13,12 @@ module Gitlab
def all_dashboard_paths(project) def all_dashboard_paths(project)
file_finder(project) file_finder(project)
.list_files_for(DASHBOARD_ROOT) .list_files_for(DASHBOARD_ROOT)
.map do |filepath| .map { |filepath| { path: filepath, default: false } }
Rails.cache.delete(cache_key(project.id, filepath))
{ path: filepath, default: false }
end
end end
def file_finder(project) def file_finder(project)
Gitlab::Template::Finders::RepoTemplateFinder.new(project, DASHBOARD_ROOT, '.yml') Gitlab::Template::Finders::RepoTemplateFinder.new(project, DASHBOARD_ROOT, '.yml')
end end
def cache_key(id, dashboard_path)
"project_#{id}_metrics_dashboard_#{dashboard_path}"
end
end end
private private
@ -39,7 +31,7 @@ module Gitlab
end end
def cache_key def cache_key
self.class.cache_key(project.id, dashboard_path) "project_#{project.id}_metrics_dashboard_#{dashboard_path}"
end end
end end
end end