Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add biz handler #29

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open

feat: add biz handler #29

wants to merge 10 commits into from

Conversation

popomore
Copy link
Member

There is three case:

  1. If it's an egg error, it will format response
  2. If it's an egg exception, it will format response and log an error
  3. if it's a normal error, it will be throw that catched by onerror handler
Checklist
  • npm test passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines
Affected core subsystem(s)
Description of change

There is three case:

1. If it's an egg error, it will format response
1. If it's an egg exception, it will format response and log an error
1. if it's a normal error, it will be throw that catched by onerror handler
@popomore
Copy link
Member Author

先看看处理是否合适。

@popomore
Copy link
Member Author

非 json 的没想好怎么处理,内容协商 egg 做的不是很好。

@fengmk2
Copy link
Member

fengmk2 commented Aug 21, 2018

@popomore 非 json 的本来 koa-onerror 就已经处理的了,得复用起来。

@popomore
Copy link
Member Author

这是是在前面拦截统一处理的,onerror 就是未捕获异常的处理,所以我觉得业务异常都可以在这里提供处理的扩张。

@popomore
Copy link
Member Author

是不是提供这样的配置,让开发者明确是处理哪种类型,格式化统一只给一个 error 对象。

onerror.uncaught.formatJSON
onerror.biz.formatJSON
onerror.uncaught.formatText
onerror.biz.formatText

@codecov
Copy link

codecov bot commented Aug 22, 2018

Codecov Report

Merging #29 into master will increase coverage by 0.54%.
The diff coverage is 98%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #29      +/-   ##
==========================================
+ Coverage   96.98%   97.53%   +0.54%     
==========================================
  Files           5        6       +1     
  Lines         166      203      +37     
==========================================
+ Hits          161      198      +37     
  Misses          5        5
Impacted Files Coverage Δ
config/config.default.js 100% <ø> (ø) ⬆️
agent.js 100% <100%> (ø) ⬆️
app/middleware/egg_onerror_handler.js 100% <100%> (ø)
app.js 97.22% <96.87%> (+0.16%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4824a04...8e18cfb. Read the comment docs.

@popomore
Copy link
Member Author

代码又改了下

if (contentType === 'html' && biz.formatHtml) {
ctx.body = biz.formatHtml(err);
} else {
ctx.body = defaultFormat(err);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

defaultFormat 直接交给 koa-onerror?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

直接 throw 出来吗?

@popomore
Copy link
Member Author

popomore commented Aug 22, 2018

看看系统的是否也要加,因为这个是兜底的,如果出现了异常就会真挂掉。

还有一个纠结点是业务处理现在是无法处理默认的 Error 的,如果不提供系统的 format,那这个 error 处理只能使用 onerror 默认的了。

@fengmk2
Copy link
Member

fengmk2 commented Aug 22, 2018

应用也可以将默认的 Error 处理了。按道理应用只处理自己的异常。

config/config.default.js Outdated Show resolved Hide resolved
@fengmk2
Copy link
Member

fengmk2 commented Aug 24, 2018

@popomore 清晰多了,先将文档写出来,文档里面将3种场景都写出示例代码,从开发者角度看看整个过程是否合理。

@@ -11,4 +11,10 @@ exports.onerror = {
appErrorFilter: null,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

上面的 // 5xx error will redirect to ${errorPageUrl} 注释都需要修改一下了。

@@ -11,4 +11,10 @@ exports.onerror = {
appErrorFilter: null,
// default template path
templatePath: path.join(__dirname, '../lib/onerror_page.mustache'),
// normalize your error response from error object
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ErrorType.ERROR and ErrorType.EXCEPTION

@dead-horse
Copy link
Member

这个放在 onerror 插件里面给我的感觉还是有点奇怪,因为里面内嵌了一些 egg-errors 的逻辑,需要配套使用。我觉得还不如单独实现一个 egg-biz-error 的插件,统一提供 egg-errors 和对应的中间件处理,给用户的感知是统一的。

@dead-horse
Copy link
Member

例如在这里配置 application.formatXX 方法, 但是一些 builtin 的异常又没有按照这个格式来处理,会让人有点疑惑。

如果是新增一个 egg-biz-error 插件,所有通过插件提供的方式抛出的异常都会被这个插件处理,系统 builtin 异常不会处理,就比较合理。

egg-biz-error 插件如果接口稳定的话,也可以在 egg 中默认开启

@popomore
Copy link
Member Author

我先把文档写一下,这样比较容易理解。

@popomore
Copy link
Member Author

egg-errors 单独使用是为了让库、插件、框架、应用都可以单独依赖来使用,而不是依赖一个 egg-biz-error 的插件。

抽出 biz-error 插件做这个错误处理我觉得也没有问题,但是这个属于 egg 错误处理的核心功能,所以我觉得再抽个插件比较麻烦。

@popomore
Copy link
Member Author

例如在这里配置 application.formatXX 方法, 但是一些 builtin 的异常又没有按照这个格式来处理,会让人有点疑惑。

这个我是这样想的,builtin 异常可能出现在一些依赖库里,业务需要对其做处理,如果不做处理就认为是未捕获异常。

try {
  // 调用依赖库
} catch (err) {
  throw MyException.from(err);
}

@atian25
Copy link
Member

atian25 commented Aug 24, 2018

link 下 RFC 或文档,从使用者角度来看下,可能会更容易理解下。

@dead-horse
Copy link
Member

我理解 egg-errors 作为单独库的的目的,我的意思是如果确定下来,可以直接将 egg-errors 从 egg-core 开始内置,这样在 egg-onerror 插件里面处理 egg-errors 相关的东西就合适了。

@popomore
Copy link
Member Author

不是内置,是希望所有的错误都用这种方式封装。

@@ -11,4 +11,24 @@ exports.onerror = {
appErrorFilter: null,
// default template path
templatePath: path.join(__dirname, '../lib/onerror_page.mustache'),
// handler your error response
errorHandler: {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里重新实现了一下

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感觉这个应该是一个配置,而是约定在 app/onerror.js 文件入口。

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我感觉这里比较简单,写配置比较容易想到,约定文件太多也不是非常好。配置还有一个好处是有 dump。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

egg 的文档将使用说明写起来看看没问题就可以合并发布了。

app.js Outdated Show resolved Hide resolved
@popomore
Copy link
Member Author

我们是不是需要提供默认项,如果开启了 errorHandler 而使用默认值的时候会跟原来 onerror 的默认处理有差异。

app.js Outdated Show resolved Hide resolved
let err = e;
const errorType = EggError.getType(err);
switch (errorType) {
case ErrorType.ERROR: break;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

又看了一次代码,还是很难理解,日志什么时候该打,什么时候该使用 EggError,什么时候用 EXCEPTION 。。。

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error 是用于终端的,比如检验错误,验权,不需要打 error。exception 是系统错误,常见的 500,或者底层抛的错,需要打 error 日志。针对响应则用 errorHandler 统一处理。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

先整理个文章出来吧,这种经验实践类的功能看代码老是跟不上思路。。。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我理解的是 ERROR 是类似业务处理报错,是业务上预期的错误,EXCEPTION 是异常,非预期的程序错误,所以需要打印日志。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果是终端的,那么应该使用 ClientError 会更好,不用思考就明白了。

"stack-trace": "^0.0.10"
},
"devDependencies": {
"autod": "^3.0.0",
"autod": "^3.0.1",
"egg": "next",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

改为 ^2


class HomeController extends Controller {
async throwError() {
throw new Error('error');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ctx.throw([status], [msg], [properties])ctx.assert(value, [status], [msg], [properties]) 这 2 个对应的用法也可以加下

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个还是不要改原生了?就作为 BUILDIN 错误好了

[ 'all', 'html', 'json', 'text', 'js' ].forEach(type => {
if (config[type]) errorOptions[type] = config[type];
});
onerror(app, errorOptions);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里是不是可以再包一层,这样的话,在 custom error handler 里面,可以支持 ctx.render 的兜底处理

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants