|
|
|
@ -25,6 +25,8 @@ public class JobScheduleHelper { |
|
|
|
|
return instance; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static final long PRE_READ_MS = 5000; // pre read
|
|
|
|
|
|
|
|
|
|
private Thread scheduleThread; |
|
|
|
|
private Thread ringThread; |
|
|
|
|
private volatile boolean scheduleThreadToStop = false; |
|
|
|
@ -47,11 +49,11 @@ public class JobScheduleHelper { |
|
|
|
|
} |
|
|
|
|
logger.info(">>>>>>>>> init xxl-job admin scheduler success."); |
|
|
|
|
|
|
|
|
|
Connection conn = null; |
|
|
|
|
while (!scheduleThreadToStop) { |
|
|
|
|
|
|
|
|
|
// 扫描任务
|
|
|
|
|
long start = System.currentTimeMillis(); |
|
|
|
|
Connection conn = null; |
|
|
|
|
PreparedStatement preparedStatement = null; |
|
|
|
|
try { |
|
|
|
|
if (conn==null || conn.isClosed()) { |
|
|
|
@ -65,16 +67,16 @@ public class JobScheduleHelper { |
|
|
|
|
// tx start
|
|
|
|
|
|
|
|
|
|
// 1、预读5s内调度任务
|
|
|
|
|
long maxNextTime = System.currentTimeMillis() + 5000; |
|
|
|
|
List<XxlJobInfo> scheduleList = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().scheduleJobQuery(maxNextTime); |
|
|
|
|
List<XxlJobInfo> scheduleList = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().scheduleJobQuery(System.currentTimeMillis() + PRE_READ_MS); |
|
|
|
|
if (scheduleList!=null && scheduleList.size()>0) { |
|
|
|
|
// 2、推送时间轮
|
|
|
|
|
for (XxlJobInfo jobInfo: scheduleList) { |
|
|
|
|
|
|
|
|
|
// 时间轮刻度计算
|
|
|
|
|
if (System.currentTimeMillis() > jobInfo.getTriggerNextTime() + 5000) { |
|
|
|
|
if (System.currentTimeMillis() > jobInfo.getTriggerNextTime() + PRE_READ_MS) { |
|
|
|
|
// 过期超5s:本地忽略,当前时间开始计算下次触发时间
|
|
|
|
|
|
|
|
|
|
// fresh next
|
|
|
|
|
jobInfo.setTriggerLastTime(jobInfo.getTriggerNextTime()); |
|
|
|
|
jobInfo.setTriggerNextTime( |
|
|
|
|
new CronExpression(jobInfo.getJobCron()) |
|
|
|
@ -82,44 +84,55 @@ public class JobScheduleHelper { |
|
|
|
|
.getTime() |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
// pass
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
} else if (System.currentTimeMillis() > jobInfo.getTriggerNextTime()) { |
|
|
|
|
// 过期5s内 :立即触发一次,当前时间开始计算下次触发时间
|
|
|
|
|
// 过期5s内 :立即触发一次,当前时间开始计算下次触发时间;一旦过期,预读一次;
|
|
|
|
|
|
|
|
|
|
jobInfo.setTriggerLastTime(jobInfo.getTriggerNextTime()); |
|
|
|
|
jobInfo.setTriggerNextTime( |
|
|
|
|
new CronExpression(jobInfo.getJobCron()) |
|
|
|
|
.getNextValidTimeAfter(new Date()) |
|
|
|
|
.getTime() |
|
|
|
|
); |
|
|
|
|
CronExpression cronExpression = new CronExpression(jobInfo.getJobCron()); |
|
|
|
|
long nextTime = cronExpression.getNextValidTimeAfter(new Date()).getTime(); |
|
|
|
|
|
|
|
|
|
// do trigger
|
|
|
|
|
// 1、trigger
|
|
|
|
|
JobTriggerPoolHelper.trigger(jobInfo.getId(), TriggerTypeEnum.CRON, -1, null, null); |
|
|
|
|
|
|
|
|
|
// 2、fresh next
|
|
|
|
|
jobInfo.setTriggerLastTime(jobInfo.getTriggerNextTime()); |
|
|
|
|
jobInfo.setTriggerNextTime(nextTime); |
|
|
|
|
|
|
|
|
|
// 3、check pre read
|
|
|
|
|
if (jobInfo.getTriggerNextTime() - System.currentTimeMillis() < PRE_READ_MS) { |
|
|
|
|
|
|
|
|
|
// 1、make ring second
|
|
|
|
|
int ringSecond = (int)((jobInfo.getTriggerNextTime()/1000)%60); |
|
|
|
|
|
|
|
|
|
// 2、push time ring
|
|
|
|
|
pushTimeRing(ringSecond, jobInfo.getId()); |
|
|
|
|
|
|
|
|
|
// 3、fresh next
|
|
|
|
|
jobInfo.setTriggerLastTime(jobInfo.getTriggerNextTime()); |
|
|
|
|
jobInfo.setTriggerNextTime( |
|
|
|
|
new CronExpression(jobInfo.getJobCron()) |
|
|
|
|
.getNextValidTimeAfter(new Date(jobInfo.getTriggerNextTime())) |
|
|
|
|
.getTime() |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
logger.debug(">>>>>>>>>>> xxl-job, push trigger : jobId = " + jobInfo.getId() ); |
|
|
|
|
} else { |
|
|
|
|
// 未过期:正常触发,递增计算下次触发时间
|
|
|
|
|
|
|
|
|
|
// 1、make ring second
|
|
|
|
|
int ringSecond = (int)((jobInfo.getTriggerNextTime()/1000)%60); |
|
|
|
|
|
|
|
|
|
// 2、push time ring
|
|
|
|
|
pushTimeRing(ringSecond, jobInfo.getId()); |
|
|
|
|
|
|
|
|
|
// 3、fresh next
|
|
|
|
|
jobInfo.setTriggerLastTime(jobInfo.getTriggerNextTime()); |
|
|
|
|
jobInfo.setTriggerNextTime( |
|
|
|
|
new CronExpression(jobInfo.getJobCron()) |
|
|
|
|
.getNextValidTimeAfter(new Date(jobInfo.getTriggerNextTime())) |
|
|
|
|
.getTime() |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
// push async ring
|
|
|
|
|
List<Integer> ringItemData = ringData.get(ringSecond); |
|
|
|
|
if (ringItemData == null) { |
|
|
|
|
ringItemData = new ArrayList<Integer>(); |
|
|
|
|
ringData.put(ringSecond, ringItemData); |
|
|
|
|
} |
|
|
|
|
ringItemData.add(jobInfo.getId()); |
|
|
|
|
|
|
|
|
|
logger.debug(">>>>>>>>>>> xxl-job, push time-ring : " + ringSecond + " = " + Arrays.asList(ringItemData) ); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
@ -139,12 +152,6 @@ public class JobScheduleHelper { |
|
|
|
|
logger.error(">>>>>>>>>>> xxl-job, JobScheduleHelper#scheduleThread error:{}", e); |
|
|
|
|
} |
|
|
|
|
} finally { |
|
|
|
|
if (conn != null) { |
|
|
|
|
try { |
|
|
|
|
conn.close(); |
|
|
|
|
} catch (SQLException e) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (null != preparedStatement) { |
|
|
|
|
try { |
|
|
|
|
preparedStatement.close(); |
|
|
|
@ -166,6 +173,12 @@ public class JobScheduleHelper { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
if (conn != null) { |
|
|
|
|
try { |
|
|
|
|
conn.close(); |
|
|
|
|
} catch (SQLException e) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
logger.info(">>>>>>>>>>> xxl-job, JobScheduleHelper#scheduleThread stop"); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
@ -235,6 +248,18 @@ public class JobScheduleHelper { |
|
|
|
|
ringThread.start(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void pushTimeRing(int ringSecond, int jobId){ |
|
|
|
|
// push async ring
|
|
|
|
|
List<Integer> ringItemData = ringData.get(ringSecond); |
|
|
|
|
if (ringItemData == null) { |
|
|
|
|
ringItemData = new ArrayList<Integer>(); |
|
|
|
|
ringData.put(ringSecond, ringItemData); |
|
|
|
|
} |
|
|
|
|
ringItemData.add(jobId); |
|
|
|
|
|
|
|
|
|
logger.debug(">>>>>>>>>>> xxl-job, push time-ring : " + ringSecond + " = " + Arrays.asList(ringItemData) ); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void toStop(){ |
|
|
|
|
|
|
|
|
|
// 1、stop schedule
|
|
|
|
|