- spring boot 相关配置
<dependency>
<groupId>org.jobrunr</groupId>
<artifactId>jobrunr-spring-boot-3-starter</artifactId>
<version>7.2.0</version>
</dependency>
org:
jobrunr:
background-job-server:
enabled: true
dashboard:
enabled: true
port: 28000
jobs:
default-number-of-retries: 10
retry-back-off-time-seed: 3
- 定制Job的覆盖逻辑:针对特定对象后面触发的job自动覆盖前面的job,重置重试间隔
前提:使用上面的starter可以自动注入Jobrunr的接口类:
private final JobScheduler jobScheduler;
private final StorageProvider storageProvider;
关键代码如下(分析了JobRunr的源码、数据库后得出的结论):
a. 首先需要为你的job生成合适的id,与目标对象(`targetIdentifier`)唯一对应
UUID uuid = UUID.nameUUIDFromBytes(targetIdentifier.getBytes(StandardCharsets.ISO_8859_1));
b. 关键的处理逻辑:如果存在则更新并enqueue(通过storageProvider.save
实现),不存在才新建
try {
// see requeue source code in JobRunrApiHandler#requeueJobById
var staleJob = storageProvider.getJobById(uuid); // 已存在job # https://github.com/jobrunr/jobrunr/discussions/759
var job = new Job(staleJob.getId(), staleJob.getVersion(),
staleJob.getJobDetails(), List.of(new EnqueuedState()), new ConcurrentHashMap<>());
// org.jobrunr.jobs.states.IllegalJobStateChangeException: A job cannot change state from ENQUEUED to ENQUEUED.
storageProvider.save(job);
} catch (JobNotFoundException e) {
jobScheduler.enqueue(uuid, () -> doYourTask(targetIdentifier)); //
}
单纯的jobScheduler.enqueue
在遇到同样的JobId时不会更新数据库,会导致重试间隔继续增长,同时日志会打印:
Skipped Job with id {} as it already exists
- 在免费版中如何注册
JobFilter
以监听Job状态变化事件,比如重试全部耗尽最终失败的事件,用于内部通知
/**
* 参考 https://springbuilders.dev/donatavict/getting-started-with-jobrunr-use-case-example-pt-ii-4hml
*/
public class JobRunrConfig {
@Component
@Slf4j
public static class GlobalTasksFilter implements JobServerFilter {
@Override
public void onFailedAfterRetries(Job job) {
log.error("All retries failed for Job {}", job.getJobName());
}
}
@Component
@RequiredArgsConstructor
public static class BackgroundJobServerBeanPostProcessor implements BeanPostProcessor {
private final GlobalTasksFilter globalTasksFilter;
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof BackgroundJobServer backgroundJobServer) {
backgroundJobServer.setJobFilters(Collections.singletonList(globalTasksFilter));
}
return bean;
}
}
}