Skip to content

Commit

Permalink
feat: support boot hook and add boot hook doc
Browse files Browse the repository at this point in the history
Refs: #2520
  • Loading branch information
killagu committed Sep 6, 2018
1 parent a2df5ad commit 5fd83d0
Show file tree
Hide file tree
Showing 9 changed files with 294 additions and 0 deletions.
131 changes: 131 additions & 0 deletions docs/lifecyle.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
@startuml
start
: start master;
partition agent {
: fork agent worker;
: load plugin.js, config.js, extends;
: load agent.js;
note right
类模式
configDidLoad
async didLoad
async willReady
async didReady
async serverDidReady
====
方法模式
beforeStart(deprecate)
end note
fork
: configDidLoad;
note left
文件都已经加载完成,
可以执行一些同步逻辑
end note
: async didLoad;
note left
文件, 配置已经加载完毕,
可以执行一些异步任务,
比如异步拉取配置来加载client,
或者检查client状态是否正常
end note
fork again
: beforeStart(deprecate);
note right
beforeStart注册的任务
在此时同时并行执行
end note
endfork
: async willReady;
note left
插件已经完全加载完毕,
所有的插件可以正常的使用,
执行一些流量进入前的任务,
比如拉取应用所需的一些配置
end note
: async didReady;
note right
agent进程已经准备完毕,
可以正常工作
====
时间点与原来的ready相同,
原来的ready不支持AsyncFunction
end note
: emit 'agent-start';
}
partition app {
: start app workers;
: load plugin.js, config.js, extends;
: load app.js;
note right
类模式
configDidLoad
async didLoad
async willReady
async didReady
async serverDidReady
====
方法模式
beforeStart(deprecate)
end note
fork
: configDidLoad;
note left
文件都已经加载完成,
与 app.js 里的同步逻辑相同,
可以修改一些配置, 修改中间件的顺序
end note
: load app/service;
: load app/middleware;
: load app/controller;
: load app/router.js;
: async DidLoad;
note left
文件, 配置已经加载完毕,
可以执行一些异步任务,
比如异步拉取配置来加载client,
或者检查client状态是否正常
end note
fork again
: beforeStart(deprecate);
note right
beforeStart注册的任务
在此时同时并行执行
end note
end fork
: async WillReady;
note left
插件已经完全加载完毕,
所有的插件可以正常的使用,
执行一些流量进入前的任务,
比如拉取应用所需的一些配置
end note
: async DidReady;
note right
app进程已经准备完毕,
HTTP server开始监听端口,
====
时间点与原来的ready相同,
原来的ready不支持AsyncFunction
end note
: emit 'app-start';
}
: emit 'egg-ready';
: async serverDidReady;
note right
agent进程和所有的app进程已经准备完毕,
可以放入流量,
end note
: master receive SIGTERM;
fork
: agent beforeClose;
fork again
: app beforeClose;
note right
以插入顺序逆序同步执行,
生产环境中不建议使用,
可能在进程结束前没有执行完成
end note
endfork
stop
@enduml
44 changes: 44 additions & 0 deletions docs/source/zh-cn/advanced/loader.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,50 @@ plugin1 为 framework1 依赖的插件,配置合并后 object key 的顺序会

### 生命周期

Egg提供了配置文件加载完成(`configDidLoad`), 文件加载完成(`didLoad`), 插件启动完毕(`willReady`), worker 准备就绪(`didReady`), 应用启动完成(`serverDidReady`), 应用即将关闭(`beforeClose`)这些生命周期函数。
定义过程如下代码
```js
// app.js or agent.js
class AppBootHook {
constructor(app) {
}

configDidLoad() {
// Config,plugin files have did load.
}

async didLoad() {
// All files have did load, start plugin here.
}

async willReady() {
// All plugins have started, can do some thing before app ready
}

async didReady() {
// Worker is ready, can do some things
// don't need to block the app boot.
}

async serverDidReady() {
// Server is listening.
}

async beforeClose() {
// Do some thing before app close.
}
}
```

启动过程如图所示:

