[Fusion] Support request batching for legacy servers#9050
[Fusion] Support request batching for legacy servers#9050tobias-tengler merged 12 commits intomainfrom
Conversation
f0ed0bb to
1210547
Compare
8278308 to
440bb87
Compare
There was a problem hiding this comment.
Pull request overview
This pull request adds support for Apollo request batching (legacy servers) to the HotChocolate Fusion GraphQL gateway. The main objective is to enable compatibility with older GraphQL servers that use the traditional array-based batching format instead of the newer JSONL/SSE streaming formats.
Changes:
- Added
SourceSchemaHttpClientBatchingModeenum to support both variable batching and Apollo request batching modes - Implemented
JsonResultEnumerableto parse both single JSON objects and JSON arrays in responses - Modified the JSON parser to support early termination when parsing individual objects from arrays
- Updated test infrastructure to support batching configuration and validation
Reviewed changes
Copilot reviewed 77 out of 80 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
SourceSchemaHttpClientConfiguration.cs |
Added batching mode configuration and Accept header management for different request types |
SourceSchemaHttpClientBatchingMode.cs |
New enum defining batching modes (VariableBatching, ApolloRequestBatching) |
SourceSchemaHttpClient.cs |
Implemented Apollo request batching support using OperationBatchRequest |
JsonResultEnumerable.cs |
New reader for parsing JSON array responses from legacy servers |
SourceResultDocument.Parse.cs |
Added early exit support for parsing individual documents from arrays |
SourceSchemaResult.cs |
Optimized error property access by caching during construction |
SseEventParser.cs |
Fixed line ending calculation (contains bugs) |
SseReader.cs |
Fixed buffer cleanup order (contains bugs) |
LookupTests.cs |
Added comprehensive tests for all batching modes |
| Migration documentation | Added TODO for documenting JSONL response format change |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
e2f76f3 to
2e266b6
Compare
🚀 Fusion Gateway Performance ResultsSimple Composite QueryConstant Load (50 VUs)
📊 Response Time Metrics
Ramping Load (0→50→500→50 VUs)
📊 Response Time Metrics
Executed Query fragment User on User {
id
username
name
}
fragment Review on Review {
id
body
}
fragment Product on Product {
inStock
name
price
shippingEstimate
upc
weight
}
query TestQuery {
topProducts(first: 5) {
...Product
reviews {
...Review
author {
...User
}
}
}
}Deep Recursion QueryConstant Load (50 VUs)
📊 Response Time Metrics
Ramping Load (0→50→500→50 VUs)
📊 Response Time Metrics
Executed Query fragment User on User {
id
username
name
}
fragment Review on Review {
id
body
}
fragment Product on Product {
inStock
name
price
shippingEstimate
upc
weight
}
query TestQuery {
users {
...User
reviews {
...Review
product {
...Product
reviews {
...Review
author {
...User
reviews {
...Review
product {
...Product
}
}
}
}
}
}
}
topProducts(first: 5) {
...Product
reviews {
...Review
author {
...User
reviews {
...Review
product {
...Product
}
}
}
}
}
}Variable Batching ThroughputConstant Load (50 VUs)
📊 Response Time Metrics
Ramping Load (0→50→500→50 VUs)
📊 Response Time Metrics
Executed Query query TestQuery_8f7a46ce_2(
$__fusion_1_upc: ID!
$__fusion_2_price: Long!
$__fusion_2_weight: Long!
) {
productByUpc(upc: $__fusion_1_upc) {
inStock
shippingEstimate(weight: $__fusion_2_weight, price: $__fusion_2_price)
}
}Variables (5 sets batched in single request) [
{ "__fusion_1_upc": "1", "__fusion_2_price": 899, "__fusion_2_weight": 100 },
{ "__fusion_1_upc": "2", "__fusion_2_price": 1299, "__fusion_2_weight": 1000 },
{ "__fusion_1_upc": "3", "__fusion_2_price": 15, "__fusion_2_weight": 20 },
{ "__fusion_1_upc": "4", "__fusion_2_price": 499, "__fusion_2_weight": 100 },
{ "__fusion_1_upc": "5", "__fusion_2_price": 1299, "__fusion_2_weight": 1000 }
]No baseline data available for comparison. Run 21728317158 • Commit 5d71413 • Thu, 05 Feb 2026 21:20:06 GMT |
🚀 Fusion Gateway Performance ResultsSimple Composite QueryConstant Load (50 VUs)
📊 Response Time Metrics
Ramping Load (0→50→500→50 VUs)
📊 Response Time Metrics
Executed Query fragment User on User {
id
username
name
}
fragment Review on Review {
id
body
}
fragment Product on Product {
inStock
name
price
shippingEstimate
upc
weight
}
query TestQuery {
topProducts(first: 5) {
...Product
reviews {
...Review
author {
...User
}
}
}
}Deep Recursion QueryConstant Load (50 VUs)
📊 Response Time Metrics
Ramping Load (0→50→500→50 VUs)
📊 Response Time Metrics
Executed Query fragment User on User {
id
username
name
}
fragment Review on Review {
id
body
}
fragment Product on Product {
inStock
name
price
shippingEstimate
upc
weight
}
query TestQuery {
users {
...User
reviews {
...Review
product {
...Product
reviews {
...Review
author {
...User
reviews {
...Review
product {
...Product
}
}
}
}
}
}
}
topProducts(first: 5) {
...Product
reviews {
...Review
author {
...User
reviews {
...Review
product {
...Product
}
}
}
}
}
}Variable Batching ThroughputConstant Load (50 VUs)
📊 Response Time Metrics
Ramping Load (0→50→500→50 VUs)
📊 Response Time Metrics
Executed Query query TestQuery_8f7a46ce_2(
$__fusion_1_upc: ID!
$__fusion_2_price: Long!
$__fusion_2_weight: Long!
) {
productByUpc(upc: $__fusion_1_upc) {
inStock
shippingEstimate(weight: $__fusion_2_weight, price: $__fusion_2_price)
}
}Variables (5 sets batched in single request) [
{ "__fusion_1_upc": "1", "__fusion_2_price": 899, "__fusion_2_weight": 100 },
{ "__fusion_1_upc": "2", "__fusion_2_price": 1299, "__fusion_2_weight": 1000 },
{ "__fusion_1_upc": "3", "__fusion_2_price": 15, "__fusion_2_weight": 20 },
{ "__fusion_1_upc": "4", "__fusion_2_price": 499, "__fusion_2_weight": 100 },
{ "__fusion_1_upc": "5", "__fusion_2_price": 1299, "__fusion_2_weight": 1000 }
]No baseline data available for comparison. Run 21742617996 • Commit 42cb921 • Fri, 06 Feb 2026 07:53:49 GMT |
Adds a new setting to enable request batching to communicate with legacy servers to the
schema-settings.json:{ "name": "products", "transports": { "http": { "url": "...", "batchingMode": "REQUEST_BATCHING" } } }Batching is disabled by default since Hot Chocolate v13, so you'll have to enable this in your subgraphs: