1

I'm using GraphQL on a .NET core website/controller. The schema is quite large, such that the constructor takes about a second to run. I couldn't have that kind of overhead on every request, so I created the schema as a singleton, shared between all requests.

    public async Task<IActionResult> Post([FromBody] GraphQLQuery query)
    {
      var executionOptions = new ExecutionOptions { 
        Schema = this.Schema, // dependency injected singleton
        /* ... */
      };
      // ...
      executionOptions.FieldMiddleware.Use(next => context =>
      {
          return  next(context).ContinueWith(x=> {
            var result = x.Result;
            return doStuff(result);
          });
      });

      var result = await new DocumentExecuter().ExecuteAsync(executionOptions).ConfigureAwait(false);
      // ...
    }

This worked most of the time, but it caused random problems with the middleware. Sometimes the middleware would start running twice for each element, which would usually cause an error the second time the middleware ran.

David784
  • 7,031
  • 2
  • 22
  • 29

1 Answers1

2

Looking at the source, it appears the middleware is being applied to the schema during the life cycle of a request, and then somehow rolled back at the end I guess? At least I'm assuming that's how the public void ApplyTo(ISchema schema) member is being used, although I'm not sure how the "rollback" part was happening.

This gave me an idea of how to solve the problem by pulling the middleware out of the view and put it in the schema constructor, like this:

    public class MySchema : Schema
    {
        public MySchema()
        {
            this.Query = new MyQuery();
            this.Mutation = new MyMutation();

            var builder = new FieldMiddlewareBuilder();
            builder.Use(next => context =>
            {
              return  next(context).ContinueWith(x=> {
                var result = x.Result;
                return doStuff(result);
              });
            });
            builder.ApplyTo(this);
        }
    }

So now the middleware is baked directly into the schema when the singleton is constructed, and the controller doesn't have to do anything.

This appears to have completely solved the problem. I'm not sure if there are other things in graphql-dotnet that mutate the schema during the request life cycle. If anyone knows of any other problems that might occur with a singleton schema I'd love to hear it!

David784
  • 7,031
  • 2
  • 22
  • 29