Repository navigation
Conversation
1e843ee to
e53163c
Compare
✅ Docs preview has no changesThe preview was not built because there were no changes. Build ID: d507af89603b2af8236da390 ✅ AI Style Review — No Changes DetectedNo MDX files were changed in this pull request. Review Log: View detailed log
|
There was a problem hiding this comment.
The issue here is the supergraph schema that expand_connectors() generates for satisfiability checking is invalid. That code is declaring (via @join__types in the supergraph schema) that certain enum types aren't present in the synthetic subgraphs when they really should be, and your PR change (instead of fixing the pathway that generates the supergraph schema for connectors) is saying that subgraph extraction logic should just ignore the invalid @join__types and try to patch up the synthetic subgraph schemas by looking at usages. That might be necessary if e.g. those invalid supergraph schemas were passing composition and we needed to support them in the router, but they're getting caught at composition time, and we should keep rejecting them there (and fix connectors code).
e53163c to
54539b4
Compare
0a0c7bc to
78f363e
Compare
There was a problem hiding this comment.
Two general comments here.
The first is that while the approach in this PR does try to ensure a valid supergraph schema is generated, I think the way it goes about this isn't robust. Specifically, the current approach tries to patch up the generated supergraph schema, instead of modifying the code that generates the synthetic subgraph schemas from the extracted subgraphs (i.e. split_subgraph()).
I can understand why the supergraph-modification approach might make sense in the current codebase, since subgraph extraction currently doesn't extract all the features of the supergraph, and connectors code has historically worked around this via some manual carryover logic in carryover_directives() (logic that this approach modifies, specifically via copy_input_types()). However, the only reason why subgraph extraction hasn't extracted some features, is that nothing downstream of subgraph extraction needed those features prior to connectors. (Separate from that, the normalization that occurs as part of merging means there isn't a single canonical way to extract subgraphs, but we should be fine to just pick one. The assertion of normalization being correct is that it shouldn't matter to downstream logic, and if it did, the normalization shouldn't have been performed to start with.) In this particular case, subgraph extraction does add the executable directive and any referenced types during subgraph extraction, so AFAICT there's no reason this approach needs to patch the supergraph schema directly.
As part of cleaning up that connectors carryover logic in the future, I expect that we'll update subgraph extraction logic to not just ignore these features (ideally making extraction idempotent, in the sense that extracted subgraphs generate a semantically equivalent supergraph schema when recomposed), and we'll swap out the old merge logic POC with the modern merge logic we use today. This brings us to the first robustness issue, which is that modern merge logic expects the subgraph schemas to be valid GraphQL, so making the changes to carryover_directives() instead of split_subgraph() means we'll have to throw this PR's work away in the future, and make the fix instead to split_subgraph() anyway.
The second robustness issue, is that the code in the current approach tries to mimic/understand how merging and @join__* logic work when modifying the supergraph schema. Doing this is bug-prone because that logic is complex, and ideally we'd leave that to the merge logic itself instead of trying to mimic it.
This brings me to the second general comment, which is that the PR's current code does contain such a bug. When computing @join__enumValues and @join__fields to add, it looks at the @join__types on the desired nodes instead of @join__enumValues and @join__fields on the desired nodes (which means the patched supergraph schema may mistakenly declare an enum value/input field is in a subgraph when it isn't).
If we need to get this fix out fast, fixing the second general comment should be enough. However, if we've got the time, I'd prefer to make the fix to split_subgraph() instead (if there's a specific reason we shouldn't make the fix there, let me know).
|
So something was bothering me about the The thing is though, when I looked at What this means is there's actually another |
78f363e to
48117bb
Compare
|
Reworked per review: the fix now lives in |
… subgraphs
Connector expansion builds each synthetic subgraph from an empty schema and
never copied executable directive definitions, or the types their arguments
reference, into it. When a non-connector subgraph defined the directive, the
expanded supergraph still contained it, but marked the argument types as absent
from the synthetic subgraphs, so subgraph extraction during satisfiability
produced invalid schemas ("Cannot wrap an undefined/null type" in JS). When
every subgraph used connectors, the directive was dropped entirely.
Both expanders now copy executable directive definitions from the source
subgraph, carrying over their argument types through process_inputs, so the
synthetic subgraphs are valid on their own and merging produces correct join
membership. This replaces the earlier approach of patching @join__* membership
in carryover.
Ref: RH-1375
48117bb to
c894f8d
Compare
…ion.md Co-authored-by: Dariusz Kuc <9501705+dariuszkuc@users.noreply.github.com>
Summary
Composing connector subgraphs alongside an executable directive whose arguments reference a custom type (for example
directive @ownership(owners: [Owner!]) on FIELDwithenum Owner) failed satisfiability validation:Rust-native composition reports the same problem as
Directive argument "@ownership(owners:)"'s inner type "Owner" does not refer to an existing input type.Root cause
split_subgraph()builds each synthetic connector subgraph from an empty schema, and neither expander (legacy v0.1-v0.3 nor v0.4+) copied executable directive definitions into it. Two bugs followed:merge_subgraphs()emits an executable directive if any single subgraph defines it, so a non-connector subgraph kept the directive in the expanded supergraph. But the synthetic subgraphs never declared its argument types, so@join__typerecorded them as absent. Subgraph extraction copies executable directives into every subgraph, which left the synthetic subgraphs referencing types they didn't have.Fix
Per review, the fix now lives in
split_subgraph()rather than in carryover. Both expanders gainprocess_executable_directives, which runs first inexpand(): for each directive definition in the source subgraph that has an executable location (and isn't already in the new schema, which skips built-ins), it carries over the argument types using the existingprocess_inputs(scalars, enums, and input objects, recursively), then inserts the definition.The synthetic subgraphs are now valid GraphQL on their own, and merging produces the correct
@join__type/@join__enumValue/@join__fieldmembership without any hand-written join logic. The earliercarryover/inputs.rsapproach is gone.Tests
Two regression tests in
tests/composition/connectors.rs, each run against connect/v0.2 (legacy expander) and v0.4:executable_directive_arg_types_survive_connector_expansion: a connector subgraph plus a plain subgraph, both defining the directive. Composition fails before the fix and succeeds after.executable_directive_survives_all_connector_expansion: connector subgraphs only. Composes, runsexpand_connectors, and asserts the expanded supergraph keeps the directive and its enum, scalar, and input types, and that subgraph extraction succeeds. Before the fix, the directive was missing.Full
apollo-federationsuite passes with no snapshot changes.Not in scope
merge_subgraphs()still emits an executable directive when any subgraph defines it, rather than requiring all of them like real composition. That's a behavior change for non-connector inputs, so it's left for a follow-up (and goes away once expansion moves to the modern merge code).Ref: RH-1375