Skip to content

feat(router): support input objects in Cost Control#2716

Merged
ysmolski merged 10 commits intomainfrom
yury/eng-8731-cost-handle-recursion-for-arguments-containing-input-objects
Apr 8, 2026
Merged

feat(router): support input objects in Cost Control#2716
ysmolski merged 10 commits intomainfrom
yury/eng-8731-cost-handle-recursion-for-arguments-containing-input-objects

Conversation

@ysmolski
Copy link
Copy Markdown
Contributor

@ysmolski ysmolski commented Mar 31, 2026

This PR adds support of input object fields passed as arguments. It handles nested input objects, recursive types, list of input objects and list-typed arguments.

Negative weights on input fields reduce the cost,
but clamped to zero for each field.

Engine PR: wundergraph/graphql-go-tools#1461

Summary by CodeRabbit

  • Refactor
    • Cost calculation now uses request variables so estimated and actual GraphQL cost headers reflect per-request inputs more accurately.
  • New Features
    • Input-field cost weights added to the schema to allow finer-grained cost influence from request payloads.
  • Tests
    • Added/updated tests validating exact estimated/actual cost headers and execution plan cache HIT/MISS behavior.
  • Chores
    • Updated a GraphQL tooling dependency version.

This PR adds support of input object fields passed as arguments.
It handles nested input objects, recursive types, list of input objects
and list-typed arguments.

Negative weights on input fields reduce the cost,
but clamped to zero for each field.

Engine PR: wundergraph/graphql-go-tools#1461
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

Important

Review skipped

This PR was authored by the user configured for CodeRabbit reviews. CodeRabbit does not review PRs authored by this user. It's recommended to use a dedicated user account to post CodeRabbit review feedback.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3750930b-d21c-476b-b720-0e3ef828f3e0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

GraphQL cost calculation now uses request/resolve variables: the GraphQL handler computes actual cost from resolveCtx.Variables, and OperationKit invokes cost validation/estimation with only opCtx.variables. Tests, a demo schema input-field @cost annotations, and two Go module versions were updated.

Changes

Cohort / File(s) Summary
GraphQL handler
router/core/graphql_handler.go
Compute costCalc.ActualCost using resolveCtx.Variables for synchronous responses (header callback and post-resolve fallback).
Operation processor
router/core/operation_processor.go
Call ValidateSliceArguments and EstimateCost with only opCtx.variables (removed planConfig argument).
Tests
router-tests/.../costs_test.go
Tightened assertions: removed non-empty checks, added exact estimated/actual header expectations, new measure-mode input-object-field-weight tests, and stricter plan-cache HIT/MISS and cache-consistency checks.
Go module bumps
router/go.mod, router-tests/go.mod
Bumped github.com/wundergraph/graphql-go-tools/v2 to a newer pseudo-version in both modules.
Demo schema
demo/pkg/subgraphs/employees/subgraph/schema.graphqls
Added @cost(weight: 17) to FindEmployeeCriteria.department and @cost(weight: -3) to FindEmployeeCriteria.title input fields.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'feat(router): support input objects in Cost Control' accurately describes the main change, which is adding support for input object fields in the router's Cost Control logic.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 31, 2026

Router image scan passed

✅ No security vulnerabilities found in image:

ghcr.io/wundergraph/cosmo/router:sha-8934c5eb9d3d14d032d5921ffc1b90f1c3112e71

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 31, 2026

Codecov Report

❌ Patch coverage is 75.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 60.70%. Comparing base (f90dc88) to head (7d5a86c).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
router/core/graphql_handler.go 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2716      +/-   ##
==========================================
- Coverage   63.24%   60.70%   -2.54%     
==========================================
  Files         251      251              
  Lines       26767    26767              
==========================================
- Hits        16929    16250     -679     
- Misses       8459     9139     +680     
+ Partials     1379     1378       -1     
Files with missing lines Coverage Δ
router/core/operation_processor.go 81.57% <100.00%> (-3.44%) ⬇️
router/core/graphql_handler.go 47.27% <50.00%> (-21.82%) ⬇️

... and 37 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ysmolski ysmolski requested review from a team as code owners April 1, 2026 13:08
@ysmolski ysmolski requested a review from JivusAyrus April 1, 2026 13:08
…1-cost-handle-recursion-for-arguments-containing-input-objects
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
router-tests/security/costs_test.go (1)

296-344: Add a variable-backed case for the new input-object coverage.

These additions only use inline object literals. The router changes here are about request-supplied input values, so a regression in variable handling would still leave this coverage green. In the cache-hit block, using one parameterized query and varying only Variables would also prove the HIT behavior without depending on inline-literal normalization.

💡 Minimal pattern
- res := xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{
- 	Query: `{ findEmployeesBy(criteria: { department: ENGINEERING }) { id } }`,
- })
+ res := xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{
+ 	Query:     `query($criteria: FindEmployeeCriteria!) { findEmployeesBy(criteria: $criteria) { id } }`,
+ 	Variables: []byte(`{"criteria":{"department":"ENGINEERING"}}`),
+ })

Also applies to: 915-964

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@router-tests/security/costs_test.go` around lines 296 - 344, Add a
variable-backed test case to cover input-object handling via variables rather
than inline literals: create a t.Run similar to the existing "input object field
cost weight" cases but send the criteria as a GraphQL variable (e.g., query with
a $criteria variable and set testenv.GraphQLRequest.Variables to {"criteria":
{"department":"ENGINEERING"}} or {"title":"Founder"}), assert the same
CostEstimatedHeader and CostActualHeader values, and in the cache-hit block
repeat the same parameterized query while varying only the Variables to prove
HIT behavior; update the existing test functions that call
xEnv.MakeGraphQLRequestOK to use Variables instead of inline criteria.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@router-tests/security/costs_test.go`:
- Around line 946-962: The test is reading the actual-cost header from the wrong
response object (resTitle1) for the 3rd and 4th requests; update the assertions
to read core.CostActualHeader from resDept2 for the 3rd request and from
resTitle2 for the 4th request so each request validates its own actual-cost
header (locate the checks near resDept2, resTitle2, resTitle1 and replace the
mistaken resTitle1 usages).

---

Nitpick comments:
In `@router-tests/security/costs_test.go`:
- Around line 296-344: Add a variable-backed test case to cover input-object
handling via variables rather than inline literals: create a t.Run similar to
the existing "input object field cost weight" cases but send the criteria as a
GraphQL variable (e.g., query with a $criteria variable and set
testenv.GraphQLRequest.Variables to {"criteria": {"department":"ENGINEERING"}}
or {"title":"Founder"}), assert the same CostEstimatedHeader and
CostActualHeader values, and in the cache-hit block repeat the same
parameterized query while varying only the Variables to prove HIT behavior;
update the existing test functions that call xEnv.MakeGraphQLRequestOK to use
Variables instead of inline criteria.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 903f7717-2d92-47f7-a210-f315cb99cfb9

📥 Commits

Reviewing files that changed from the base of the PR and between 167dee4 and b3b1b53.

⛔ Files ignored due to path filters (1)
  • demo/pkg/subgraphs/employees/subgraph/generated/generated.go is excluded by !**/generated/**
📒 Files selected for processing (3)
  • demo/pkg/subgraphs/employees/subgraph/schema.graphqls
  • router-tests/security/costs_test.go
  • router-tests/testenv/testdata/config.json

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
demo/pkg/subgraphs/employees/subgraph/schema.graphqls (1)

281-281: Consider documenting why negative field cost is intentional.

Line 281 uses @cost(weight: -3), which is easy to misread as accidental. A short inline comment near this field (or the input type) would help prevent future “cleanup” removals.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@demo/pkg/subgraphs/employees/subgraph/schema.graphqls` at line 281, The field
'title: String `@cost`(weight: -3)' uses a negative cost which can be mistaken for
an accidental typo; add a short inline comment or description near the 'title'
field (or the input/type that contains it) explaining why a negative
`@cost`(weight: -3) is intentional (e.g., compensates for other expensive fields,
balances query cost model, or enables specific query patterns) so future
maintainers won't remove or "clean up" the negative value; reference the 'title'
field and the '@cost' directive when adding this documentation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@demo/pkg/subgraphs/employees/subgraph/schema.graphqls`:
- Line 281: The field 'title: String `@cost`(weight: -3)' uses a negative cost
which can be mistaken for an accidental typo; add a short inline comment or
description near the 'title' field (or the input/type that contains it)
explaining why a negative `@cost`(weight: -3) is intentional (e.g., compensates
for other expensive fields, balances query cost model, or enables specific query
patterns) so future maintainers won't remove or "clean up" the negative value;
reference the 'title' field and the '@cost' directive when adding this
documentation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f49d8099-941d-40c6-9346-583af270b8ad

📥 Commits

Reviewing files that changed from the base of the PR and between b3b1b53 and 1bfe3c4.

⛔ Files ignored due to path filters (1)
  • demo/pkg/subgraphs/employees/subgraph/generated/generated.go is excluded by !**/generated/**
📒 Files selected for processing (3)
  • demo/pkg/subgraphs/employees/subgraph/schema.graphqls
  • router-tests/security/costs_test.go
  • router-tests/testenv/testdata/config.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • router-tests/security/costs_test.go

…1-cost-handle-recursion-for-arguments-containing-input-objects
…1-cost-handle-recursion-for-arguments-containing-input-objects
@ysmolski ysmolski merged commit 2ca7b28 into main Apr 8, 2026
55 of 56 checks passed
@ysmolski ysmolski deleted the yury/eng-8731-cost-handle-recursion-for-arguments-containing-input-objects branch April 8, 2026 12:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants