From 6e2ffcb92e97722aea72696a5ae7b7db0913ba3b Mon Sep 17 00:00:00 2001 From: canonical Date: Sat, 18 Jan 2025 19:53:50 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9job=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/nop/job/api/IJobScheduler.java | 65 ++++++++++++++----- .../nop/job/api/spec/AnnualCalendarSpec.java | 7 +- .../nop/job/core/calendar/AnnualCalendar.java | 8 +-- .../job/core/calendar/CalendarBuilder.java | 2 +- .../sys/dao/elector/SysDaoLeaderElector.java | 2 + 5 files changed, 59 insertions(+), 25 deletions(-) diff --git a/nop-job/nop-job-api/src/main/java/io/nop/job/api/IJobScheduler.java b/nop-job/nop-job-api/src/main/java/io/nop/job/api/IJobScheduler.java index beaeb3d33..90cff1a3b 100644 --- a/nop-job/nop-job-api/src/main/java/io/nop/job/api/IJobScheduler.java +++ b/nop-job/nop-job-api/src/main/java/io/nop/job/api/IJobScheduler.java @@ -7,10 +7,14 @@ */ package io.nop.job.api; +import io.nop.api.core.annotations.biz.BizMutation; +import io.nop.api.core.annotations.biz.BizObjName; +import io.nop.api.core.annotations.biz.BizQuery; +import io.nop.api.core.annotations.core.Name; import io.nop.api.core.exceptions.NopException; import io.nop.job.api.spec.JobSpec; - import jakarta.annotation.Nullable; + import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -19,17 +23,24 @@ import static io.nop.job.api.JobApiErrors.ARG_JOB_NAME; import static io.nop.job.api.JobApiErrors.ERR_JOB_UNKNOWN_JOB; +@BizObjName("JobScheduler") public interface IJobScheduler { + + @BizQuery List getAllJobNames(); - JobDetail getJobDetail(String jobName); + @BizQuery + @Nullable + JobDetail getJobDetail(@Name("jobName") String jobName); /** * 得到指定任务的状态信息 * * @param ignoreUnknown 当jobName对应的任务不存在时是否抛出异常 */ - default List getJobDetails(Set jobNames, boolean ignoreUnknown) { + @BizQuery + default List getJobDetails(@Name("jobNames") Set jobNames, + @Name("ignoreUnknown") boolean ignoreUnknown) { List ret = new ArrayList<>(jobNames.size()); for (String jobName : jobNames) { JobDetail detail = getJobDetail(jobName); @@ -46,9 +57,15 @@ default List getJobDetails(Set jobNames, boolean ignoreUnknow /** * 加入任务,并自动启动trigger */ - void addJob(JobSpec spec, boolean allowUpdate, boolean startTrigger); - - default void addJobs(Collection specs, boolean allowUpdate, boolean startTrigger) { + @BizMutation + void addJob(@Name("jobSpec") JobSpec spec, + @Name("allowUpdate") boolean allowUpdate, + @Name("startTrigger") boolean startTrigger); + + @BizMutation + default void addJobs(@Name("specs") Collection specs, + @Name("allowUpdate") boolean allowUpdate, + @Name("startTrigger") boolean startTrigger) { for (JobSpec spec : specs) { addJob(spec, allowUpdate, startTrigger); } @@ -57,9 +74,11 @@ default void addJobs(Collection specs, boolean allowUpdate, boolean sta /** * 删除任务。如果任务当前处于运行状态,则会先取消任务 */ - boolean removeJob(String jobName); + @BizMutation + boolean removeJob(@Name("jobName") String jobName); - default boolean removeJobs(Collection jobNames) { + @BizMutation + default boolean removeJobs(@Name("jobNames") Collection jobNames) { if (jobNames == null) return false; @@ -71,6 +90,7 @@ default boolean removeJobs(Collection jobNames) { return b; } + @BizMutation default boolean clearJobs() { return removeJobs(getAllJobNames()); } @@ -79,14 +99,17 @@ default boolean clearJobs() { * 获取job当前状态。如果没有找到已注册的job,则返回null */ @Nullable - TriggerStatus getTriggerStatus(String jobName); + @BizQuery + TriggerStatus getTriggerStatus(@Name("jobName") String jobName); /** * 启动已经注册的任务 */ - boolean startJob(String jobName); + @BizQuery + boolean startJob(@Name("jobName") String jobName); - default boolean startJobs(Collection jobNames) { + @BizQuery + default boolean startJobs(@Name("jobNames") Collection jobNames) { if (jobNames == null) return false; @@ -98,6 +121,7 @@ default boolean startJobs(Collection jobNames) { return b; } + @BizQuery default boolean startAllJobs() { return startJobs(getAllJobNames()); } @@ -105,9 +129,11 @@ default boolean startAllJobs() { /** * 暂停任务。但是任务仍然保存在调度器中,并没有被删除 */ - boolean pauseJob(String jobName); + @BizQuery + boolean pauseJob(@Name("jobName") String jobName); - default boolean pauseJobs(Collection jobNames) { + @BizQuery + default boolean pauseJobs(@Name("jobNames") Collection jobNames) { if (jobNames == null) return false; @@ -119,6 +145,7 @@ default boolean pauseJobs(Collection jobNames) { return b; } + @BizMutation default boolean pauseAllJobs() { return pauseJobs(getAllJobNames()); } @@ -126,9 +153,11 @@ default boolean pauseAllJobs() { /** * 取消任务。任务取消后会进入取消状态,不会被自动调度 */ - boolean cancelJob(String jobName); + @BizMutation + boolean cancelJob(@Name("jobName") String jobName); - default boolean cancelJobs(Collection jobNames) { + @BizMutation + default boolean cancelJobs(@Name("jobNames") Collection jobNames) { if (jobNames == null) return false; @@ -140,6 +169,7 @@ default boolean cancelJobs(Collection jobNames) { return b; } + @BizMutation default boolean cancelAllJobs() { return cancelJobs(getAllJobNames()); } @@ -147,14 +177,15 @@ default boolean cancelAllJobs() { /** * 手动触发一次任务。如果任务正在执行,则返回false。如果任务没有处于调度状态,则临时调度一次。 任何时刻同一个jobName对应的任务只会有一个实例在执行。 */ - boolean fireNow(String jobName); + @BizMutation + boolean fireNow(@Name("jobName") String jobName); /** * 从数据库中装载持久化任务。 * * @param epoch 每次leader选举都产生一个新的epoch号 */ - void activate(long epoch); + void activate(@Name("epoch") long epoch); /** * deactivate之后不允许再接收外部指令。负载均衡场景下只有一个主任务调度器允许运行,如果发生主从切换,从服务器要执行deactivate操作。 处于deactivate状态的调度器不会再修改数据库。 diff --git a/nop-job/nop-job-api/src/main/java/io/nop/job/api/spec/AnnualCalendarSpec.java b/nop-job/nop-job-api/src/main/java/io/nop/job/api/spec/AnnualCalendarSpec.java index a18193bef..38e70e943 100644 --- a/nop-job/nop-job-api/src/main/java/io/nop/job/api/spec/AnnualCalendarSpec.java +++ b/nop-job/nop-job-api/src/main/java/io/nop/job/api/spec/AnnualCalendarSpec.java @@ -10,18 +10,19 @@ import io.nop.api.core.annotations.data.DataBean; import java.time.MonthDay; +import java.util.List; @DataBean public class AnnualCalendarSpec extends CalendarSpec { private static final long serialVersionUID = 1L; - private MonthDay[] excludes; + private List excludes; - public MonthDay[] getExcludes() { + public List getExcludes() { return excludes; } - public void setExcludes(MonthDay[] excludes) { + public void setExcludes(List excludes) { this.excludes = excludes; } } diff --git a/nop-job/nop-job-core/src/main/java/io/nop/job/core/calendar/AnnualCalendar.java b/nop-job/nop-job-core/src/main/java/io/nop/job/core/calendar/AnnualCalendar.java index 70dbbf015..db80f6eb7 100644 --- a/nop-job/nop-job-core/src/main/java/io/nop/job/core/calendar/AnnualCalendar.java +++ b/nop-job/nop-job-core/src/main/java/io/nop/job/core/calendar/AnnualCalendar.java @@ -13,7 +13,7 @@ import java.io.Serializable; import java.time.LocalDate; import java.time.MonthDay; -import java.util.Arrays; +import java.util.List; public class AnnualCalendar extends BaseCalendar implements ICalendar, Serializable { @@ -22,15 +22,15 @@ public class AnnualCalendar extends BaseCalendar implements ICalendar, Serializa /** * excludeDays需要按时间顺序排好序 */ - private MonthDay[] excludeDays; + private List excludeDays; public AnnualCalendar(ICalendar baseCalendar) { super(baseCalendar); } - public void setExcludeDays(MonthDay[] excludeDays) { + public void setExcludeDays(List excludeDays) { this.excludeDays = excludeDays; - Arrays.sort(excludeDays); + excludeDays.sort(MonthDay::compareTo); } private boolean isExcludedDay(LocalDate day) { diff --git a/nop-job/nop-job-core/src/main/java/io/nop/job/core/calendar/CalendarBuilder.java b/nop-job/nop-job-core/src/main/java/io/nop/job/core/calendar/CalendarBuilder.java index b1ef141c9..1a96e6cce 100644 --- a/nop-job/nop-job-core/src/main/java/io/nop/job/core/calendar/CalendarBuilder.java +++ b/nop-job/nop-job-core/src/main/java/io/nop/job/core/calendar/CalendarBuilder.java @@ -39,7 +39,7 @@ public static ICalendar buildCalendar(List calendars) { for (CalendarSpec calInfo : calendars) { if (calInfo instanceof AnnualCalendarSpec) { AnnualCalendarSpec spec = (AnnualCalendarSpec) calInfo; - if (ArrayHelper.isEmpty(spec.getExcludes())) + if (CollectionHelper.isEmpty(spec.getExcludes())) continue; AnnualCalendar annual = new AnnualCalendar(cal); diff --git a/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/elector/SysDaoLeaderElector.java b/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/elector/SysDaoLeaderElector.java index a9547849b..876dfd973 100644 --- a/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/elector/SysDaoLeaderElector.java +++ b/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/elector/SysDaoLeaderElector.java @@ -219,6 +219,7 @@ private boolean changeLeader(NopSysClusterLeader leader, IEntityDao dao = dao(); + IEstimatedClock clock = dao.getDbEstimatedClock(); for (int i = 0; i < 10; i++) { NopSysClusterLeader leader = getEntity(dao); @@ -227,6 +228,7 @@ public void restartElection() { // 增大epoch将导致当前的leader发现epoch已改变,需要重新获取leader leader.setLeaderEpoch(leader.getLeaderEpoch() + 1); + leader.setExpireAt(clock.getMinCurrentTime()); leader.orm_disableVersionCheckError(true); dao.updateEntityDirectly(leader);