mirror of https://github.com/shunfei/cronsun
show job's next run time in UI
parent
b1f93a411c
commit
8e9b0f9e6b
21
job.go
21
job.go
|
@ -411,6 +411,26 @@ func (j *Job) String() string {
|
||||||
return string(data)
|
return string(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNextRunTime return the job's next run time by now,
|
||||||
|
// will return zero time if job will not run.
|
||||||
|
func (j *Job) GetNextRunTime() time.Time {
|
||||||
|
nextTime := time.Time{}
|
||||||
|
if len(j.Rules) < 1 {
|
||||||
|
return nextTime
|
||||||
|
}
|
||||||
|
for i, r := range j.Rules {
|
||||||
|
sch, err := cron.Parse(r.Timer)
|
||||||
|
if err != nil {
|
||||||
|
return nextTime
|
||||||
|
}
|
||||||
|
t := sch.Next(time.Now())
|
||||||
|
if i == 0 || t.UnixNano() < nextTime.UnixNano() {
|
||||||
|
nextTime = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nextTime
|
||||||
|
}
|
||||||
|
|
||||||
// Run 执行任务
|
// Run 执行任务
|
||||||
func (j *Job) Run() bool {
|
func (j *Job) Run() bool {
|
||||||
var (
|
var (
|
||||||
|
@ -738,6 +758,5 @@ func (j *Job) CreateCmdAttr() (*syscall.SysProcAttr, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return sysProcAttr, nil
|
return sysProcAttr, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,6 +219,7 @@ func (j *Job) GetList(ctx *Context) {
|
||||||
type jobStatus struct {
|
type jobStatus struct {
|
||||||
*cronsun.Job
|
*cronsun.Job
|
||||||
LatestStatus *cronsun.JobLatestLog `json:"latestStatus"`
|
LatestStatus *cronsun.JobLatestLog `json:"latestStatus"`
|
||||||
|
NextRunTime string `json:"nextRunTime"`
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := cronsun.DefalutClient.Get(prefix, clientv3.WithPrefix(), clientv3.WithSort(clientv3.SortByKey, clientv3.SortAscend))
|
resp, err := cronsun.DefalutClient.Get(prefix, clientv3.WithPrefix(), clientv3.WithSort(clientv3.SortByKey, clientv3.SortAscend))
|
||||||
|
@ -263,6 +264,12 @@ func (j *Job) GetList(ctx *Context) {
|
||||||
} else {
|
} else {
|
||||||
for i := range jobList {
|
for i := range jobList {
|
||||||
jobList[i].LatestStatus = m[jobList[i].ID]
|
jobList[i].LatestStatus = m[jobList[i].ID]
|
||||||
|
nt := jobList[i].GetNextRunTime()
|
||||||
|
// if nt.IsZero() {
|
||||||
|
// jobList[i].NextRunTime = "Never run"
|
||||||
|
// } else {
|
||||||
|
jobList[i].NextRunTime = nt.Format("2006-01-02 15:04:05")
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -61,7 +61,7 @@
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<div id="initloader"></div>
|
<div id="initloader"></div>
|
||||||
</div>
|
</div>
|
||||||
<script src="build.js?v=8fbb71c"></script>
|
<script src="build.js?v=b1f93a4"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -66,6 +66,8 @@
|
||||||
<td>
|
<td>
|
||||||
<span v-if="!job.latestStatus">-</span>
|
<span v-if="!job.latestStatus">-</span>
|
||||||
<span v-else>{{formatLatest(job.latestStatus)}}</span>
|
<span v-else>{{formatLatest(job.latestStatus)}}</span>
|
||||||
|
<br/>
|
||||||
|
<span>{{formatNextRunTime(job.nextRunTime)}}</span>
|
||||||
</td>
|
</td>
|
||||||
<td :class="{error: job.latestStatus && !job.latestStatus.success}">
|
<td :class="{error: job.latestStatus && !job.latestStatus.success}">
|
||||||
<span v-if="!job.latestStatus">-</span>
|
<span v-if="!job.latestStatus">-</span>
|
||||||
|
@ -186,6 +188,10 @@ export default {
|
||||||
return this.$L('on {node} took {times}, {begin ~ end}', this.$store.getters.hostshowsWithoutTip(latest.node), formatDuration(latest.beginTime, latest.endTime), formatTime(latest.beginTime, latest.endTime));
|
return this.$L('on {node} took {times}, {begin ~ end}', this.$store.getters.hostshowsWithoutTip(latest.node), formatDuration(latest.beginTime, latest.endTime), formatTime(latest.beginTime, latest.endTime));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
formatNextRunTime: function(nextRunTime){
|
||||||
|
return this.$L('next will run on {nextTime}', nextRunTime);
|
||||||
|
},
|
||||||
|
|
||||||
showExecuteJobModal: function(jobName, jobGroup, jobId){
|
showExecuteJobModal: function(jobName, jobGroup, jobId){
|
||||||
this.$refs.executeJobModal.show(jobName, jobGroup, jobId);
|
this.$refs.executeJobModal.show(jobName, jobGroup, jobId);
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="ui icon input">
|
<div class="ui icon input">
|
||||||
<input type="text" v-bind:value="rule.timer" v-on:input="change('timer', $event.target.value)" :placeholder="$L('0 * * * * *, rules see the 「?」on the right')"/>
|
<input type="text" v-bind:value="rule.timer" v-on:input="change('timer', $event.target.value)" :placeholder="$L('0 * * * * *, rules see the 「?」on the right')"/>
|
||||||
<i ref="ruletip" class="large help circle link icon" data-position="top right" :data-content="$L('<sec> <min> <hr> <day> <month> <week>, rules is same with Cron')" data-variation="wide"></i>
|
<i ref="ruletip" class="large help circle link icon" data-position="top right" :data-html="$L('<sec> <min> <hr> <day> <month> <week>, rules is same with Cron')" data-variation="wide"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
|
|
|
@ -75,6 +75,7 @@ var language = {
|
||||||
'all groups': 'All groups',
|
'all groups': 'All groups',
|
||||||
'all nodes': 'All nodes',
|
'all nodes': 'All nodes',
|
||||||
'on {node} took {times}, {begin ~ end}': 'On {0} took {1}, {2}',
|
'on {node} took {times}, {begin ~ end}': 'On {0} took {1}, {2}',
|
||||||
|
'next will run on {nextTime}': 'Next will run at {0}',
|
||||||
'create job': 'Create job',
|
'create job': 'Create job',
|
||||||
'update job': 'Update job',
|
'update job': 'Update job',
|
||||||
'output': 'Output',
|
'output': 'Output',
|
||||||
|
@ -106,7 +107,10 @@ var language = {
|
||||||
'timeout(in seconds, 0 for no limits)': 'Timeout(in seconds, 0 for no limits)',
|
'timeout(in seconds, 0 for no limits)': 'Timeout(in seconds, 0 for no limits)',
|
||||||
'log expiration(log expired after N days, 0 will use default setting: {n} days)': 'Log expiration(log expired after N days, 0 will use default setting: {0} days)',
|
'log expiration(log expired after N days, 0 will use default setting: {n} days)': 'Log expiration(log expired after N days, 0 will use default setting: {0} days)',
|
||||||
'0 * * * * *, rules see the 「?」on the right': '0 * * * * *, rules see the 「?」on the right',
|
'0 * * * * *, rules see the 「?」on the right': '0 * * * * *, rules see the 「?」on the right',
|
||||||
'<sec> <min> <hr> <day> <month> <week>, rules is same with Cron': '<sec> <min> <hr> <day> <month> <week>, rules is same with Cron',
|
'<sec> <min> <hr> <day> <month> <week>, rules is same with Cron': '<sec> <min> <hour> <day> <month> <week>, rules is same with Cron.' +
|
||||||
|
'<br/>If want run job once at special time (like Linux\'s "at" command), you can use "@at 2006-01-02 15:04:05" to set it.' +
|
||||||
|
'<br/>You may use one of several pre-defined schedules in place of a cron expression. "@hourly" run once an hour, beginning of hour.' +
|
||||||
|
'<br/>More detail please visit the wiki.',
|
||||||
'and please running on those nodes': 'And please running on those nodes',
|
'and please running on those nodes': 'And please running on those nodes',
|
||||||
'do not running on those nodes': 'Do not running on those nodes',
|
'do not running on those nodes': 'Do not running on those nodes',
|
||||||
'the job dose not have a timer currently, please click the button below to add a timer': 'The job dose not have a timer currently, please click the button below to add a timer',
|
'the job dose not have a timer currently, please click the button below to add a timer': 'The job dose not have a timer currently, please click the button below to add a timer',
|
||||||
|
|
|
@ -76,6 +76,7 @@ var language = {
|
||||||
'all groups': '所有分组',
|
'all groups': '所有分组',
|
||||||
'all nodes': '所有节点',
|
'all nodes': '所有节点',
|
||||||
'on {node} took {times}, {begin ~ end}': '于 {0} 耗时 {1}, {2}',
|
'on {node} took {times}, {begin ~ end}': '于 {0} 耗时 {1}, {2}',
|
||||||
|
'next will run on {nextTime}': '下次将运行于 {0}',
|
||||||
'create job': '新建任务',
|
'create job': '新建任务',
|
||||||
'update job': '更新任务',
|
'update job': '更新任务',
|
||||||
'output': '输出',
|
'output': '输出',
|
||||||
|
@ -107,7 +108,10 @@ var language = {
|
||||||
'timeout(in seconds, 0 for no limits)': '超时设置(单位“秒”,0 表示不限制)',
|
'timeout(in seconds, 0 for no limits)': '超时设置(单位“秒”,0 表示不限制)',
|
||||||
'log expiration(log expired after N days, 0 will use default setting: {n} days)': '日志过期(日志保存天数,0 表示使用默认设置:{0} 天)',
|
'log expiration(log expired after N days, 0 will use default setting: {n} days)': '日志过期(日志保存天数,0 表示使用默认设置:{0} 天)',
|
||||||
'0 * * * * *, rules see the 「?」on the right': '0 * * * * *, 规则参考右边的「?」',
|
'0 * * * * *, rules see the 「?」on the right': '0 * * * * *, 规则参考右边的「?」',
|
||||||
'<sec> <min> <hr> <day> <month> <week>, rules is same with Cron': '<秒> <分> <时> <日> <月> <周>,规则与 Cron 一样',
|
'<sec> <min> <hr> <day> <month> <week>, rules is same with Cron': '<秒> <分> <时> <日> <月> <周>,规则与 Cron 一样。' +
|
||||||
|
'<br/>如果要指定只在某个时间点执行一次(类似Linux系统的at命令),可以使用 "@at 2006-01-02 15:04:05" 这样来设定。' +
|
||||||
|
'<br/>也支持一些简写,例如 @daily 表示每天执行一次。' +
|
||||||
|
'<br/>更多请参考wiki。',
|
||||||
'and please running on those nodes': '同时在这些节点上面运行',
|
'and please running on those nodes': '同时在这些节点上面运行',
|
||||||
'do not running on those nodes': '不要在这些节点上面运行',
|
'do not running on those nodes': '不要在这些节点上面运行',
|
||||||
'the job dose not have a timer currently, please click the button below to add a timer': '当前任务没有定时器,点击下面按钮来添加定时器',
|
'the job dose not have a timer currently, please click the button below to add a timer': '当前任务没有定时器,点击下面按钮来添加定时器',
|
||||||
|
|
Loading…
Reference in New Issue