.Net6 + GraphQL + MongoDb 中间件

介绍

本节来看一下GraphQL中间件的写法

正文

新增TimeoutMiddleware中间件,GraphQL中间件没有约束接口。该示例中间件的主要作用是检查 GraphQL 不包含在HashSet中的hashvalue接口,就使用
配置的ExecutionTimeout时间来定义接口超时。超时后返回一个错误消息,以便客户端可以得知超时情况。

   public class TimeoutMiddleware
    {   
        
        private readonly HotChocolate.Execution.RequestDelegate _next;
        private readonly TimeSpan _standardTimeout;

        private static readonly TimeSpan _extendedTimeout = TimeSpan.FromSeconds(30);
        private readonly HashSet<string> _specialQueries = new() { "9n/8UkfQWTolxOBgUPZ2oA1==" };

        public TimeoutMiddleware(
            HotChocolate.Execution.RequestDelegate next,
            IRequestExecutorOptionsAccessor options)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
            _next = next ?? throw new ArgumentNullException("next");
            _standardTimeout = options.ExecutionTimeout;
        }


        public async ValueTask InvokeAsync(IRequestContext context)
        {
            //if (Debugger.IsAttached)
            //{
            //    await _next(context).ConfigureAwait(continueOnCapturedContext: false);
            //    return;
            //}

            Console.WriteLine(context.Request.QueryHash);

            using CancellationTokenSource timeout = new CancellationTokenSource(context.Request.QueryHash is not null &&
                _specialQueries.Contains(context.Request.QueryHash)
                    ? _extendedTimeout
                    : _standardTimeout);

            CancellationTokenSource combined = CancellationTokenSource.CreateLinkedTokenSource(context.RequestAborted, timeout.Token);

            try
            {
                context.RequestAborted = combined.Token;
                await _next(context).ConfigureAwait(continueOnCapturedContext: false);
                if (timeout.IsCancellationRequested)
                {
                    context.Result = QueryResultBuilder.CreateError(
                        new Error(string.Format("Timed out {0}.", _standardTimeout), "HC0045"));
                }
            }
            catch (OperationCanceledException)
            {
                if (!timeout.IsCancellationRequested)
                {
                    throw;
                }
                context.Result = QueryResultBuilder.CreateError(
                    new Error(string.Format("Timed out {0}.", _standardTimeout), "HC0045"));
            }
            finally
            {
                IResponseStream responseStream = context.Result as IResponseStream;
                if (responseStream != null)
                { 
                    responseStream.RegisterDisposable(combined);
                }
                else
                {
                    combined.Dispose();
                }
            }


        }
    }

修改Program注册上面的中间件,这里展示下默认给我们附加了那些中间件(我们也可以使用默认提供的UseTimeout来实现)。


    // 接口响应时间不能大于1秒
    .ModifyRequestOptions(t => t.ExecutionTimeout = TimeSpan.FromSeconds(1))
    .UseExceptions()
    .UseRequest<TimeoutMiddleware>()
    //.UseTimeout()
    .UseDocumentCache()
    .UseDocumentParser()
    .UseDocumentValidation()
    .UseOperationCache()
    .UseOperationComplexityAnalyzer()
    .UseOperationResolver()
    .UseOperationVariableCoercion()
    .UseOperationExecution()

93

结语

本系列主要将GraphQL的使用,示例项目不能应用于生产,后续发一些GraphQL库出来讲解生产中的实际应用

联系作者:加群:867095512 @MrChuJiu

posted @ 2023-02-16 13:19  初久的私房菜  阅读(11872)  评论(0编辑  收藏  举报
作者:初久的私房菜
好好学习,天天向上
返回顶部小火箭
好友榜:
如果愿意,把你的博客地址放这里
张弛:https://blog.zhangchi.fun/