ChilliCream / graphql-platform

Welcome to the home of the Hot Chocolate GraphQL server for .NET, the Strawberry Shake GraphQL client for .NET and Banana Cake Pop the awesome Monaco based GraphQL IDE.
https://chillicream.com
MIT License
5.27k stars 748 forks source link

No data if one of mutation throw an exception #5514

Closed tr4cks closed 2 years ago

tr4cks commented 2 years ago

Is there an existing issue for this?

Describe the bug

If I make a request with several mutations but one of them throws an exception then the data of the other mutations cannot be retrieved even though they were executed correctly. It poses a serious problem because we have no way of knowing if the other mutations were successful or not (modification of the database...) The only way to get around this problem is to define the return type as nullable which is not at all suitable. This problem also applies to queries.

Steps to reproduce

  1. Create .net project with this file
    
    var builder = WebApplication.CreateBuilder(args);

builder.Services .AddGraphQLServer() .AddMutationType() .AddQueryType();

var app = builder.Build();

app.MapGraphQL();

app.Run();

public class Query { public string Status() { return "OK"; } }

public class Mutation { public string WithoutException() { Console.WriteLine("is executed"); return "OK"; }

public string ThrowException()
{
    throw new Exception();
    return "OK";
}

}


2. Execute this request
```graphql
mutation {
  withoutException
  throwException
}

Relevant log output

{
  "errors": [
    {
      "message": "Unexpected Execution Error",
      "locations": [
        {
          "line": 3,
          "column": 3
        }
      ],
      "path": [
        "throwException"
      ]
    }
  ]
}

Additional Context?

No response

Product

Hot Chocolate

Version

12.15.0

PascalSenn commented 2 years ago

The only way to get around this problem is to define the return type as nullable which is not at all suitable.

This is a feature of graphql called null propagation and is part of the spec and cannot (and should not) be tampered with. If the return type is non nullable then you have to provide a value.

But there are several patterns in HotChocolate that you can use to help you with this problem.

  1. Create a Transaction Scope around all the mutations to ensure that either ALL or NON of them execute correctly: https://chillicream.com/docs/hotchocolate/v12/defining-a-schema/mutations/#transactions
  2. Use mutation conventions for input and payloads: https://chillicream.com/docs/hotchocolate/v12/defining-a-schema/mutations/#conventions

The second one is highly recommended. If you use mutations conventions you follow the input/payload pattern which is defacto standard by now.