Skip to content

Conversation

@ardatan
Copy link
Member

@ardatan ardatan commented Jun 25, 2025

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Summary of Changes

Hello @ardatan, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors the GraphQL response serialization process by moving away from serde_json's preserve_order feature. It introduces a new, custom projection and serialization layer that directly constructs the JSON response string, ensuring field order based on the GraphQL selection set. This change aims to improve performance and maintain strict adherence to GraphQL response ordering specifications.

Highlights

  • Custom GraphQL Response Serialization: Introduced a new projection module (lib/query-plan-executor/src/projection.rs) that handles the serialization of GraphQL response data directly into a JSON string. This new logic ensures that fields are ordered according to the GraphQL selection set, replacing the previous reliance on serde_json's preserve_order feature.
  • Dependency Simplification: The preserve_order feature has been removed from serde_json dependencies across bin/dev-cli, bin/gateway, and lib/query-plan-executor's Cargo.toml files. This simplifies the dependency tree and removes the need for indexmap as a transitive dependency.
  • Performance Optimization: The new projection logic directly serializes the GraphQL response to a string, avoiding intermediate serde_json::Value allocations. This change is expected to improve the overall performance of response generation.
  • Refactored Execution Flow: The execute_query_plan function in lib/query-plan-executor/src/lib.rs now returns the final serialized JSON string directly. Logic for adding queryPlan extensions and handling introspection data has been integrated into the new projection mechanism, streamlining the response pipeline.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link

github-actions bot commented Jun 25, 2025

Federation Audit Results

189 tests   189 ✅  3s ⏱️
 42 suites    0 💤
 42 files      0 ❌

Results for commit 757a21c.

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Jun 25, 2025

TestsPassed ✅SkippedFailedTime ⏱
federation-audit | abstract-types.xml18 ran18 ✅514ms
federation-audit | child-type-mismatch.xml4 ran4 ✅101ms
federation-audit | circular-reference-interface.xml2 ran2 ✅43ms
federation-audit | complex-entity-call.xml1 ran1 ✅90ms
federation-audit | corrupted-supergraph-node-id.xml10 ran10 ✅134ms
federation-audit | enum-intersection.xml5 ran5 ✅76ms
federation-audit | fed1-external-extends-resolvable.xml1 ran1 ✅26ms
federation-audit | fed1-external-extends.xml4 ran4 ✅66ms
federation-audit | fed1-external-extension.xml4 ran4 ✅68ms
federation-audit | fed2-external-extends.xml4 ran4 ✅70ms
federation-audit | fed2-external-extension.xml4 ran4 ✅74ms
federation-audit | include-skip.xml4 ran4 ✅89ms
federation-audit | input-object-intersection.xml3 ran3 ✅39ms
federation-audit | interface-object-indirect-extension.xml1 ran1 ✅59ms
federation-audit | interface-object-with-requires.xml7 ran7 ✅111ms
federation-audit | keys-mashup.xml1 ran1 ✅32ms
federation-audit | mutations.xml4 ran4 ✅95ms
federation-audit | mysterious-external.xml2 ran2 ✅41ms
federation-audit | nested-provides.xml2 ran2 ✅37ms
federation-audit | node.xml1 ran1 ✅28ms
federation-audit | non-resolvable-interface-object.xml7 ran7 ✅78ms
federation-audit | null-keys.xml1 ran1 ✅31ms
federation-audit | override-type-interface.xml4 ran4 ✅76ms
federation-audit | override-with-requires.xml4 ran4 ✅93ms
federation-audit | parent-entity-call-complex.xml1 ran1 ✅36ms
federation-audit | parent-entity-call.xml1 ran1 ✅29ms
federation-audit | provides-on-interface.xml2 ran2 ✅43ms
federation-audit | provides-on-union.xml2 ran2 ✅40ms
federation-audit | requires-interface.xml5 ran5 ✅83ms
federation-audit | requires-requires.xml5 ran5 ✅112ms
federation-audit | requires-with-argument.xml5 ran5 ✅107ms
federation-audit | requires-with-fragments.xml6 ran6 ✅102ms
federation-audit | shared-root.xml2 ran2 ✅44ms
federation-audit | simple-entity-call.xml1 ran1 ✅25ms
federation-audit | simple-inaccessible.xml4 ran4 ✅61ms
federation-audit | simple-interface-object.xml13 ran13 ✅185ms
federation-audit | simple-override.xml2 ran2 ✅39ms
federation-audit | simple-requires-provides.xml12 ran12 ✅188ms
federation-audit | typename.xml6 ran6 ✅97ms
federation-audit | unavailable-override.xml2 ran2 ✅34ms
federation-audit | union-interface-distributed.xml10 ran10 ✅114ms
federation-audit | union-intersection.xml12 ran12 ✅227ms

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request removes the preserve_order feature from serde_json and introduces custom serialization logic to ensure the GraphQL response fields are ordered according to the selection set.

The review identified several critical and high-severity issues in the new serialization code:

  • Critical: The custom JSON serialization logic does not escape string values and object keys, which will lead to invalid JSON for certain inputs.
  • High: There are several uses of .unwrap() on serialization results, which could cause the gateway to panic and crash.

These issues should be addressed to ensure the stability and correctness of the gateway.

@github-actions
Copy link

github-actions bot commented Jun 25, 2025

k6-benchmark results

     ✓ response code was 200
     ✓ no graphql errors
     ✓ valid response structure

     █ setup

     checks.........................: 100.00% ✓ 25272      ✗ 0   
     data_received..................: 742 MB  25 MB/s
     data_sent......................: 9.9 MB  328 kB/s
     http_req_blocked...............: avg=28.54µs  min=862ns   med=2.08µs   max=9.19ms   p(90)=3.28µs   p(95)=3.77µs  
     http_req_connecting............: avg=24.05µs  min=0s      med=0s       max=9.15ms   p(90)=0s       p(95)=0s      
     http_req_duration..............: avg=175.63ms min=3.48ms  med=175.07ms max=354.93ms p(90)=215.28ms p(95)=230.54ms
       { expected_response:true }...: avg=175.63ms min=3.48ms  med=175.07ms max=354.93ms p(90)=215.28ms p(95)=230.54ms
     http_req_failed................: 0.00%   ✓ 0          ✗ 8444
     http_req_receiving.............: avg=627.93µs min=36.81µs med=79.04µs  max=152.56ms p(90)=2.15ms   p(95)=3.3ms   
     http_req_sending...............: avg=79.79µs  min=7.36µs  med=13.79µs  max=18.4ms   p(90)=23.32µs  p(95)=37.85µs 
     http_req_tls_handshaking.......: avg=0s       min=0s      med=0s       max=0s       p(90)=0s       p(95)=0s      
     http_req_waiting...............: avg=174.92ms min=3.43ms  med=174.49ms max=344.14ms p(90)=214.63ms p(95)=229.45ms
     http_reqs......................: 8444    279.615842/s
     iteration_duration.............: avg=178.42ms min=38.22ms med=175.56ms max=702.97ms p(90)=215.8ms  p(95)=231.12ms
     iterations.....................: 8424    278.953559/s
     vus............................: 50      min=50       max=50
     vus_max........................: 50      min=50       max=50

@github-actions
Copy link

github-actions bot commented Jun 26, 2025

GraphQL over HTTP Audit Results

61 tests   61 ✅  0s ⏱️
 1 suites   0 💤
 1 files     0 ❌

Results for commit 3279e86.

♻️ This comment has been updated with latest results.

@graphql-hive graphql-hive deleted a comment from github-actions bot Jun 26, 2025
@ardatan ardatan force-pushed the no-preserve-order branch from 444ee6d to 3ac33e2 Compare June 27, 2025 10:33
@ardatan ardatan changed the title No preserve order, serialize the response using selection set in order Perf improvements Jun 27, 2025
@ardatan ardatan force-pushed the no-preserve-order branch 6 times, most recently from b4ca892 to 3279e86 Compare July 3, 2025 10:29
@ardatan ardatan force-pushed the no-preserve-order branch 3 times, most recently from 151a9fc to b728374 Compare July 9, 2025 12:54
@ardatan ardatan force-pushed the no-preserve-order branch 3 times, most recently from bdd3056 to 64dae35 Compare July 18, 2025 10:42
@ardatan ardatan marked this pull request as ready for review July 21, 2025 10:09
ardatan and others added 20 commits July 21, 2025 13:09
The previous version was never reaching primitive cases because for
primitives selection is empty already.
This fixes that so it uses our serialization instead of serde_json.
…ions in project_requires (#211)

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
…ion (#220)

Also merged this into this PR by accident  #221
Sorry :/

---------

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
Also includes #226 & #229 & #245

---------

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
@ardatan ardatan force-pushed the no-preserve-order branch from 2f95327 to 757a21c Compare July 21, 2025 10:09
@ardatan ardatan changed the title Perf improvements Performance improvements Jul 21, 2025
ardatan added 2 commits July 21, 2025 14:51
#287)

`HttpRequestParams` service clones stuff from `req` object which already
has all the details. Instead we can extract those only when we need it
from `req` using `trait`s as in this PR

- Now PipelineError is created by a method of Request named
`new_pipeline_error` that extract accept header inside.
- PipelineErrorVariant -> PipelineError conversion is removed because it
is error-prone to create a PipelineError without accept header.
`req.new_pipeline_error` method is encouraged
- Avoid copying accept header value, and check the accept header value
in place
Copy link
Member

@dotansimha dotansimha left a comment

Choose a reason for hiding this comment

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

Overall the changes in this PR are great and pushing us in the direction we wanted.

I would like to ask you to check if you can optimize and refactor the main lib.rs in this PR.
The main concern I have now is the fact that we have different way of handling the PlanNode variants in different cases (root? child? inside flatten?)

I feel like a better implementation will have to deal with this in a recursive/queue-link way, and deal with each kind of node just once. Currently, there are too many places where we have "special" handling, and it make the code messy.

@ardatan ardatan merged commit c3e8a2b into main Jul 23, 2025
10 checks passed
@ardatan ardatan deleted the no-preserve-order branch July 23, 2025 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use serde_json::Map without preserve_order

3 participants