Skip to content

[RFC] 增加 ExceptionFilter 机制,统一异常处理流 #28

@noahziheng

Description

@noahziheng

初版 Spec 中,我们约定了 Exception 的声明、抛出机制;
但捕获一节仅保留了临时的 onerror 实现,受制于 Koa 执行机制,并不完善,因此并未直接实现。

在上层框架开发实践中,我们发现,对于用户需要关注的异常大致有两类:

  • 作用域在 Singleton 的异常
    • 通常在生命周期中抛出
    • 大多会被/有机会被显式 try-catch
    • 剩余需要被框架主动处理(通常是:打点、打日志、通知 Daemon、退出进程)
  • 作用域在 Execution 的异常
    • 通常在业务代码中抛出
    • 大多不适合被显式 try-catch(执行时机、代码冗余)
    • 业务需要关心并主动进行处理(通常协议有关,如返回响应状态码、JSON 错误结构体)
    • 一般与中间件有关
    • 需要提供一套命名为 ExceptionFilter 的机制来用于在执行期处理

机制需要包括:

  • 提供 Interface 用于编码实践,Filter 实体放入 IoC 容器
  • 提供基于配置的注册机制,用于执行单元获取实体信息
  • TriggerExceptionHandler 中增加公共逻辑,用于统一执行 Filter
  • 提供元信息语法糖用于处理指定错误码/错误实体的错误

需讨论的模糊问题:

  • 不希望过度冲击已有的中间件序列(有用户习惯使用中间件处理错误,且经常不抛出),思路有二:
    • 只在 Trigger 中增加特殊处理,在执行流最末尾执行 Filter
    • 增加 ExceptionHandler.throw 处理逻辑,API 抛出后立即执行 Filter(是 ExceptionHandler 设计本意)
      • 会冲击中间件序列中的 catch 逻辑
      • 为了保证 throw xxx 仍然也能正常执行,Trigger 中的 catch 仍需存在
  • 为了与中间件处理错误有所差异,不考虑引入 ctx,单个 Filter 不应关心其他 Filter,那就有可能出现多个 Filter 重复执行对协议响应的操作,有解法如下:
    • Filter 全部依序执行,为单个 Filter 提供类似 done() 的 API,主动终止执行序列(API 不优雅)
    • 规定通用的、针对单个错误码/实体的 Filter 唯一,不允许存在多个(通用性受限)

Spec 修改草案见 #27 中的 Markdown

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions