首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >处理Absinthe中的异常

处理Absinthe中的异常
EN

Stack Overflow用户
提问于 2019-08-14 08:38:46
回答 1查看 613关注 0票数 3

问题

有许多指南可用于处理苦艾酒中的错误元组,但对于异常几乎为零。

这一点很重要,因为始终存在一些不可忽视的问题,这些问题可能会引发异常并返回不符合图形响应/错误规范的响应。如果GraphQL客户端(如阿波罗 )自动批处理请求,而一个查询中的异常会使整个BEAM进程崩溃,导致所有查询失败,这就会特别麻烦。

现有办法

我的第一个想法是使用中间件将解析器封装在try/rescue块中,我遇到的唯一两个链接也提出了类似的方法:

代码语言:javascript
复制
- 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)

代码语言:javascript
复制
- 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

我的解决方案

我的方法有点受博客文章的启发,但我尝试遵循这种行为,使用中间件元组规范,而不是匿名函数:

中间件定义:

代码语言:javascript
复制
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方法。

代码语言:javascript
复制
def middleware(middleware, _field, %{identifier: type}) when type in [:query, :mutation] do
  Enum.map(middleware, &ExceptionMiddleware.wrap/1)
end

结果:

它将它们转换为:

代码语言:javascript
复制
[
  {ExceptionMiddleware, handle: {AuthMiddleware, [access: :admin]}},
  {ExceptionMiddleware, handle: {{Resolution, :call}, &some_resolver/3}},
  {ExceptionMiddleware, handle: {Subscription, []}},
  {ExceptionMiddleware, handle: &anon_middleware/2},
]

问题(S)

我对我的方法仍然没有完全的信心,因为这感觉有点烦琐,而且滥用了苦艾酒的中间件。所以,我有兴趣得到以下几个问题的答案:

  • 还有其他可能的办法吗?使用Absinthe中间件到底是正确的选择吗?
  • 如果是这样,那么包装所有中间件还是只替换Absinthe.Resolution中间件是有意义的吗?
  • 那么标准的方法是什么呢?
EN

回答 1

Stack Overflow用户

发布于 2019-08-30 12:29:23

德西夫,我们使用一个名为失当的内部工具来处理异常和错误。这可能对你有用。

https://github.com/Decisiv/blunder-absinthe

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57491077

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档