- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个包含一些作业的应用程序,我想将这些作业保留在数据库中以便更好地维护。
该应用程序的结构如下:
数据库:
CREATE TABLE jobs_config (
id int8 NOT NULL GENERATED BY DEFAULT AS IDENTITY,
job_name varchar NOT NULL,
scheduled_value varchar NOT NULL,
CONSTRAINT jobs_config_pk PRIMARY KEY (id),
CONSTRAINT jobs_config_name_un UNIQUE (job_name)
);
insert into jobs_config(job_name, scheduled_value) values('DeleteExpiredTokenJob', '0 0 10 * * MON');
JAVA Spring 启动:
@Entity
@Table(name = "jobs_config")
public class JobsConfig {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "job_name")
private String jobName;
private String scheduledValue;
public JobsConfig() {
}
public JobsConfig(String jobName, String scheduledValue) {
this.jobName = jobName;
this.scheduledValue = scheduledValue;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
public String getScheduledValue() {
return scheduledValue;
}
public void setScheduledValue(String scheduledValue) {
this.scheduledValue = scheduledValue;
}
}
@Service
public class JobSchedulerService implements SchedulingConfigurer {
private static Logger logger = LoggerFactory.getLogger(JobSchedulerService.class);
@Autowired
JobsConfigRepository jobsConfigRepository;
@Autowired
DeleteExpiredTokenJob deleteExpiredTokenJob;
@Autowired
TestJob testJob;
@Bean
public TaskScheduler poolScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setThreadNamePrefix("ThreadPoolTaskScheduler");
scheduler.setPoolSize(1);
scheduler.initialize();
return scheduler;
}
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setTaskScheduler(poolScheduler());
listJobList();
// refreshJobList( poolScheduler());
}
public void listJobList() {
List<JobsConfig> jobsList = jobsConfigRepository.findAll();
for (JobsConfig jobName : jobsList) {
switch (jobName.getJobName()) {
case "DeleteExpiredTokenJob":
scheduleJob(poolScheduler(), deleteExpiredTokenJob, jobName.getJobName());
break;
case "TestJob":
scheduleJob(poolScheduler(), testJob, jobName.getJobName());
break;
default:
logger.info(String.format("JOB NOT FOUND [%s]", jobName.getJobName()));
}
}
}
public void scheduleJob(TaskScheduler scheduler, JobInterface jobInterface, String jobName){
scheduler.schedule(new Runnable(){
@Override
public void run() {
jobInterface.jobCode();
}
}, new Trigger(){
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
Optional <JobsConfig> job = jobsConfigRepository.findByJobName(jobName);
String cronExp = job.get().getScheduledValue();
return new CronTrigger(cronExp).nextExecutionTime(triggerContext);
}
});
}
//THIS IS WHAT I'VE TRIED !
/*private void refreshJobList(TaskScheduler scheduler){
scheduler.schedule(new Runnable(){
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" The Task2 executed at "+ new Date());
listJobList();
}
}, new Trigger(){
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
String cronExp="0/10 * * * * ?";//Can be pulled from a db . This will run every minute
return new CronTrigger(cronExp).nextExecutionTime(triggerContext);
}
});
}*/
}
这个想法是,每次我在 jobs_config 表中添加一条记录时,我都需要将其反射(reflect)在 java 中。
因此,如果我在表中添加新作业,我希望无需重新启动应用程序即可使用(当然,DeleteExpiredTokenJob 的 java 代码存在)。
insert into jobs_config(job_name, scheduled_value) values('DeleteExpiredTokenJob', '0/5 * * * * ?');
基本上我需要刷新列表List<JobsConfig> jobsList = jobsConfigRepository.findAll();
来自listJobList()
方法。
我怎样才能实现这个目标?
最佳答案
我发现您尝试创建一个可以刷新作业的作业,但没有成功。
我看不到在数据库中添加新作业后使其可用的简单方法,假设它有一个新的@Autowired
作业要注入(inject),但我想我知道如何跟踪数据库中的更新作业,即scheduled_value
列。
将旧的 JobsConfig
值保留在此处。
检查其中是否有任何更改。
2.a。如果发生更改,则取消下一个作业执行,并安排更新的作业。
睡几分钟以进行下一次检查。 (就像您在注释代码中所做的那样)
Map<String, JobsConfig> oldJobsConfigs = new HashMap<>();
Map<String, ScheduledFuture<?>> activeJobs = new HashMap<>()
public void listJobList() {
List<JobsConfig> jobsList = jobsConfigRepository.findAll();
for (JobsConfig jobName : jobsList) {
// If this job was there before and has not changed, do nothing.
if (oldJobsConfigs.containsKey(jobName.getJobName()) && oldJobsConfigs.get(jobName.getJobName()).getScheduledValue().equals(jobName.getScheduledValue()))
break;
// Cancel previous execution, if any.
if (activeJobs.containsKey(jobName.getJobName()) {
ScheduledFuture<?> job = activeJobs.get(jobName.getJobName());
job.cancel(false);
try {
job.get(); // Warning! If the job is running, blocks current thread until the job finishes. If has an endless loop, it will block current thread forever.
} catch (CancellationException e) {
// Do nothing, this is good, we did not spent time waiting for the job to finish.
} catch (InterruptedException | ExecutionException e) {
// Log it?
}
}
ScheduledFuture<?> newJob = null;
switch (jobName.getJobName()) {
case "DeleteExpiredTokenJob":
newJob = scheduleJob(poolScheduler(), deleteExpiredTokenJob, jobName.getJobName());
break;
case "TestJob":
newJob = scheduleJob(poolScheduler(), testJob, jobName.getJobName());
break;
default:
logger.info(String.format("JOB NOT FOUND [%s]", jobName.getJobName()));
}
if (newJob != null)
activeJobs.put(jobName.getJobName(), newJob);
}
}
并更改 scheduleJob
签名,以便它将利用 scheduler
返回的内容。
public ScheduledFuture<?> scheduleJob(TaskScheduler scheduler, JobInterface jobInterface, String jobName) {
return scheduler.schedule(new Runnable() {
// ... unchanged
希望有帮助。 :D
UPD:如果有一天您的作业数量远远超过十个,您可以稍微调整一下 JobInterface
,以便它将返回其作业名称:
public interface JobInterface {
// ... old methods
String getJobName(); // Consider switching to enums?
}
并让 Spring 将 JobInterface
的所有实现 Autowiring 到 JobSchedulerService
:
@Service
public class JobSchedulerService implements SchedulingConfigurer {
@Autowired
JobsConfigRepository jobsConfigRepository;
@Autowired
List<JobInterface> allJobs;
然后,您将编写的不是包含大量条目的 switch
ScheduledFuture<?> newJob = null;
for(JobInterface job : allJobs)
if (job.getJobName().equals(jobName.getJobName()))
newJob = scheduleJob(/*arguments*/);
if (newJob == null)
logger.warn(/*swear loudly :)*/);
也就是说,仅当您想要删除此开关
时。如果您打算工作的数量很少,那么保持原样也可以。
关于Java Spring Boot 计划作业,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58856236/
我的程序有问题。 我有一个比较两个字符串的条件: (if (eq? (exp1) (exp2))) 当 exp1 给我一个字符串,exp2 给我一个字符串。可以肯定的是,当我更改“eq?”时到“=”,
我们有多种主要使用 GWT 开发的产品,目前由我们的最终客户使用。 想知道 GWT 的路线图。我得到了一些非官方的更新,谷歌正在将 GWT 中开发的产品转移到其他一些新技术。这是真的吗? GWT 的长
我希望每 15 分钟定期构建一次。我在网上看过,我正在使用这个时间表:*/15 * * * * Jenkins 告诉我使用 H/15 * * * * 来平均分配负载而不是 */15 * * * * 有
所以我正试图在 Scheme 中找出整个 call/cc 的东西。下面是我正在使用的代码: (+ 1 (call/cc (lambda (k) (if (number? k)
所以我正试图在 Scheme 中找出整个 call/cc 的东西。下面是我正在使用的代码: (+ 1 (call/cc (lambda (k) (if (number? k)
我们有一个 Azure WebJob,计划在 UTC 每天上午 8:00 运行(CRON - 0 00 08 * * *)。大多数时候它都会正确触发,但有时会触发两次(第二次运行)第一次运行后约 10
我是 Terraform 的新手。我正在尝试通过 azure 管道创建一个简单的存储帐户,但是当我运行我的管道时,我收到错误“太多命令行参数”。我很震惊,我不知道自己做错了什么。有人可以帮忙吗。 这是
我想在某些逻辑中间停止芭蕾舞 Actor 程序。如何使用代码停止 ballerina 中正在运行的程序?我正在寻找相当于 java 中的 System.exit(0) 的东西。 最佳答案 我相信您正在
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 8年前关闭。 Improve this qu
我们有一个 Azure WebJob,计划在 UTC 每天上午 8:00 运行(CRON - 0 00 08 * * *)。大多数时候它都会正确触发,但有时会触发两次(第二次运行)第一次运行后约 10
我是 Terraform 的新手。我正在尝试通过 azure 管道创建一个简单的存储帐户,但是当我运行我的管道时,我收到错误“太多命令行参数”。我很震惊,我不知道自己做错了什么。有人可以帮忙吗。 这是
我正在浏览 htdp 并在一开始的某个地方发现了这个:- Explain why the following sentences are illegal definitions: 1. (define
我正在使用 Laravel 开发成员(member)门户。 成员(member)资格有不同的类别,例如1) 单人2) 成人3) 家庭以及不同价格的所有类型。 我有一个 plans 表和 plans_s
我使用 DreamHost 作为我的网站的服务器,并且我尝试每天、每周和每月执行某个 MySQL 查询来更改我的网站的数据库。我开始在本地主机上使用事件调度程序,然后我发现我无法在 DreamHost
这周我的 crontab 作业发生了一个问题。 设置如下,每两周正常运行一次,直到现在。 10 06 * * 1 test $(($(date +\%W)\%2)) -eq 0 && echo 'te
编写了一个简单的脚本,它将在日志文件中写入日期时间戳,并且每次运行该脚本时,它都会附加到该日志文件中。 #!/bin/sh echo $(date) >> log.txt 当我尝试每 1 分钟安排一次
我对 PIPE 的了解是它用于单向通信,它有助于在两个相关进程之间进行通信。我从一本书中得到了下面的 PIPE 编程代码示例。我正在尝试使用 printf 理解代码并在代码的每一行之后打印出所有点。但
代码如下: (define make-simple-sv-num (lambda (delare) (let ((tal (random-from-to 100000 1000000)))
我目前正在使用“How To Design Programs”——使用 Scheme/Racket;我在 Scheme 的 R5RS 版本中遇到了一个非常奇特的功能。 在进行简单的减法时,尽管使用的是
我想确定时间表的详细信息。例如: 我有一个事件的时间表:event.schedule "Every 3 months on the 10th day of the month" 由哈希表示: {
我是一名优秀的程序员,十分优秀!