-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Global analyzers error context? #255
Comments
The goal is to support query analyzers returning errors. Here's the code that's supposed to handle one returned error per analyzer: https://github.com/rmosolgo/graphql-ruby/blob/master/lib/graphql/query.rb#L184-L185 (That is, The intended use case is just what you described: different analyzers can return their own errors to the user. However:
I know it's a bit weird to have an API that expects errors as return values. This is a personal opinion, taken after http://c2.com/cgi/wiki?DontUseExceptionsForFlowControl . I'm open to supporting How does that sound to you? Would any of those improvements work in your case? |
This part:
would be wonderful. Mostly because it separates the notion of a I can get to work on a PR if that works for you.
I think it works as expected and/or designed. Every analyzer is separate and does its own thing. From a usage perspective, this separation of concerns breaks down when you try to do error handling. It's a bit like a linter that would only complain about one error at a time. |
Consider these two analyzers (neither one works yet): # Check for proper permissions & record any errors
class PermissionAnalyzer1
def initial_value(query)
{
current_user: query.context[:current_user],
errors: [],
}
end
def call(memo, visit_type, irep_node)
required_scope = get_required_scope(irep_node)
if !has_required_scope(memo[:current_user], required_scope)
memo[:errors] << GraphQL::AnalysisError.new("Scope required but not present: #{required_scope}")
end
memo
end
# Return errors ... or an empty array, if there weren't any
def final_value(memo)
memo[:errors]
end
end # Check for proper permissions & raise errors
class PermissionAnalyzer2
def initial_value(query)
{
current_user: query.context[:current_user],
}
end
def call(memo, visit_type, irep_node)
required_scope = get_required_scope(irep_node)
if !has_required_scope?(memo[:current_user], required_scope)
raise GraphQL::AnalysisError.new("Scope required but not present: #{required_scope}")
end
memo
end
def final_value(memo)
# pass, any notable event was handled by raising an error
end
end These are the two options we're talking about, right? I prefer the first one because, for a reader, you're not required to "jump" to gem internals to see where that error is going. (Or, if you're lucky, it might be documented 😬 ) In any case, implementing the second one includes supporting the first, and since this is Ruby, we should support
|
I actually prefer the first one, too! |
Hello! Now I can use phrases like, "At GitHub, we've..." 😆
At GitHub, we've got a few query analyzers. Two that report errors back to the user are our scope analyzer and our pagination analyzer. The scope analyzer ensures that, given a query, the requesting user has the right OAuth scopes and access (for example, if your query requests a user's email, you'll need the
user:email
scope. Our pagination analyzer reports on things like if you're not usingfirst:
orlast:
on connections, or if yourfirst
value is insanely large, etc.We're interested in cascading errors through all our analyzers, such that the
errors
response a user receives reports on all the errors in a query. After your talk with @bswinnerton, we realized we could usefinal_value
to report the sum of all the errors, but this is scoped per-query. We're trying to avoid a situation where we provide errors on scoping, the user fixes that, and then we provide errors on missing pagination arguments. Let's just throw 'em all at once!Would you be open to a patch that handles this? I'm thinking of passing along an ivar through the analyzers, and then defining a new method, like
schema.query_analysis_result_handler
, which a user can then define to do whatever they want.The text was updated successfully, but these errors were encountered: