Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/controllers/graphql_controller.rb')
-rw-r--r--app/controllers/graphql_controller.rb60
1 files changed, 58 insertions, 2 deletions
diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb
index ff4fce9ad1e..3d3b7f31dfd 100644
--- a/app/controllers/graphql_controller.rb
+++ b/app/controllers/graphql_controller.rb
@@ -12,6 +12,9 @@ class GraphqlController < ApplicationController
# Max size of the query text in characters
MAX_QUERY_SIZE = 10_000
+ # The query string of a standard IntrospectionQuery, used to compare incoming requests for caching
+ CACHED_INTROSPECTION_QUERY_STRING = CachedIntrospectionQuery.query_string
+
# If a user is using their session to access GraphQL, we need to have session
# storage, since the admin-mode check is session wide.
# We can't enable this for anonymous users because that would cause users using
@@ -32,6 +35,7 @@ class GraphqlController < ApplicationController
before_action :set_user_last_activity
before_action :track_vs_code_usage
before_action :track_jetbrains_usage
+ before_action :track_jetbrains_bundled_usage
before_action :track_gitlab_cli_usage
before_action :disable_query_limiting
before_action :limit_query_size
@@ -54,7 +58,12 @@ class GraphqlController < ApplicationController
urgency :low, [:execute]
def execute
- result = multiplex? ? execute_multiplex : execute_query
+ result = if Feature.enabled?(:cache_introspection_query) && params[:operationName] == 'IntrospectionQuery'
+ execute_introspection_query
+ else
+ multiplex? ? execute_multiplex : execute_query
+ end
+
render json: result
end
@@ -80,7 +89,7 @@ class GraphqlController < ApplicationController
log_exception(exception)
response.headers.merge!(exception.headers)
- render_error(exception.message, status: :too_many_requests)
+ render_error(exception.message, status: :service_unavailable)
end
rescue_from Gitlab::Graphql::Variables::Invalid do |exception|
@@ -169,6 +178,11 @@ class GraphqlController < ApplicationController
.track_api_request_when_trackable(user_agent: request.user_agent, user: current_user)
end
+ def track_jetbrains_bundled_usage
+ Gitlab::UsageDataCounters::JetBrainsBundledPluginActivityUniqueCounter
+ .track_api_request_when_trackable(user_agent: request.user_agent, user: current_user)
+ end
+
def track_gitlab_cli_usage
Gitlab::UsageDataCounters::GitLabCliActivityUniqueCounter
.track_api_request_when_trackable(user_agent: request.user_agent, user: current_user)
@@ -259,4 +273,46 @@ class GraphqlController < ApplicationController
def logs
RequestStore.store[:graphql_logs].to_a
end
+
+ def execute_introspection_query
+ if introspection_query_can_use_cache?
+ Gitlab::AppLogger.info(message: "IntrospectionQueryCache hit")
+ log_introspection_query_cache_details(true)
+
+ # Context for caching: https://gitlab.com/gitlab-org/gitlab/-/issues/409448
+ Rails.cache.fetch(
+ introspection_query_cache_key,
+ expires_in: 1.day) do
+ execute_query.to_json
+ end
+ else
+ Gitlab::AppLogger.info(message: "IntrospectionQueryCache miss")
+ log_introspection_query_cache_details(false)
+
+ execute_query
+ end
+ end
+
+ def introspection_query_can_use_cache?
+ graphql_query = GraphQL::Query.new(GitlabSchema, query: query, variables: build_variables(params[:variables]))
+
+ CACHED_INTROSPECTION_QUERY_STRING == graphql_query.query_string.squish
+ end
+
+ def introspection_query_cache_key
+ # We use context[:remove_deprecated] here as an introspection query result can differ based on the
+ # visibility of schema items. Visibility can be affected by the remove_deprecated param. For more context, see:
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/409448#note_1377558096
+ ['introspection-query-cache', Gitlab.revision, context[:remove_deprecated]]
+ end
+
+ def log_introspection_query_cache_details(can_use_introspection_query_cache)
+ Gitlab::AppLogger.info(
+ message: "IntrospectionQueryCache",
+ can_use_introspection_query_cache: can_use_introspection_query_cache.to_s,
+ query: query,
+ variables: build_variables(params[:variables]).to_s,
+ introspection_query_cache_key: introspection_query_cache_key.to_s
+ )
+ end
end