.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()
结语
本系列主要将GraphQL的使用,示例项目不能应用于生产,后续发一些GraphQL库出来讲解生产中的实际应用
联系作者:加群:867095512 @MrChuJiu