问题
有许多指南可用于处理苦艾酒中的错误元组,但对于异常几乎为零。
这一点很重要,因为始终存在一些不可忽视的问题,这些问题可能会引发异常并返回不符合图形响应/错误规范的响应。如果GraphQL客户端(如阿波罗 )自动批处理请求,而一个查询中的异常会使整个BEAM进程崩溃,导致所有查询失败,这就会特别麻烦。
现有办法
我的第一个想法是使用中间件将解析器封装在try/rescue块中,我遇到的唯一两个链接也提出了类似的方法:
- Ben Wilson, one of the creators of Absinthe, recommends replacing the `Resolution` middleware with a custom one that executes the resolver in a `try` block
- This would not handle exceptions in other middleware (but maybe that's how it should be)
- Tries to do the same thing, but doesn't follow the `Absinthe.Middleware` behaviour spec
- Instead wraps all existing middleware in anonymous functions
- We also lose insight into the enabled middleware and their configs when inspecting them because of this
我的解决方案
我的方法有点受博客文章的启发,但我尝试遵循这种行为,使用中间件元组规范,而不是匿名函数:
中间件定义:
defmodule MyApp.ExceptionMiddleware do
@behaviour Absinthe.Middleware
@default_error {:error, :internal_server_error}
@default_config []
@spec wrap(Absinthe.Middleware.spec()) :: Absinthe.Middleware.spec()
def wrap(middleware_spec) do
{__MODULE__, [handle: middleware_spec]}
end
@impl true
def call(resolution, handle: middleware_spec) do
execute(middleware_spec, resolution)
rescue
error ->
Sentry.capture_exception(error, __STACKTRACE__)
Absinthe.Resolution.put_result(resolution, @default_error)
end
# Handle all the ways middleware can be defined
defp execute({{module, function}, config}, resolution) do
apply(module, function, [resolution, config])
end
defp execute({module, config}, resolution) do
apply(module, :call, [resolution, config])
end
defp execute(module, resolution) when is_atom(module) do
apply(module, :call, [resolution, @default_config])
end
defp execute(fun, resolution) when is_function(fun, 2) do
fun.(resolution, @default_config)
end
end在模式中应用它:
在所有查询/变异中间件上调用wrap/1方法。
def middleware(middleware, _field, %{identifier: type}) when type in [:query, :mutation] do
Enum.map(middleware, &ExceptionMiddleware.wrap/1)
end结果:
它将它们转换为:
[
{ExceptionMiddleware, handle: {AuthMiddleware, [access: :admin]}},
{ExceptionMiddleware, handle: {{Resolution, :call}, &some_resolver/3}},
{ExceptionMiddleware, handle: {Subscription, []}},
{ExceptionMiddleware, handle: &anon_middleware/2},
]问题(S)
我对我的方法仍然没有完全的信心,因为这感觉有点烦琐,而且滥用了苦艾酒的中间件。所以,我有兴趣得到以下几个问题的答案:
Absinthe.Resolution中间件是有意义的吗?https://stackoverflow.com/questions/57491077
复制相似问题