如何配置触发器的到期日期



我有下一个JobSchedulerService:

@Slf4j
@Service
@RequiredArgsConstructor
public class QuartzServiceImpl implements JobSchedulerService {
private final SchedulerFactoryBean schedulerFactoryBean;
@Override
public void scheduleJob(LocalDateTime date, Class jobClass, boolean repeatUntilManuallyStopped, Map<String, Object> jobDataMap) {
String expirationDate = date.toString();
String name = jobClass.getName() + "_";;
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(name + expirationDate)
.storeDurably().build();
if(jobDataMap != null){
jobDetail.getJobDataMap().putAll(jobDataMap);
}
jobDetail.getJobDataMap().put("expirationDate", expirationDate);
ZonedDateTime zonedDateTime = date.atZone(ZoneId.systemDefault());
SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name + expirationDate)
.startAt(Date.from(zonedDateTime.toInstant()))
.endAt(Date.from(zonedDateTime.plusMinutes(2).toInstant()))
.withSchedule(repeatUntilManuallyStopped ?
SimpleScheduleBuilder.repeatMinutelyForever().withMisfireHandlingInstructionFireNow() : SimpleScheduleBuilder.simpleSchedule().withMisfireHandlingInstructionFireNow())
.build();

schedule(jobDetail, trigger, false);
}
@Override
public void scheduleJob(LocalDateTime date, int intervalInMinutes, int count, Class jobClass,  Map<String, Object> jobDataMap) {
String expirationDate = date.toString();
String name = jobClass.getName() + "_";
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(name + expirationDate)
.storeDurably().build();
jobDetail.getJobDataMap().putAll(jobDataMap);
jobDetail.getJobDataMap().put("expirationDate", expirationDate);
LocalDateTime currentTime = LocalDateTime.now();
LocalDateTime startDateTime = date;
int decrement = count;
while (decrement != 0) {
startDateTime = startDateTime.minusMinutes(intervalInMinutes);
decrement --;
if(currentTime.compareTo(startDateTime) >= 0) {
startDateTime = currentTime;
break;
}
}
SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name + expirationDate)
.startAt(Date.from(startDateTime.atZone(ZoneId.systemDefault()).toInstant()))
.withSchedule(SimpleScheduleBuilder.repeatMinutelyForTotalCount(count - decrement, intervalInMinutes)
.withMisfireHandlingInstructionFireNow())
.build();
schedule(jobDetail, trigger, false);
}
public Date schedule(JobDetail jobDetail, SimpleTrigger trigger, boolean isUnique) {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
try {
boolean alreadyExists = scheduler.checkExists(jobDetail.getKey());
if(isUnique && alreadyExists) {
throw new ApiException(ApiError.RESOURCE_EXISTS);
} else if(!alreadyExists){
Date date = scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
return date;
} else {
return trigger.getStartTime();
}
} catch (ObjectAlreadyExistsException e) {
if(isUnique) {
ExceptionTracker.captureException(e);
log.error("Could not schedule job with key {} and description {}. Job already exists", jobDetail.getKey().getName(), jobDetail.getDescription());
throw new ApiException(ApiError.INTERNAL_SERVER_ERROR);
} else {
return trigger.getStartTime();
}
} catch (Exception e){
ExceptionTracker.captureException(e);
log.error("Could not schedule job with key {} and description {}. Localized message => {}", jobDetail.getKey().getName(), jobDetail.getDescription(), e.getLocalizedMessage());
throw new ApiException(ApiError.INTERNAL_SERVER_ERROR);
}
}
}

这里我设置了2分钟后过期的时间

.endAt (Date.from (zonedDateTime.plusMinutes (2) .toInstant ()))

我在应用程序创建作业和触发器后立即关闭它。但是当我再次启动时,它运行过期触发器,即使时间已经通过表qrtz_triggers.end_time.

我的Quartz属性文件:

org.quartz.scheduler.instanceName=PostcreditService
org.quartz.scheduler.instanceId=AUTO
org.quartz.threadPool.threadCount=5
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.misfireThreshold=60000
org.quartz.jobStore.tablePrefix=postcredit.qrtz_
org.quartz.jobStore.isClustered=true
org.quartz.plugin.shutdownHook.class=org.quartz.plugins.management.ShutdownHookPlugin
org.quartz.plugin.shutdownHook.cleanShutdown=TRUE

配置:

@Configuration
public class QuartzConfig {
@Autowired
private ApplicationContext applicationContext;
@Autowired
private DataSource dataSource;
@Bean
public JobFactory jobFactory() {
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setQuartzProperties(quartzProperties());
schedulerFactory.setWaitForJobsToCompleteOnShutdown(true);
schedulerFactory.setAutoStartup(true);
schedulerFactory.setJobFactory(jobFactory());
schedulerFactory.setDataSource(dataSource);
return schedulerFactory;
}
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
}

,请帮助!

您正在使用TriggerBuilder.endAt()正确设置触发器的过期时间

在创建作业和触发器后立即关闭应用程序。但是当我再次启动它运行过期触发,即使时间已经传入表qrtz_triggers.end_time.

发生这种情况是因为在重新启动时,quartz检查是否有失火触发器,并尝试根据配置的mirefire指令(在您的情况下是withMisfireHandlingInstructionFireNow)重新运行这些触发器。现在的问题是,这个特定的指令不考虑触发器的endAt()时间,总是设置一个新的nextFireTime并重新运行它。

对于您的情况,您可能需要考虑其他失火指令,如withMisfireHandlingInstructionNowWithExistingCount

最新更新