2019-06-21 10:20:00 -04:00
# frozen_string_literal: true
module Gitlab
module Graphql
module CallsGitaly
class Instrumentation
# Check if any `calls_gitaly: true` declarations need to be added
2019-07-02 01:32:44 -04:00
# Do nothing if a constant complexity was provided
2019-06-21 10:20:00 -04:00
def instrument ( _type , field )
type_object = field . metadata [ :type_class ]
2019-07-02 01:32:44 -04:00
return field unless type_object . respond_to? ( :calls_gitaly? )
return field if type_object . constant_complexity? || type_object . calls_gitaly?
2019-06-21 10:20:00 -04:00
old_resolver_proc = field . resolve_proc
2019-06-26 06:42:25 -04:00
gitaly_wrapped_resolve = - > ( typed_object , args , ctx ) do
2019-06-21 10:20:00 -04:00
previous_gitaly_call_count = Gitlab :: GitalyClient . get_request_count
2019-06-26 06:42:25 -04:00
result = old_resolver_proc . call ( typed_object , args , ctx )
2019-06-21 10:20:00 -04:00
current_gitaly_call_count = Gitlab :: GitalyClient . get_request_count
2019-06-27 21:24:47 -04:00
calls_gitaly_check ( type_object , current_gitaly_call_count - previous_gitaly_call_count )
2019-06-26 06:42:25 -04:00
result
end
field . redefine do
resolve ( gitaly_wrapped_resolve )
2019-06-21 10:20:00 -04:00
end
end
2019-06-27 21:24:47 -04:00
def calls_gitaly_check ( type_object , calls )
return if calls < 1
# Will inform you if there needs to be `calls_gitaly: true` as a kwarg in the field declaration
# if there is at least 1 Gitaly call involved with the field resolution.
2019-07-02 01:32:44 -04:00
error = RuntimeError . new ( " Gitaly is called for field ' #{ type_object . name } ' on #{ type_object . owner . try ( :name ) } - please either specify a constant complexity or add `calls_gitaly: true` to the field declaration " )
2019-06-27 21:24:47 -04:00
Gitlab :: Sentry . track_exception ( error )
end
2019-06-21 10:20:00 -04:00
end
end
end
end