graphql-platform icon indicating copy to clipboard operation
graphql-platform copied to clipboard

Error when combined Batch operation with persisted query

Open john2094 opened this issue 3 years ago • 4 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Describe the bug

When I configured my project to work with persisted query and operation batch both at the same time, the request failed.

The expected response of this query must be the response of persisted query if has been persisted or an error response when it hasn't

[{
    "errors": [
        {
            "message": "PersistedQueryNotFound",
            "extensions": {
                "code": "HC0020"
            }
        }
    ]
},{
    "errors": [
        {
            "message": "PersistedQueryNotFound",
            "extensions": {
                "code": "HC0020"
            }
        }
    ]
},{//data of query that was already persisted}
,...]

Steps to reproduce

  1. Make a batch query with multiple persisted queryids and without query definition. eg
[
{"operationName":"MyProfile","variables":{},"extensions":{"persistedQuery":{"version":1,"sha256Hash":"2fa3cab6acbe4ad09fbf16faddd6db5ffcf4ad03173966775b971ceeb9ca704f"}}},
{"operationName":"getAudiences","variables":{},"extensions":{"persistedQuery":{"version":1,"sha256Hash":"7747363f36e24eb75cfa8ac4be37db47467b593dab6c02982eacec71b5b777a4"}}},
{"operationName":"getCountAdminUsers","variables":{},"extensions":{"persistedQuery":{"version":1,"sha256Hash":"cd811f502b0b96889fbe426dee3bc4d31c78a9ab9b1ee84e5ce1f2834c4c2c54"}}},
{"operationName":"getAdminUsers","variables":{"first":1},"extensions":{"persistedQuery":{"version":1,"sha256Hash":"c39836aefa4960d6601f03053b425dcc1d127682ab2352e8f629f30d50b75ad3"}}},
{"operationName":"getFooterMenu","variables":{},"extensions":{"persistedQuery":{"version":1,"sha256Hash":"c3c4febf4771d0fb31dc1931aa8cd9ea300e20dac58fad05d02eafb7df15d5f9"}}}
]

Relevant log output

[
    {
        "errors": [
            {
                "message": "Unexpected Execution Error",
                "extensions": {
                    "message": "Object reference not set to an instance of an object.",
                    "stackTrace": "   at HotChocolate.Execution.Batching.BatchExecutor.BatchExecutorEnumerable.ExecuteNextAsync(IReadOnlyQueryRequest request, CancellationToken cancellationToken)"
                }
            }
        ]
    }
]

Additional Context?

I realized the problem is on these lines because a Query prop was expected, but it is null.

I modified the code and verified query prop has a value before continue

if (request.Query != null || request.QueryId == null)
{
    DocumentNode document = request.Query is QueryDocument d
        ? d.Document
        : Utf8GraphQLParser.Parse(request.Query!.AsSpan());

    OperationDefinitionNode operation =
        document.GetOperation(request.OperationName);

    if (document != _previous)
    {
        _fragments = document.GetFragments();
        _visitationMap.Initialize(_fragments);
    }

    operation.Accept(
        _visitor,
        _visitationMap,
        _ => VisitorAction.Continue);

    _previous = document;
    document = RewriteDocument(operation);
    operation = (OperationDefinitionNode)document.Definitions[0];
    IReadOnlyDictionary<string, object?>? variableValues =
        MergeVariables(request.VariableValues, operation);

    request = QueryRequestBuilder.From(request)
        .SetQuery(document)
        .SetVariableValues(variableValues)
        .AddExportedVariables(_exportedVariables)
        .SetQueryId(null) // TODO ... should we create a name here?
        .SetQueryHash(null)
        .Create();
}
else
{
    request = QueryRequestBuilder.From(request)

        .SetVariableValues(request.VariableValues)
        .AddExportedVariables(_exportedVariables)
        .SetQueryId(request.QueryId)
        .SetQueryHash(null)
        .Create();
}

return (IReadOnlyQueryResult)await _requestExecutor.ExecuteAsync(
    request, cancellationToken)
    .ConfigureAwait(false);

and change this line for the following

 if (result.Data is null && result.Errors is null)
{
    break;
}


and it works as expected.

I thought to make a PR, but i'm not sure if the first if...else statement afected something else.

Thank for you help.

Product

Hot Chocolate

Version

12.11.1

john2094 avatar Jul 08 '22 17:07 john2094

I came across this issue in 12.9.0. BatchExecutor does not work with persisted queries.

Deathrage avatar Sep 05 '22 09:09 Deathrage

I think this might be dupe of #2987

Deathrage avatar Sep 05 '22 09:09 Deathrage

I am currently working on this, I hope to have the modifications ready within a week

john2094 avatar Jul 20 '23 20:07 john2094

Can this fix be merged soon? We rely exclusively on persisted queries and batching would give us a major performance increase.

Also, a big thanks to the Hot Chocolate dev team and community. It is an outstanding piece of software.

Aaron9905 avatar Feb 02 '24 12:02 Aaron9905