![](https://user-images.githubusercontent.com/6897780/42219323-24cbd7a8-7efe-11e8-86b9-cf280846aa9f.png)

使用 `beforeClose` 的时候需要注意,在 egg 的 进程关闭处理中是有超时时间的,如果 worker 进程在接收到进程退出信号之后,没有在所规定的时间内退出,将会被强制关闭。
如果需要调整超时时间的话,查看[此处文档](https://github.com/eggjs/egg-cluster)

旧版的使用方法:

Egg提供了应用启动(`beforeStart`), 启动完成(`ready`), 关闭(`beforeClose`)这三个生命周期方法。
```
init master process
Expand Down
6 changes: 6 additions & 0 deletions lib/egg.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ class EggApplication extends EggCore {
*/
this.messenger = new Messenger();

// trigger serverDidReady hook when all app workers
// and agent worker is ready
this.messenger.on('egg-ready', () => {
this.lifecycle.triggerServerDidReady();
});

// dump config after ready, ensure all the modifications during start will be recorded
// make sure dumpConfig is the last ready callback
this.ready(() => process.nextTick(() => {
Expand Down
1 change: 1 addition & 0 deletions lib/loader/agent_worker_loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class AgentWorkerLoader extends EggLoader {

load() {
this.loadAgentExtend();
this.loadBootHook();
this.loadCustomAgent();
}
}
Expand Down
1 change: 1 addition & 0 deletions lib/loader/app_worker_loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class AppWorkerLoader extends EggLoader {
this.loadHelperExtend();

// app > plugin
this.loadBootHook();
this.loadCustomApp();
// app > plugin
this.loadService();
Expand Down
39 changes: 39 additions & 0 deletions test/fixtures/apps/boot-app/agent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use strict';

const sleep = require('mz-modules/sleep');

module.exports = class {
constructor(app) {
app.bootLog = [];
this.app = app;
}

configDidLoad() {
this.app.bootLog.push('configDidLoad');
}

async didLoad() {
await sleep(1);
this.app.bootLog.push('didLoad');
}

async willReady() {
await sleep(1);
this.app.bootLog.push('willReady');
}

async didReady() {
await sleep(1);
this.app.bootLog.push('didReady');
}

async beforeClose() {
await sleep(1);
this.app.bootLog.push('beforeClose');
}

async serverDidReady() {
await sleep(1);
this.app.bootLog.push('serverDidReady');
}
};
39 changes: 39 additions & 0 deletions test/fixtures/apps/boot-app/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use strict';

const sleep = require('mz-modules/sleep');

module.exports = class {
constructor(app) {
app.bootLog = [];
this.app = app;
}

configDidLoad() {
this.app.bootLog.push('configDidLoad');
}

async didLoad() {
await sleep(1);
this.app.bootLog.push('didLoad');
}

async willReady() {
await sleep(1);
this.app.bootLog.push('willReady');
}

async didReady() {
await sleep(1);
this.app.bootLog.push('didReady');
}

async beforeClose() {
await sleep(1);
this.app.bootLog.push('beforeClose');
}

async serverDidReady() {
await sleep(1);
this.app.bootLog.push('serverDidReady');
}
};
3 changes: 3 additions & 0 deletions test/fixtures/apps/boot-app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "boot-app"
}
30 changes: 30 additions & 0 deletions test/lib/core/loader/load_boot.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use strict';

const assert = require('assert');
const utils = require('../../../utils');

describe('test/lib/core/loader/load_boot.test.js', () => {
let app;

before(() => {
app = utils.app('apps/boot-app');
return app.ready();
});

it('should load app.js', async () => {
await app.close();
assert.deepStrictEqual(app.bootLog, [ 'configDidLoad',
'didLoad',
'willReady',
'didReady',
'serverDidReady',
'beforeClose' ]);
assert.deepStrictEqual(app.agent.bootLog, [ 'configDidLoad',
'didLoad',
'willReady',
'didReady',
'serverDidReady',
'beforeClose' ]);
});

});

0 comments on commit 5fd83d0

Please sign in to comment.