Skip to content

Conversation

@exbe
Copy link
Contributor

@exbe exbe commented Jun 15, 2018

  • ? extends GraphQLType can be traversed using TypeTraverser
  • SchemaUtil implementation uses visitor/traverser to fulfill its contract

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JavaDoc on key types would be needed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this one a real stretch in terms of saying this is "better"...There are 2 conditions -scalar and enum and there is some unwrapping to be done.

If I look at this code is an indirection that is low value.

That said the others have more value

Copy link
Contributor Author

@exbe exbe Jun 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unwrapping is using recursion, which is based on a fixed stack.

Large and deep graphs have a chance to overflow stack. VERY large graphql type system will overflow it for sure.

Recursion is also application-dependent at runtime. If this lib will be called after web server, IoC framework, other application layers .... this all eats up stack leaving less and less room. Not to mention hypothetical cycles in graphql type system...

Another hypothetical case is there application developer would run graphql in a thread with custom (and small) execution stack.

Traverser is free from all above issues. It relies on a true stack, which would grow in size if needed and tracks visited types as it goes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In theory - perhaps

but in practice, given a graphql type it can only be 1 of 6 different types (enum, scalar, object, input, interface and union) or the wrappers like (list, null, type reference)

So in order to blow the stack given a single graphql type, then you would need megabytes of wrapping

eg [![![![![![![![![![![![![![SomeTypeHere]]]]]]]]]]]

Given a simple graphql type there is no infinite tree.

Now if you include graphql.schema.GraphQLFieldDefinition (which does not derive from GraphqlType) then yes you can have a large tree.

My point is that not ALL uses case of recursion are problematic. And in this case where we have a single GraphqlType, not at all.

Copy link
Contributor Author

@exbe exbe Jun 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My point is that not ALL uses case of recursion are problematic.

Agree on 100%. Do you think that traverser gives too much of overhead?

This case might be trivial, but it is still type traversal. Traverser looks good enough to cover this case too. Would you prefer to have custom algorithm here instead?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Java Doc and @internal of @publicapi would be needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeTraverser is similar to NodeTraverser. Shall I update both?

I consider NodeTraverser/TypeTraverser as @internal for now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, please make it @Internal for now.

@bbakerman
Copy link
Member

The build is failing with

A problem occurred evaluating root project 'graphql-java'.
git hash could not be determined

I am not sure what they means however. Can you re-pull master onto this branch so as to perhaps fix this.

I did this on other branches and it seem to work. Like I said I am not sure what this is??

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is enough visitor code here that it deserves its own file.

Perhaps not one class per visitor so I would create a package protected holder of these classes called say "TypeVisitors" that contained these classes

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please put these at the top of the file. Bit more idiomatic

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simple JavaDoc please.

This probably deserves to be @publicapi eventually (as a help to write a visitor)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also naming as mentioned above GraphqlTypeVisitorStub

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming is hard but I would call this (and the others) GraphqlTypeVisitor

My reasoning is that we have runtime types and AST types and its already confusing

So we have GraphqlType / GraphqlObjectType and so on to help with that

Hence I visitor of GraphqlType thigns should have the GraphqlTypeVisitor naming. Same with the stubb and so on

Copy link
Member

@bbakerman bbakerman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to see more unit tests of the specific traversal on all types.

I know existing tests around SchemaUtil probably test this by accident

But I think we need a test that demonstrates that given all the GraphqlType derived things, that a visitor will in fact see them all.

@exbe
Copy link
Contributor Author

exbe commented Jun 18, 2018

@bbakerman Build failure is coming from gradle function (here), but it seems execution of the git command itself was ok. I think it has something to do with gradle thread... not sure.

I will try to re-base/re-sync with latest master and see what happens.

From travis log.

current git hash:
git rev-parse --short HEAD
df45cb3

Thank you for review, I will follow up with comments.

@exbe exbe closed this Jun 18, 2018
@exbe exbe reopened this Jun 18, 2018
@exbe
Copy link
Contributor Author

exbe commented Jun 18, 2018

@bbakerman I feel confused with usage of @PublicAPI/@internal. Is there guide anywhere besides javadoc? Basically I would love to wait few release before switching it to public. Probably we could od same thing for NodeVisitorStub/NodeVisitor - they are @internal, but I believe they should be @public as well.

Let me ping you about test cases on gitter. I might need to clarify some use cases.

@exbe
Copy link
Contributor Author

exbe commented Jun 18, 2018

PS close-reopen PR helps to "fix" build failure on travis CI

@andimarek
Copy link
Member

@exbe yes: the current build (getting the git hash part) is sometimes flaky.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this deprecated now?

Copy link
Contributor Author

@exbe exbe Jun 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andimarek This method was part of older recursive reference resolution algorithm.
This PR uses getChildren() to unwrap actual type and replaceType(GraphQLInputType type) to set it.

I am not sure if anyone else is using it (e.g. clients), so I have marked it as @deprecated.
Ideally, if it is not part of some use case, this can be removed in future versions.

If I miss some use case, I would be happy to learn about it and add support.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove them: they are not used anywhere else and were only for one purpose

@exbe
Copy link
Contributor Author

exbe commented Jun 20, 2018

@bbakerman @andimarek I think I responded to all comments.
Please take a look

Copy link
Member

@andimarek andimarek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this PR.
In general I think it is a real improvement compared to the manual traversing. 👍

Please see my other comments for what to change.

Also: Please use the graphql-java formatter https://github.com/graphql-java/graphql-java/blob/master/graphql-java-code-style.xml and format your code with that.

Thanks

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Class name: 'GraphQLTypeVisitor' not 'GrapqhlTypeVisitor'

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the difference here between Interfaces and concrete types?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For convince, which is based on assumption that in most cases developers won't need to visit marker interface very often (even stub doesn't care).

Not a big deal - I can move default implementation under GraphQLTypeVisitorStub.

What is your preference @bbakerman and @andimarek?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

naming: GraphQL...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unit testing is missing: have a look at NodeVisitorStubTest for inspiration.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is getting tested via TypeTraverserTest :) Is it good enough?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

naming: GraphQL...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please make every class public and extract in a extra file. Don't make them package protected, but mark them as @Internal

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, please make it @Internal for now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why protected? I would say make it private. We don't really design for inheritance: if there is something that should be customizable it should be done in another way.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private .. see above

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private static please if we keep it, but more important: simplify it please by only caring about enter, because we only support depthFirst atm.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @bbakerman: the original code for isLeafType and isInputType is so much simpler and I don't really see a non theoretical argument to replace that. So please revert it to the original code and delete the LeafVisitor.

@andimarek
Copy link
Member

We will probably make the NodeTraverser public, this includes TraverserContext. See #1097. So I don't see a problem to make this visitor also public. @exbe

@exbe
Copy link
Contributor Author

exbe commented Jul 16, 2018

@bbakerman @andimarek do you see anything else, which I should change in a scope of this PR?
Please let me know.

@exbe
Copy link
Contributor Author

exbe commented Aug 26, 2018

@bbakerman @andimarek any updates on this one?

@andimarek
Copy link
Member

I am really sorry for the delay @exbe. Will try to review it soon.

@exbe
Copy link
Contributor Author

exbe commented Sep 3, 2018

@andimarek no worries, take your time :)

Copy link
Member

@andimarek andimarek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, see my comments for some final thoughts.

import graphql.util.TraversalControl;
import graphql.util.TraverserContext;

@Internal
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be public: we recently made the general Traverser also public, so nothing prevents us from making this public too

public TraversalControl visitGraphQLTypeReference(GraphQLTypeReference node, TraverserContext<GraphQLType> context) {

final GraphQLType resolvedType = typeMap.get(node.getName());
Assert.assertTrue(resolvedType != null, "type %s not found in schema", node.getName());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just as a hint: we also have assertNoNull

import graphql.util.TraverserContext;

@Internal
public class GraphQLTypeRefResolvingVisitor extends GraphQLTypeVisitorStub {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you think about putting this class into the other one GraphQLTypeResolvingVisitor? it is a very hard dependency and it would make it more readable imho

…lver

- type visitor promoted to public api
- better code style for assertion
@exbe
Copy link
Contributor Author

exbe commented Sep 5, 2018

@andimarek please check

@andimarek
Copy link
Member

@exbe thanks for the patience ... looks good

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants