cn.ponfee.disjob.supervisor.base.TriggerTimes Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of disjob-supervisor Show documentation
Show all versions of disjob-supervisor Show documentation
Distributed job supervisor module
The newest version!
/*
* Copyright 2022-2024 Ponfee (http://www.ponfee.cn/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.ponfee.disjob.supervisor.base;
import cn.ponfee.disjob.common.date.Dates;
import cn.ponfee.disjob.core.enums.MisfireStrategy;
import cn.ponfee.disjob.core.enums.TriggerType;
import cn.ponfee.disjob.supervisor.model.SchedJob;
import org.springframework.util.Assert;
import java.util.Date;
/**
* Trigger time utility
*
* @author Ponfee
*/
public final class TriggerTimes {
public static Long updateNextTriggerTime(SchedJob job) {
Long lastTriggerTime = job.getLastTriggerTime();
Date now = new Date();
// 若更改Job状态或者修改Job trigger config,则以当前时间为基准来计算nextTriggerTime
job.setLastTriggerTime(Long.max(now.getTime() - 1, lastTriggerTime == null ? 0 : lastTriggerTime));
Long next = computeNextTriggerTime(job, now);
Assert.notNull(next, () -> "Expire " + TriggerType.of(job.getTriggerType()) + " value: " + job.getTriggerValue());
// reset the job lastTriggerTime
job.setLastTriggerTime(lastTriggerTime);
return next;
}
/**
* Returns the next trigger time
*
* @param job the job data
* @param now the now time
* @return next trigger time milliseconds
*/
public static Long computeNextTriggerTime(SchedJob job, Date now) {
Assert.notNull(now, "Compute next trigger time 'now' cannot be null.");
Date last = Dates.ofTimeMillis(job.getLastTriggerTime());
Date next = computeNextTriggerTime0(job, last, now);
if (last != null && next != null && !next.after(last)) {
throw new IllegalStateException("Next trigger time must be after last: " + last + ", " + last);
}
Date end = job.getEndTime();
return next == null || (end != null && next.after(end)) ? null : next.getTime();
}
// -------------------------------------------------------------------------------private methods
private static Date computeNextTriggerTime0(SchedJob job, Date last, Date now) {
TriggerType type;
if (job == null || TriggerType.DEPEND == (type = TriggerType.of(job.getTriggerType()))) {
return null;
}
MisfireStrategy strategy = MisfireStrategy.of(job.getMisfireStrategy());
String value = job.getTriggerValue();
final Date start = job.getStartTime();
final Date max = Dates.max(start, last, now);
if (type == TriggerType.ONCE) {
// `ONCE`类型要单独处理
Date next = type.computeNextTriggerTime(value, new Date(-1));
boolean isInvalid = (next == null) ||
(start != null && next.before(start)) ||
(last != null && !next.after(last)) ||
(strategy == MisfireStrategy.SKIP_ALL_LOST && next.before(max));
return isInvalid ? null : next;
}
if (max.equals(start) && !start.equals(last)) {
// last < now <= start[max]
return type.computeFirstTriggerTime(value, start);
}
if (last == null) {
// start < now[max]
Date next = type.computeNextTriggerTime(value, max);
if (strategy == MisfireStrategy.SKIP_ALL_LOST || next != null) {
return next;
}
// 解决某些CRON组件支持固定时间表达式的场景,如(2022-01-02 03:04:05):5 4 3 2 1 ? 2022
next = type.computeFirstTriggerTime(value, start != null ? start : new Date(-1));
if (next == null || (start != null && next.before(start))) {
return null;
}
if (strategy == MisfireStrategy.FIRE_ALL_LOST) {
return next;
}
// 到了这里 misfireStrategy=FIRE_ONCE_NOW
Date afterNext = type.computeNextTriggerTime(value, next);
// (next < now < afterNext) ? next : now
return (afterNext == null || afterNext.after(max)) ? next : max;
}
// last < start ? computeFirstTriggerTime(start) : computeNextTriggerTime(last)
Date next = (start != null && last.before(start)) ?
type.computeFirstTriggerTime(value, start) : type.computeNextTriggerTime(value, last);
// start < next && last < next
if (next == null || !next.before(max)) {
// next == null || next >= max
return next;
}
// ---------------- On here: start < next < now[max] && last < next < now[max] ---------------- //
if (strategy == MisfireStrategy.FIRE_ALL_LOST) {
return next;
} else if (strategy == MisfireStrategy.FIRE_ONCE_NOW) {
Date afterNext = type.computeNextTriggerTime(value, next);
// (next < now < afterNext) ? next : now
return (afterNext == null || afterNext.after(max)) ? next : max;
} else if (strategy == MisfireStrategy.SKIP_ALL_LOST) {
return type.computeNextTriggerTime(value, max);
} else {
throw new UnsupportedOperationException("Unsupported compute next trigger time: " + type);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy