fix: calculate costs for abstract fields correctly - #2925
Conversation
This PR fixes how costs for abstract types are calculated. Especially for fragments used on abstract types. For example, for actual costs, instead of summing each type of the union, engine sums only costs for types actually seen in the returned results. For estimated costs, instead of summing all the implementing nodes of abstract types, we just pick the implementing type with the maximum cost and add that to the costs of fields selected on the abstract type itself. I had to recalculate and verify numbers in tests. Unfortunately, this fix is not final. There is unfinished work with how the cost of the field itself is selected. Right now we pick the maximum weight across implementing types and dataSources independently from children costs selection. This concerns the estimation the most. The better approach would be to be tie this process with the selection of the type with maximum cost.
…1-inline-fragments-on-abstract-list-types-charge-all-items
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
WalkthroughBump graphql-go-tools to v2.4.4; switch router cost-header wiring and fallback to use ChangesCost calculation TypeNameStats migration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (2.12.2)level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies" Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2925 +/- ##
===========================================
+ Coverage 42.18% 66.05% +23.87%
===========================================
Files 846 258 -588
Lines 122252 27309 -94943
Branches 9731 0 -9731
===========================================
- Hits 51573 18040 -33533
+ Misses 70339 7818 -62521
- Partials 340 1451 +1111
🚀 New features to boost your workflow:
|
Router image scan passed✅ No security vulnerabilities found in image: |
…ct" (#1528) Follow-up to #1518. That PR was correct but incomplete and exposed an old defect. ## Problem `GetSchema()` only forced the **root** variables object non-nullable when the operation had a required variable: ```go if len(v.schema.Required) > 0 { v.schema.Nullable = false } ``` Operations with **all-optional variables** kept a nullable root. Before #1518 that serialized to `{"type":"object","nullable":true}` and was harmless (validators ignore the unknown `"nullable"` keyword). After #1518 it serializes to `{"type":["object","null"]}`, which strict consumers reject - the MCP go-sdk's `AddTool` requires the input schema `type` to be exactly `"object"` and panics: ``` panic: AddTool "list_employees": input schema must have type "object" (got [object null]) ``` This breaks the cosmo router engine bump 2.4.2 -> 2.4.3 (wundergraph/cosmo#2925): `pkg/mcpserver`, `protocol` and `security` suites all panic. ## Fix The root variables object is always a concrete object - the container is present or omitted, never the JSON literal `null` - so set `Nullable = false` unconditionally in `GetSchema()`. This is consistent with nested input-object variables, which are already forced non-nullable. Only individual optional fields remain nullable. Golden tests updated (root `["object","null"]` -> `"object"`); the `root_schema_nullable_based_on_required_arguments` subtest renamed to `root schema is always a non-nullable object`. ## Tests `go test ./pkg/engine/jsonschema/` passes; gofmt and go vet clean. Verified against the cosmo router via a local `replace`: `pkg/mcpserver` no longer panics. ## Follow-up Needs a patch release (2.4.4) and a corresponding engine bump in cosmo#2925. Fixes ENG-9682
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.
Tip: disable this comment in your organization's Code Review settings.
…ist-types-charge-all-items
…2926) Updates two stale goldens in router-tests/protocol/mcp_test.go to unblock the ./protocol job on #2925. The engine bump (graphql-go-tools #1518/#1528) changed nullable rendering from {"type":"x","nullable":true} to the union {"type":["x","null"]} (nullable enums gain a trailing null). These goldens hard-code the generated schema, so they went stale. Engine fix is correct; goldens just needed updating.
This PR fixes how costs for abstract types are calculated. Especially
for fragments used on abstract types.
For example, for actual costs, instead of summing each type of the
union, engine sums only costs for types actually seen in the returned
results.
For estimated costs, instead of summing all the implementing nodes of
abstract types, we just pick the implementing type with the maximum cost
and add that to the costs of fields selected on the abstract type
itself.
Also this includes fixes for jsonschema:
Summary by CodeRabbit
Chores
Bug Fixes / Improvements
Tests