[PRO] Can't get custom directive from a document retrieved from the operation store
alexeyr-ci opened this issue · 3 comments
Describe the bug
I've added a custom directive which applies to queries. When I get a document for a query which has this directive, I can't obtain the directive (and its arguments) from the document.
Versions
graphql
version: 1.13.23
graphql-pro
: 1.25.2
rails
: 7.0.8.1
GraphQL schema
class GraphDirective::Cache < GraphQL::Schema::Directive
argument :max_age, Integer, required: false, description: 'Cache expiration in seconds'
locations QUERY
end
class ApplicationSchema < GraphQL::Schema
directive(GraphDirective::Cache)
...
end
GraphQL query
Example GraphQL query and response (if query execution is involved)
query menuItemReviews ($menuItemId: Int, $pagination: PaginationInput, $approved: Boolean) @cache { ... }
{
"data": {
"products": […]
}
}
Steps to reproduce
- Create a custom directive
- Create a schema and a query including this directive.
- Obtain a document for the
operation_id
corresponding to the query as follows:GraphQL::Query.new( ApplicationSchema, variables: variables, context: context, operation_name: operation_name, ).document
context
here containsoperation_id
. It's actually constructed in a pretty complex way, if I need to create a minimal reproduction I'll have to reduce that part. Maybe there is a better way to obtain the document? But it's the one I found by checking whereSchema.execute
ends up. - Get the definition for the query from the document with
definition = document.definitions.find { |definition| definition.name == operation_name }
. - Check
definition.directives
.
Expected behavior
definition.directives
should contain the directive from the query.
Actual behavior
definition.directives
is empty. I can see the full definition
in the debugger, and all @directives
are empty, so it doesn't seem like there is another way to access the needed directive.
Hey, thanks for the detailed report and sorry for the trouble! I wrote up a script like your report above, but it worked for me:
Reading custom query-level directives from OperationStore
require "bundler/inline"
gemfile do
gem "graphql", "1.13.23" # or latest, 2.3.2
gem "graphql-pro", "1.25.2" # or latest, 1.27.4
gem "redis"
gem "racc"
gem "logger"
end
$redis = Redis.new
$redis.flushall
class MySchema < GraphQL::Schema
class Cache < GraphQL::Schema::Directive
argument :max_age, Integer, required: false, description: 'Cache expiration in seconds'
locations QUERY
end
class Query < GraphQL::Schema::Object
field :int, Integer do
argument :i, Integer
end
end
query(Query)
directives(Cache)
use GraphQL::Pro::OperationStore, redis: $redis
end
MySchema.operation_store.upsert_client("client-1", "secret")
MySchema.operation_store.add(
client_name: "client-1",
operation_alias: "get-int",
body: "query GetInt($int: Int!) @cache { int(i: $int) }"
)
query = GraphQL::Query.new(MySchema, context: { operation_id: "client-1/get-int"})
pp query.selected_operation.directives.map(&:name)
# ["cache"]
pp query.document.definitions.find { |d| d.name == "GetInt" }.directives.map(&:name)
# ["cache"]
Does that script work for you? Or do you see anything missing from it, compared to your case?
One thing you could check is the OperationStore dashboard (doc). Can you find your sync
'd operation there? Does the query string in the dashboard include @cache
?
I'll try to check during the weekend or early next week.
I'm sorry, it looks like I simply didn't regenerate the operation store after modifying the query. It works as expected now, though I have an additional question I asked in discussions.