-
Notifications
You must be signed in to change notification settings - Fork 19
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
refactor: classify #23
Conversation
agent.js
Outdated
agent.messenger.once('egg-ready', () => { | ||
// Compatible | ||
for (const type of Object.keys(handlers)) { | ||
schedule.use(type, handler2Class(type, handlers[type])); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里可以加个 depd
lib/schedule.js
Outdated
} | ||
|
||
const handler = new Strategy(this.agent, key, schedule); | ||
this.handler.set(key, handler); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里还没太想好 stop()
怎么用,目前的 key 是全路径,这个不好传递进来。
初步想法是 exports.key
的方式给用户去定义,我们检测不允许冲突。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
没想好之前,handler 这里可能先不存了,要干掉。
因为如果存的话,就要考虑到 Strategy
的退出机制,那边退出后这边也要跟着移除。
lib/strategy/base.js
Outdated
try { | ||
do { | ||
// TODO: try | ||
nextTick = interval.next().getTime(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里要 try 下,支持 cronOptions
后,会有 endDate
导致的主动退出
lib/schedule.js
Outdated
this.agent = agent; | ||
this.handler = new Map(); | ||
this.strategy = new Map(); | ||
this.use('worker', WorkerStrategy); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个也写在 agent.js 里吧
lib/schedule.js
Outdated
const AllStrategy = require('./strategy/all'); | ||
const Strategy = require('./strategy/base'); | ||
|
||
module.exports = class Schedule { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
用 sdk-base?实现 _init?这样不需要手动调用 start 了。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
感觉继承 sdk-base
好像也没啥用处,就是 nextTick 自动调用 init,因为 handler 是在 ready 里面才注册的,这样的话就要把 Schedule
的实例化也放进来,感觉继承也没啥好处
lib/schedule.js
Outdated
} | ||
|
||
const handler = new Strategy(this.agent, key, schedule); | ||
this.handler.set(key, handler); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个 handler 存着有啥用?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
上面有提到,#23 (comment)
实现 close 和 beforeClose 的时候要移除掉?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
之前是想在 agent 里面可以支持 close 掉指定的任务。这个不知道有没有场景?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
如果没有的话,可以考虑不存 handler,只在 Strategy 内部,判断到 agent 的那个状态位后,自己退出循环(目前是跳过,不是退出)
lib/schedule.js
Outdated
} | ||
|
||
start() { | ||
this.agent.disableSchedule = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个可以写在 agent.js 里
agent.disableSchedule = false;
agent.on('close', () => {
agent.disableSchedule = true;
});
其他都是只读。
lib/schedule.js
Outdated
|
||
const Strategy = this.strategy.get(type); | ||
if (!Strategy) { | ||
const err = new Error(`schedule type [${type}] is not defined`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is not supported?
lib/strategy/base.js
Outdated
const ms = require('humanize-ms'); | ||
const safetimers = require('safe-timers'); | ||
|
||
module.exports = class BaseStrategy { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BaseStrategy 承载一个功能就是保留 sender
原来的扩展
agent[SCHEDULE_HANDLER].cluster = (schedule, sender) => {
listenXXX(schedule.event, () => {
sender.one();
});
};
期望的扩展
class ClusterStrategy extends BaseStrategy {
constructor(scheduleInfo) {
super(scheduleInfo);
// 这里实现触发时机
listenXXX(scheduleInfo.event, () => {
this.sendOne();
});
}
}
agent.use('cluster', ClusterStrategy);
感觉不需要传递 agent,入参是 scheduleInfo,有 sendOne 和 sendAll 方法。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- sender 目前的设计,是每次都生成一个,bind
key
的,感觉有点别扭。 - 传入 agent 的话,Strategy 里面可以调用
agent.config
和agent.logger
。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Strategy 还是简单点
lib/strategy/base.js
Outdated
const ms = require('humanize-ms'); | ||
const safetimers = require('safe-timers'); | ||
|
||
module.exports = class BaseStrategy { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
然后在搞个本地的基类实现现有的功能
class LocalStrategy extends BaseStrategy {
start(listener) {
startXXX(listener);
}
close() {
// 关闭 interval
}
});
class AllLocalStrategy extends LocalStrategy {
constructor(scheduleInfo) {
super(scheduleInfo);
this.start(() => {
this.sendAll();
});
}
}
class WorkerLocalStrategy extends LocalStrategy {
constructor(scheduleInfo) {
super(scheduleInfo);
this.start(() => {
this.sendOne();
});
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
嗯,这个可以再拆下。
应该暴露 app.ScheduleStrategy |
Codecov Report
@@ Coverage Diff @@
## master #23 +/- ##
=====================================
Coverage 100% 100%
=====================================
Files 3 9 +6
Lines 111 168 +57
=====================================
+ Hits 111 168 +57
Continue to review full report at Codecov.
|
e60ea0e
to
2eef536
Compare
10c9839
to
6b2faa6
Compare
lib/strategy/base.js
Outdated
'use strict'; | ||
|
||
module.exports = class BaseStrategy { | ||
constructor(agent, key, scheduleInfo) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
传一个对象就好了,不然继承的时候不好写
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
是指三个作为一个对象传入还是?
你看下 base 和 timer,没有 agent 的话不行。
lib/strategy/base.js
Outdated
constructor(agent, key, scheduleInfo) { | ||
this.agent = agent; | ||
this.key = key; | ||
this.scheduleInfo = scheduleInfo; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
要不就叫 schedule 好了,和定义的名字一样
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
好
lib/strategy/local.js
Outdated
throw new Error('[egg-schedule] schedule.interval or schedule.cron must be present'); | ||
} | ||
|
||
const send = () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
send 做参数传入不好?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个timer 也可以做个单例,然后在子类 timer.start(key, cb),并且管理所有的 timer,可以直接关闭 timer 不需要在这里实现 close
嗯,跟这个一起的,明早再想想,没电了现在。其他几个 review 改了,刚提交了一份最新了。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
改为参数传入了
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
单例的那个明天再看看
lib/strategy/base.js
Outdated
this.agent.messenger.send(this.key); | ||
} | ||
|
||
start() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里不需要实现 start
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
基类里面不写个空函数? 毕竟 schedule 那边会调用的
lib/strategy/worker.js
Outdated
module.exports = class WorkerStrategy extends Strategy { | ||
constructor(...args) { | ||
super(...args); | ||
this.type = 'worker'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个不用了吧
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
好,在外面 use
时有设置 prototype.type
了
lib/strategy/worker.js
Outdated
@@ -0,0 +1,14 @@ | |||
'use strict'; | |||
|
|||
const Strategy = require('./timer'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个文件在哪
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个timer 也可以做个单例,然后在子类 timer.start(key, cb),并且管理所有的 timer,可以直接关闭 timer 不需要在这里实现 close
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
timer 文件没看到?刷新下。
我在想是不是把所有的 Strategy
的实例,都在自己的构造函数里面存到 static 去?
然后 Strategy 提供一个 static close()
这样的好处:
- schedule 那边就不用搞个 handler map 了。
- 在 cron 里面触发 endDate 后,把自己 close 掉,就可以自己回收了,否则不好通知 schdule。
觉得怎么样?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
endDate 是哪里出发的
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
我期望 strategy 不需要 start 方法了,都在构造函数做就好了,基本都是注册一个 sender
默认的就是通过 timer 注册一个 sender
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
嗯,timer 的改了提交了。
agent.js
Outdated
}; | ||
const handlers = agent[SCHEDULE_HANDLER] = {}; | ||
agent.schedule = new Schedule(agent); | ||
agent.ScheduleStrategy = BaseStrategy; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个写在 extend,没有插件顺序问题
agent.js
Outdated
err.message = `[egg-schedule] parse cron instruction(${schedule.cron}) error: ${err.message}`; | ||
throw err; | ||
agent.messenger.once('egg-ready', () => { | ||
agent.schedule.use('worker', WorkerStrategy); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
现在定义可以放在外面了
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
兼容的那几个不行吧? 放外面的话,执行顺序是怎么样的?
agent.js
Outdated
agent.schedule.use('all', AllStrategy); | ||
//TODO: compatible, will remove at next major | ||
const keys = Object.keys(handlers); | ||
if (keys.length) agent.deprecate('should use `schedule.use()` instead of `agent[Symbol.for(\'egg#scheduleHandler\')]` to register handler.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
放到循环里提示?
lib/schedule.js
Outdated
|
||
use(type, clz) { | ||
assert(typeof clz.prototype.start === 'function', `schedule type [${type}] should implement \`start\` method`) | ||
clz.prototype.type = type; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个 type 不要了,class 都知道自己是谁了,还需要这个标识?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
嗯,可以干掉了。
lib/schedule.js
Outdated
} | ||
|
||
close() { | ||
this.closed = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
实际化设 false ?
lib/schedule.js
Outdated
for (const handler of this[HANDLER].values()) { | ||
handler.close(); | ||
} | ||
this.agent.coreLogger.info('[egg-schedule] close tasks.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
写到 for 循环?把 key 打出来
lib/strategy/timer.js
Outdated
} | ||
|
||
if (interval) { | ||
this.interval = this.safeInterval(send, ms(interval)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里每个配置不需要 return 么?
lib/strategy/worker.js
Outdated
@@ -0,0 +1,14 @@ | |||
'use strict'; | |||
|
|||
const Strategy = require('./timer'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
endDate 是哪里出发的
this.startCron(key, interval, listener); | ||
}, nextTick - now); | ||
|
||
this.timer.set(key, tid); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
每个递归都覆盖?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
嗯,因为是 setTimeout ,每次都是一个新的了,要记录最后一个
lib/strategy/worker.js
Outdated
module.exports = class WorkerStrategy extends Strategy { | ||
constructor(...args) { | ||
super(...args); | ||
this.timer = new Timer(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
我的意思是用单例,不用多实例
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this.agent.scheduleTimer.start(key, schedule, () => this.sendOne());
然后 start 和 close 都可以删掉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这样就是把 timer 提到最外面了,现在这样也就两个实例。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
提的话,我更倾向于提到 agent.schedule.timer
就好了
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
主要是这个 timer 就是内置的 strategy 用的,把他当作插件来考虑看看。
agent.js
Outdated
agent.disableSchedule = true; | ||
return; | ||
agent.beforeClose(() => { | ||
return agent.schedule.close(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agent.scheduleTimer.close
lib/schedule.js
Outdated
} | ||
|
||
start() { | ||
this.closed = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里是不是不用设了
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
如果手动调用一次 close,然后再调用 start 这种场景呢?
agent.js
Outdated
|
||
if (schedule.interval) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dead-horse 这里原来就可以设置多个的吗
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
啥?
agent.js
Outdated
}); | ||
} | ||
close() { | ||
this.agent.logger.warn(`schedule type [${type}] stop is not implemented yet`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
没有 close 就不要实现了。
1dd935d
to
0c47873
Compare
test/fixtures/customType/agent.js
Outdated
@@ -6,4 +6,14 @@ module.exports = function(agent) { | |||
agent[SCHEDULE_HANDLER].custom = function(schedule, sender) { | |||
setInterval(sender.one, schedule.interval); | |||
}; | |||
|
|||
class ClusterStrategy extends agent.ScheduleStrategy { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
分为两个例子吧
} catch (err) { | ||
err.message = `[egg-schedule] parse cron instruction(${schedule.cron}) error: ${err.message}`; | ||
throw err; | ||
agent.messenger.once('egg-ready', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
加一下注释,需要等插件注册 strategy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
加了,在下一行
throw new Error('[egg-schedule] schedule.interval or schedule.cron must be present'); | ||
} | ||
|
||
if (interval) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里我的意思是如果一个 schedule 同时配置了 interval cron immediate 呢?应该匹配到就返回。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
嗯,这个要看之前是怎么样的了,cc @dead-horse
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
之前的逻辑好像就是这样的,都配置了就都执行
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
嗯,这个就保持原来逻辑
其他 +1,剩下的 @dead-horse 看看,估计要等国庆后了。 |
CI 好像不是很稳 |
@dead-horse 看看 |
+1 |
2.5.0 |
Checklist
npm test
passesAffected core subsystem(s)
Description of change
cronOptions
,配置时区等。close [egg-schedule] cron-style 建议支持自定义 timezone egg#1274agent.schedule.use(type, Strategy)
方式agent.schedule
/agent.ScheduleStrategy
egg-schedule
,把key
放到 data 里面传递,减少事件注册个数。key
去掉前缀,直接为 fullpath