|
| 1 | +# GraphQL WG Notes - September 2023 |
| 2 | + |
| 3 | +**Watch the replays:** |
| 4 | +[GraphQL Working Group Meetings on YouTube](https://www.youtube.com/playlist?list=PLP1igyLx8foH30_sDnEZnxV_8pYW3SDtb) |
| 5 | + |
| 6 | +# Primary |
| 7 | + |
| 8 | +Agenda: |
| 9 | +[https://github.com/graphql/graphql-wg/blob/main/agendas/2023/10-Oct/05-wg-primary.md](https://github.com/graphql/graphql-wg/blob/main/agendas/2023/10-Oct/05-wg-primary.md) |
| 10 | + |
| 11 | +## Determine volunteers for note taking (1m, Lee) |
| 12 | + |
| 13 | +- Benjie |
| 14 | + |
| 15 | +## Review prior secondary meetings (5m, Lee) |
| 16 | + |
| 17 | +- Previous meetings were skipped due to the conference. |
| 18 | + |
| 19 | +## Review previous meeting's action items (5m, Lee) |
| 20 | + |
| 21 | +- [Ready for review](https://github.com/graphql/graphql-wg/issues?q=is%3Aissue+is%3Aopen+label%3A%22Ready+for+review+%F0%9F%99%8C%22+sort%3Aupdated-desc) |
| 22 | +- [All open action items (by last update)](https://github.com/graphql/graphql-wg/issues?q=is%3Aissue+is%3Aopen+label%3A%22Action+item+%3Aclapper%3A%22+sort%3Aupdated-desc) |
| 23 | +- [All open action items (by meeting)](https://github.com/graphql/graphql-wg/projects?query=is%3Aopen+sort%3Aname-asc) |
| 24 | +- ACTION - Benjie: close all action items that haven't received activity in 6 |
| 25 | + months. |
| 26 | +- Lack of keyword implies this is a query, but we are talking about a selection |
| 27 | + set. |
| 28 | +- Lee: It's implied that the top is the mutation. |
| 29 | +- Benjie: line 399, “given the following operations” |
| 30 | +- Lee: intent is to show the full operation. That’s why this is perceived as |
| 31 | + confusing. Roman’s suggestion is correct but incorrect. |
| 32 | +- Lee: okay with this being an incremental thing, and take a partial fix from |
| 33 | + Roman. But we need follow ups. |
| 34 | +- Benjie: not 100% sure this is the right solution :). Specifically talking |
| 35 | + about executing a selection….. |
| 36 | +- ACTION: firm up the wording, e.g. replace "selection set" with "operation" or |
| 37 | + similar. |
| 38 | + |
| 39 | +## Client Controlled Nullability and True Nullability Schema (30m, Jordan/Benjie) |
| 40 | + |
| 41 | +- [True Nullability Schema](https://github.com/graphql/graphql-wg/discussions/1394) |
| 42 | +- [Null-Only-On-Error type (asterisk) RFC](https://github.com/graphql/graphql-spec/pull/1048) |
| 43 | +- Jordan: Product code will do null coalescing and other tricks to deal with |
| 44 | + nullable-by-default, or will just get issues. |
| 45 | +- CCN gives a solution to this to make it easier to work with; but there's a |
| 46 | + fundamental issue: these assertions are made "blindly". They can't see if a |
| 47 | + field is _expected_ to be null normally, or if it's an exceptional case where |
| 48 | + it's expected to be null, and it will only be null on error. |
| 49 | +- Q: Why do we coerce errors to null? |
| 50 | +- A: We want the client-server relationship to say that the "data" portion is |
| 51 | + type-safe with respect to the schema - so you know which fields will be there |
| 52 | + and which will not. Then we get an issue where a field wants to be null |
| 53 | + because of an error, but the schema says it cannot be null, so we propagate |
| 54 | + the null to the next level. |
| 55 | +- As we explored this with Relay, we realized that it's not type-safe data, and |
| 56 | + some "metadata" in the errors object; but actually it's a tree where each |
| 57 | + value is there, null, or an error. Errors are only separate as an encoding |
| 58 | + issue. |
| 59 | +- Lee: Agree. Also: forwards compatibility - we want schema changes to be able |
| 60 | + to be made without breaking older clients. You can always return a subset of |
| 61 | + the values from a field; but never a super set - never new unexpected values. |
| 62 | + Nullability is this shape of problem - a union of the thing you can get with |
| 63 | + null. This is why GraphQL does this the opposite way around to most |
| 64 | + programming languages - it's never safe to make an output nullable, but it's |
| 65 | + always safe to make it non-nullable - therefore non-null, adding the `!`, is |
| 66 | + the safe behavior. |
| 67 | +- Most schema designers follow the defaults, and the default is nullable to make |
| 68 | + sure that these changes can be made later. |
| 69 | +- Jordan: Now let's think about "error handling clients". These clients aren't |
| 70 | + comfortable rendering partial data. Adding Relay to the Ads manager product at |
| 71 | + Facebook and the coercion story is not comfortable; and we're not alone - we |
| 72 | + only want to see null when it's really truly null. Relay is exploring error |
| 73 | + handling approaches. It's common to throw away entire responses if any errors |
| 74 | + exist. This is the default state for Apollo Client too. |
| 75 | +- Relay wants to be an error handling client that will never render a null |
| 76 | + that's actually an error, but will contain that in some way. Imagine reading a |
| 77 | + field on the client is like lazily evaluating the field on the server - and |
| 78 | + that might throw. So it's like propagating the error from the server until you |
| 79 | + read it on the client, and then using the client's own error handling |
| 80 | + mechanisms for that read. |
| 81 | +- This class of clients are doing a lot of work to handle nulls that are never |
| 82 | + expected to be null; we could be handling that. |
| 83 | +- Desire: communicate to the clients the "true" nullability of these fields. |
| 84 | + When they meet a true null, they will then know that the value being null is a |
| 85 | + normal part of operation, not an exceptional case. |
| 86 | +- Two missing pieces: |
| 87 | + 1. A mechanism for error-handling clients to see the "true nullability" of the |
| 88 | + schema, whilst allowing non-error-handling clients to see the expectations |
| 89 | + that they see today. Sharing the same server, same schema potentially. |
| 90 | + 2. Resilient error-handling clients would like to opt-out of null bubbling |
| 91 | + (and error coercion generally). Give me any data, just tell me it's an |
| 92 | + error. |
| 93 | +- Lee: Why don't we have the metadata today to accept the garbage and use the |
| 94 | + errors metadata to determine the null is an error. |
| 95 | +- Jordan: the client can know that; but at type generation time an |
| 96 | + error-handling client wants to give a non-nullable type if it will only be |
| 97 | + null on error. |
| 98 | +- Stephen: Result<Option<T>> can become Result<T> if we know it's just |
| 99 | + the value or an error. |
| 100 | +- Lee: historical validation of this: classic failure mode was before |
| 101 | + client-side type generation got good, we had Obj-C and Java generating |
| 102 | + mediocre types and not thinking hard about nulls, and the Java clients often |
| 103 | + assumed that nulls weren't possible, which was generally true but not always - |
| 104 | + and then all the clients would NPE. We had to handle this in all the clients |
| 105 | + at Facebook. |
| 106 | +- Benjie: what we need is what Jordan described as true nullability from the |
| 107 | + server (source of truth). This will help out greatly with different peoples’ |
| 108 | + asks. Some people want exceptions, others want default behavior. |
| 109 | +- Benjie: expressing true nullability “nonnull”, “nonOnlyOnError” mutually |
| 110 | + exclusive. |
| 111 | + - https://github.com/graphql/graphql-spec/pull/1048/files |
| 112 | +- Lee: What's the new semantic information that’s communicated by schema |
| 113 | + developer? Does the combination of the two for client developers seem great or |
| 114 | + complicated? |
| 115 | +- Michael: The client can switch null bubbling off is the value prop of this |
| 116 | + proposal. So unclear how the marking here provides value to the consumer. |
| 117 | +- Benjie: the client still needs to make decisions of every single null they can |
| 118 | + potentially encounter. The \* indicate it will only be null in the exception |
| 119 | + case. So for a true null-handling client you can know this thing will have a |
| 120 | + non-null value, otherwise it will be thrown. |
| 121 | +- Michael: Any field could throw error, what’s the benefit of having “_”. |
| 122 | + Unclear about the decision the client can make with the “_” |
| 123 | +- Jordan: The need for the 3rd state is for bridging the stage of existing |
| 124 | + clients and the client can handle the null/error/nonnull union types. The |
| 125 | + middle state will be interpreted differently during the client codegen stage. |
| 126 | +- Martin: @catch?? The actual control? The middle type shouldn’t be too |
| 127 | + concerned with the codegen? |
| 128 | +- Jordan: if I’m a codegen client, and the field is in the middle state, then I |
| 129 | + will handle it differently. But I can give you a safe non-null type. Existing |
| 130 | + client is not a error handling client. |
| 131 | +- Lee: What do we want the default to be? Nonnull modifiers have the effect of |
| 132 | + creating a different way to create an error bubble. When we introduce “_” is |
| 133 | + that going to be everywhere, or do we want to advise it to use sparsely. ? is |
| 134 | + either null, or value. Default is the “ambiguous” field. ‘?’ makes it clear |
| 135 | + that this field is indeed semantically null. “_” resolves the ambiguity. |
| 136 | +- Benjie: every single SDL that currently exists, if they wanna introduce this, |
| 137 | + all these files need to be all modified. |
| 138 | +- Lee: If this proposal is also where you (Benjie) started, I think there is |
| 139 | + something there, that I think worth figuring out. |
| 140 | +- Stephen: for backend developer who knows nothing about GraphQL “\*” will be |
| 141 | + confusing and “?” is much more intuitive. |
| 142 | + |
| 143 | +## Full Schemas (15min, Martin) |
| 144 | + |
| 145 | +- [Terminology + Appendix C: built-in definitions](https://github.com/graphql/graphql-wg/discussions/1391) |
| 146 | +- [https://github.com/graphql/graphql-spec/pull/1049](https://github.com/graphql/graphql-spec/pull/1049) |
| 147 | +- Related topic. Full schema idea: in Apollo Kotlin we need to be able to |
| 148 | + validate an arbitrary operation, and we can't do that without knowing which |
| 149 | + introspection features the schema supports. |
| 150 | +- Ideally there'd be an artifact that can be produced by the server and consumed |
| 151 | + by the client that includes the "full schema" definition. |
| 152 | +- Source schema document: what we do today, brevity important, written by |
| 153 | + humans, no-built in types (boring; might conflict) |
| 154 | + - `type Query {a: Int}` < Valid source schema |
| 155 | +- Full schema document: exhaustive; contains _all_ of the built in types, |
| 156 | + written by machines, much more verbose. Can be used to determine if the schema |
| 157 | + opts out of null bubbling or other such things. |
| 158 | +- Currently doesn't contain meta-fields: `__type`, `__schema` and `__typename`. |
| 159 | + `__typename` especially is really verbose. |
| 160 | +- There may be unused types in the document - e.g. if `ID` is not used anywhere |
| 161 | + it may still exist in the full schema document |
| 162 | +- Apollo Kotlin users often do an introspection query and convert to GraphQL to |
| 163 | + store into source control; they're already doing this. |
0 commit comments