Skip to content
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

Using callable (unresolved) fields with a long running server #1329

Closed
oprypkhantc opened this issue Mar 2, 2023 · 8 comments
Closed

Using callable (unresolved) fields with a long running server #1329

oprypkhantc opened this issue Mar 2, 2023 · 8 comments

Comments

@oprypkhantc
Copy link
Contributor

oprypkhantc commented Mar 2, 2023

Hey.

I initially created an issue in another project which uses webonyx/graphql-php - thecodingmachine/graphqlite. I'm using Swoole as an HTTP server so I'm able to share the Schema instance across multiple requests.

It all plays nicely until you're trying to have dynamic field definitions based on the request. Rarely, but sometimes this is needed, for example when you're trying to hide fields based on authorization. Normally, fields defined with callback solve this:

'fields' => [
    'field' => function () {
        return random_bool() ? new FieldDefinition() : new FieldDefinition(); // yada yada
    }
]

but there are two problems with this:

  1. After resolving this callback, it's result is cached. If you change it so it's resolved each time getFields() is called it seems to work
  2. It's not possible to exclude the field dynamically from that callback, i.e. you have to return a FieldDefinition and can't return null

Those two are separate, but related issues. I don't think an efficient solution (one that would not require rebuilding the whole schema on each request) is there.

Thoughts?

@spawnia
Copy link
Collaborator

spawnia commented Mar 2, 2023

Use two schemas.

@spawnia spawnia closed this as not planned Won't fix, can't repro, duplicate, stale Mar 2, 2023
@oprypkhantc
Copy link
Contributor Author

@spawnia There could be hundreds of "dynamic" fields, meaning we'd have to rebuild the whole Schema on each request. This is an enormous amount of performance & request time lost for nothing. Isn't there a better way? Apps on Swoole are becoming increasingly more popular and this will only become more of a problem with time.

@spawnia
Copy link
Collaborator

spawnia commented Mar 2, 2023

This library fundamentally assumes that types are immutable once defined. It would be a lot of work (including deviating massively from the reference library!) to change this.

@oprypkhantc
Copy link
Contributor Author

Got you. I'll try to make it work by creating different Schema's and some clever caching and see if it works. Thank you.

@spawnia
Copy link
Collaborator

spawnia commented Mar 2, 2023

I would advise presenting a consistent schema to users and implement access control on top of that. Hiding fields is very bad for clients that rely on introspection as part of their tooling.

@oprypkhantc
Copy link
Contributor Author

Yes, that was my first thought. For authorization that's what we're doing - I just used this as an example.

My real use case is versioning - I want to version the whole Schema based on a header. I'm aware this is not recommended but I'm not a fan of proposed solutions (like creating fields under a different name or passing a version argument to each one) - it's just not very scalable in a project that changes rapidly.

@spawnia
Copy link
Collaborator

spawnia commented Mar 2, 2023

it's just not very scalable in a project that changes rapidly.

Facebook would disagree.

@oprypkhantc
Copy link
Contributor Author

it's just not very scalable in a project that changes rapidly.

Facebook would disagree.

Facebook doesn't expose it's GraphQL API to the public so it's not a problem they care about. It does become one when you need to communicate to multiple API consumers, both internal and public, about changes in the API and urge them to upgrade.

It's just a cleaner way of handling this, although obviously just going for never-breaking schema evolution is fine as long as you don't need any of that and are willing to deal with non optimal field names and types.

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

No branches or pull requests

2 participants