Skip to content

Fix batch resolver in paging context#9660

Open
michaelstaib wants to merge 5 commits into
mainfrom
mst/fix-batch-resolver
Open

Fix batch resolver in paging context#9660
michaelstaib wants to merge 5 commits into
mainfrom
mst/fix-batch-resolver

Conversation

@michaelstaib

Copy link
Copy Markdown
Member

No description provided.

Copilot AI review requested due to automatic review settings May 8, 2026 21:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes batch resolver behavior when paging and node/lookup resolvers are involved, ensuring batched execution remains correct when selections use different paging arguments (and supporting batch pipelines for node resolvers). It also extends the execution scheduler to reliably dispatch root-level batch entries and updates the source generator/analyzers to correctly recognize batch connection resolvers and batch lookup patterns.

Changes:

  • Add batch-pipeline support to node resolvers and extend type interception to capture batch resolver pipelines.
  • Introduce batch middleware + partitioning for paging to correctly handle per-selection paging arguments in batched resolvers.
  • Ensure root batch entries are dispatched even when there are no non-batch root resolver tasks, and update analyzers/source generation to support new batch/connection/lookup combinations.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/HotChocolate/Data/test/Data.Tests/Pagination/PagingArgumentsParameterExpressionBuilderTests.cs Adds coverage for paging argument mapping/partitioning in batch resolvers (including PageConnection).
src/HotChocolate/Core/test/Types.Tests/Types/Relay/NodeResolverTests.cs Adds tests for node resolver behavior when the query field uses a batch resolver.
src/HotChocolate/Core/test/Types.Tests/Types/Relay/snapshots/NodeResolverTests.NodeResolver_On_Query_Field_With_BatchResolver_Schema.snap New snapshot for schema output of the new node/batch resolver test.
src/HotChocolate/Core/test/Types.Tests/Types/Relay/snapshots/NodeResolverTests.NodeResolver_On_Query_Field_With_BatchResolver_Fetch_Through_Node_Field.snap New snapshot for execution output of node field resolving through a batch resolver.
src/HotChocolate/Core/test/Types.Tests/Types/Composite/LookupTests.cs Adds schema + execution coverage for [Lookup] combined with [BatchResolver].
src/HotChocolate/Core/test/Types.Tests/Execution/BatchResolverTests.cs Adds regression test ensuring aliased field arguments are properly batched.
src/HotChocolate/Core/test/Types.Analyzers.Tests/PagingTests.cs Adds generator snapshot coverage for batch resolver returning PageConnection<T> with PagingArguments.
src/HotChocolate/Core/test/Types.Analyzers.Tests/ObjectTypeTests.cs Adds generator snapshot coverage for [Lookup] + [BatchResolver].
src/HotChocolate/Core/test/Types.Analyzers.Tests/LookupReturnsNonNullableTypeAnalyzerTests.cs Adds analyzer snapshot coverage: batch lookup returning nullable list should not warn.
src/HotChocolate/Core/test/Types.Analyzers.Tests/LookupReturnsListTypeAnalyzerTests.cs Adds analyzer snapshot coverage: batch lookup list return should not error.
src/HotChocolate/Core/test/Types.Analyzers.Tests/snapshots/PagingTests.GenerateSource_BatchResolver_PageConnection_MatchesSnapshot.md New generated-source snapshot for batch paging + connection generation.
src/HotChocolate/Core/test/Types.Analyzers.Tests/snapshots/ObjectTypeTests.BatchResolver_With_Lookup_MatchesSnapshot.md New generated-source snapshot for batch lookup generation.
src/HotChocolate/Core/test/Types.Analyzers.Tests/snapshots/LookupReturnsNonNullableTypeAnalyzerTests.Method_BatchResolverNullableListReturn_NoWarning.md New snapshot asserting no warning for batch lookup nullable list return.
src/HotChocolate/Core/test/Types.Analyzers.Tests/snapshots/LookupReturnsListTypeAnalyzerTests.Method_BatchResolverListReturn_NoError.md New snapshot asserting no error for batch lookup list return.
src/HotChocolate/Core/src/Types/Types/Relay/NodeResolverTypeInterceptor.cs Captures batch resolver pipeline when a query field doubles as a node resolver.
src/HotChocolate/Core/src/Types/Types/Relay/NodeResolverInfo.cs Extends node resolver metadata to include an optional batch pipeline.
src/HotChocolate/Core/src/Types/Types/Relay/NodeFieldResolvers.cs Executes batch pipeline when available for node resolution (single + nodes field).
src/HotChocolate/Core/src/Types/Types/Pagination/PagingHelper.cs Adds batch paging middleware and introduces paging-based batch partitioning key.
src/HotChocolate/Core/src/Types/Types/ObjectType.Initialization.cs Ensures batch partition key resolver is propagated from interface fields.
src/HotChocolate/Core/src/Types/Types/ObjectField.cs Carries batch partition key resolver into the executable ObjectField instance.
src/HotChocolate/Core/src/Types/Types/Descriptors/Configurations/ObjectFieldConfiguration.cs Stores/merges/copies the batch partition key resolver in field configuration.
src/HotChocolate/Core/src/Types/Types/Descriptors/Configurations/InterfaceFieldConfiguration.cs Stores/merges/copies the batch partition key resolver for interface fields.
src/HotChocolate/Core/src/Types/Resolvers/BatchPartitionKeyResolver.cs Introduces internal delegate type for batch partition key resolution.
src/HotChocolate/Core/src/Types/Execution/Processing/WorkScheduler.Execute.cs Flushes pending root batch entries before entering the scheduler work loop.
src/HotChocolate/Core/src/Types/Execution/Processing/Tasks/ResolverTaskFactory.cs Avoids dummy root task scheduling when only batch entries exist; avoids registering empty spans.
src/HotChocolate/Core/src/Types/Execution/Processing/Tasks/BatchResolverTask.cs Executes batch pipelines partitioned by a per-context partition key when configured.
src/HotChocolate/Core/src/Types/Execution/Processing/QueryExecutor.cs Updates scheduler entry point name (ExecuteAsync1ExecuteAsync).
src/HotChocolate/Core/src/Types.CursorPagination/Extensions/UseConnectionAttribute.cs Adds batch paging validation middleware and sets paging batch partition key resolver.
src/HotChocolate/Core/src/Types.Analyzers/Models/Resolver.cs Tracks whether a resolver is a connection resolver independent of resolver kind (incl. batch).
src/HotChocolate/Core/src/Types.Analyzers/LookupReturnsNonNullableTypeAnalyzer.cs Skips non-nullability lookup checks for batch lookup resolvers.
src/HotChocolate/Core/src/Types.Analyzers/LookupReturnsListTypeAnalyzer.cs Skips list-type lookup checks for batch lookup resolvers.
src/HotChocolate/Core/src/Types.Analyzers/Inspectors/ObjectTypeInspector.cs Detects batch connection resolvers and marks them for connection generation/flags.
src/HotChocolate/Core/src/Types.Analyzers/Inspectors/ConnectionTypeTransformer.cs Uses IsConnectionResolver and supports batch resolver return shapes for connection type inference.
src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/TypeFileBuilderBase.cs Updates generator output for connection resolvers and improves batch parameter binding (incl. paging args/flags).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +170 to +193
internal static ulong GetPagingBatchPartitionKey(IMiddlewareContext context)
{
var options = GetPagingOptions(context.Schema, context.Selection.Field);
var first = context.ArgumentValue<int?>(FirstArgumentName);
var after = context.ArgumentValue<string?>(AfterArgumentName);
int? last = null;
string? before = null;

if (options.AllowBackwardPagination ?? PagingDefaults.AllowBackwardPagination)
{
last = context.ArgumentValue<int?>(LastArgumentName);
before = context.ArgumentValue<string?>(BeforeArgumentName);
}

var flags = ConnectionFlagsHelper.GetConnectionFlags(context);

if (first is null
&& after is null
&& last is null
&& before is null
&& flags is ConnectionFlags.None)
{
return 0;
}
Generalize the engine's batch partitioner from a single delegate to an
ImmutableArray<BatchPartitionKeyResolver> and recurse through the levels in
BatchResolverTask. Each leaf partition is dispatched to the user's batch
pipeline once, preserving the all-same-key fast path at every level.

Carry the inner partition key on NodeResolverInfo so the upcoming node-level
batch resolver can honor a node-resolver source field's partitioner.
- node field uses BatchResolver + chained partitioners (typeName outer, user partitioner inner) so sibling node calls coalesce per node type and per inner partition.
- nodes field uses BatchResolver without partitioners; the resolver expands ids into per-id child contexts, groups by type, and sub-partitions by the type's inner BatchPartitionKey before invoking BatchPipeline.
- ResolveNodeBatchAsync / ResolveNodesBatchAsync replace the per-context middleware shims.
# Conflicts:
#	.gitignore
#	src/HotChocolate/Core/src/Types.Analyzers/Inspectors/ObjectTypeInspector.cs
#	src/HotChocolate/Core/src/Types.Analyzers/Models/Resolver.cs
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