首页 > 解决方案 > GraphQL .NET:单例模式的中间件问题

问题描述

我在 .NET 核心网站/控制器上使用 GraphQL。架构非常大,因此构造函数需要大约一秒钟的时间才能运行。我不能在每个请求上都有这种开销,所以我将模式创建为一个单例,在所有请求之间共享。

    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);
      // ...
    }

这在大多数情况下都有效,但它会导致中间件出现随机问题。有时中间件会开始为每个元素运行两次,这通常会在中间件第二次运行时导致错误。

标签: graphql-dotnet

解决方案


查看源代码,似乎中间件在请求的生命周期中被应用于模式,然后我猜想最后以某种方式回滚?至少我假设这就是public void ApplyTo(ISchema schema)成员的使用方式,尽管我不确定“回滚”部分是如何发生的。

这让我知道了如何通过将中间件拉出视图并将其放入模式构造函数来解决问题,如下所示:

    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);
        }
    }

所以现在中间件在构造单例时直接烘焙到模式中,控制器不需要做任何事情。

这似乎已经完全解决了这个问题。我不确定 graphql-dotnet 中是否还有其他东西会在请求生命周期中改变模式。如果有人知道单例模式可能出现的任何其他问题,我很想听听!


推荐阅读