-
Notifications
You must be signed in to change notification settings - Fork 1.1k
[Pre-RFC] Support gradual upgrade/rename of Input types and Scalars in field arguments for values with compatible wire format #526
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
Comments
@kestred Sorry for the delay. Variant Also, note that in this proposal you don't need Do you want this issue to stay open or combination of #509 + #521 will solve your problem? |
@IvanGoncharov - they look mostly on point; only lingering questions for clarity. The key in both cases for me is how input arguments are validated against where Rather than how the value itself it is validated. The assertion being that in these examples wrt. #509Suppose some schema: input Point2D {
x: Float
y: Float
}
input Point3D {
x: Float
y: Float
z: Float
}
type Mutation {
addPoint(point: Point3D)
} Would this query execute without errors given how #509 is currently proposed? mutation ($myPoint: Point2D) {
addPoint(point: $myPoint)
} wrt. #521Suppose some schema: scalar PersonId ofType String;
type Person { .. }
type Query { person(id: PersonId!): Person } Would this query execute without errors given how #521 is currently proposed? query ($id: String!) {
person(id: $id)
} |
@kestred Good question, I'm not sure since we were focused only on scalar to list coercion and coercion between different scalar types.
With only #521 accepted it would produce errors. But with #521 + #509 it would valid query. |
For scalars, this behavior seems great!
Yeah, I agree that implicit conversion is sketchy here. In the ideas proposed above there were a variety of explicit mechanisms, however after this conversation I think a different mechanism for handling graceful upgrade might be more suitable (assuming #521 and #509 for scalars). Suppose we had some schema: input XY {
x: Float
y: Float
}
type Mutation {
addPoint(point: XY)
} I'd like to have a way to change the name of input Point {
x: Float
y: Float
z: Float
}
input XY = Point # or `input XY: Point`? `alias XY: Point`?
type Mutation {
addPoint(point: Point)
} Overall, I think |
@kestred In general, we need to balance features and added complexity. Not sure if it fully covers your scenario but #525 allows you to |
I'm hoping to discuss solutions for the use case of upgrading field argument input type / scalars from less-strict to more strict types; consider:
Where there isn't a reasonable way to make this change over time, because any change to the graph will break queries that use variables:
Motivation
This feels like (and certainly is for me) a very common use case where, you may start with a less specific type (frequently a
String
scalar) and would like to upgrade to a well-typed value over time (e.g. aBigDecimal
, aDateTime
, an enum, etc).Similarly, you may want to change the name of an
InputObject
, even if the structure of the argument hasn't changed to be able to provide a consistent and predictable API to consumers as business needs grow and change (separately, you'd of course like to be able to deprecate fields on InputObjects).I feel this is an especially frequent issue for rapidly prototyped graph APIs, that you'd like to harden and polish after they've already been deployed into a production environment.
The current way I'd make this change is an extraordinarily painful process both for the provider and consumers of an API:
Add a new field with the new arguments (or old ones; doesn't really matter) and
deprecate the previous field:
Wait for all consumers to switch off the old field.
Change the original field and de-deprecate it, deprecating the temporary field
Eventually remove the temporary, now deprecated, field.
Hopefully, an RFC that make this problem easier to solve reduces the amount of friction involved in gradual enhancement of a graph schema without being forced to choose between having a well-typed schema vs. having a predictable schema.
Ideas/Suggestions
I will add ideas from the thread here as they are discussed (Last Edited: Oct 25, 2018)
A. Overloading fields
The spec could allow fields to be overridden; the executor would choose which variant to resolve through a combination of the name and number of arguments and the type of input variables.
There would be ambiguity when NOT using variables, which could be resolved by:
@defaultOverload
)The
@deprecated
attribute could be applied as normal to any of the overloadsB. Anonymous Input Unions (aka. sum types) w/ deprecatable variants
This is similar to many of the InputUnion suggestions, with the key difference being in how
variables are validated. With an anonymous input union, a variable should be specified
using any of the variant names, rather than the a new InputUnion name.
This suffers from all of the same variant discrimination problems as previous work on input unions:
see #395, #488,
and #202.
C. Less strict type inference of variables using
ofType
We could allow scalar variables types to be valid if the wire representation of the scalar is passed as the type of the variable instead of the more strict type; relying on something like #521.
For example,
Unfortunately, by only relying on that change, this only converting builtin scalars to well typed scalars (but not vice-versa) and doesn't provide a solution for renaming
InputObject
s.D. Allowing explicit type coercions
We could come up with a way to annotate that type coercion between any two types is supported.
This is somewhat of an extension of #521.
Currently this idea is my favorite (syntax and details to be worked out).
The text was updated successfully, but these errors were encountered: