【问题标题】:Play! framework: can I reschedule the job?玩!框架:我可以重新安排工作吗?
【发布时间】:2012-09-14 07:51:15
【问题描述】:


我正在使用播放! 1.2.4版框架
在我的应用程序中,我实现了许多计划作业(play.jobs.Job 的后代)。

问题

我可以在运行时更改这些作业的时间表吗?

我自己的发现

乍一看,Play 中的作业调度!是通过play.jobs.JobsPlugin 完成的,后者又使用公开的JDK 的java.util.concurrent.ScheduledThreadPoolExecutor 实例。到目前为止,我想出了以下方法:当需要更改时间表时,我只需迭代执行者的预定作业,取消一个我需要重新安排的作业并安排相同的作业(更准确地说,同一类的作业)新设置。像这样的:

for (final Object o: JobsPlugin.executor.getQueue())
{
    ScheduledFuture task = (ScheduledFuture) o;
    Job job = (Job) Java.extractUnderlyingCallable((FutureTask)task);
    if (MyJob.class == job.getClass())
    {
        task.cancel(true);
        new MyJob().every("2h");
        break;
    }
}

有没有更好的解决方案? 谢谢!

【问题讨论】:

    标签: playframework scheduler jobs playframework-1.x


    【解决方案1】:

    我不确定您的解决方案是否有效,因为当您查看 JobsPlugin 调用时,它会在每个作业执行结束时重新计算作业的下一个计划执行日期。

    这是我的解决方案,我重新创建了一个 JobScheduler 类,以便能够根据我的作业的 cron 属性计算作业执行日期。由于可见性规则,我不得不重新声明一些工作属性。

    所以我的工作类别是

    package jobs;
    
    import java.util.Date;
    import java.util.concurrent.ExecutorService;
    
    import play.jobs.Job;
    
    public class MyJob extends Job<Object> {
    
        public Date nextPlannedExecution = null;
        public String cron = null;
    
        @Override
        public void _finally() {
            // cron is null if we force job execution
            if (cron != null) {
                // As the job don't have a Cron annotation, super call does nothing
                super._finally();
                JobScheduler.scheduleForCRON(this, cron);
            }
        }
    
        void setExecutor(ExecutorService executor) {
            this.executor = executor;
        }
    }
    

    我的调度程序类是 打包工作;

    import java.util.Date;
    import java.util.concurrent.Callable;
    import java.util.concurrent.TimeUnit;
    
    import models.Partner;
    import play.Logger;
    import play.jobs.Job;
    import play.jobs.JobsPlugin;
    import play.libs.Expression;
    import play.libs.Time.CronExpression;
    
    public class JobScheduler {
    
        public static synchronized void scheduleCsvExportJob(String cron) {
            MyJob myJob = null;
            for (Job<?> job : JobsPlugin.scheduledJobs) {
                if (job instanceof MyJob) {
                    myJob = (MyJob) job;
                }
            }
            if (myJob == null) {
                myJob = new MyJob();
                JobsPlugin.scheduledJobs.add(myJob);
            }
            myJob.cron = cron;
            scheduleForCRON(myJob, myJob.cron);
        }
    
        public static void scheduleForCRON(MyJob job, String cron) {
            try {
                Date now = new Date();
                cron = Expression.evaluate(cron, cron).toString();
                CronExpression cronExp = new CronExpression(cron);
                Date nextDate = cronExp.getNextValidTimeAfter(now);
                if (nextDate != null && !nextDate.equals(job.nextPlannedExecution)) {
                    job.nextPlannedExecution = nextDate;
                    JobsPlugin.executor.schedule((Callable<?>) job, nextDate.getTime() - now.getTime(),
                            TimeUnit.MILLISECONDS);
                    job.setExecutor(JobsPlugin.executor);
                }
            } catch (Exception ex) {
                Logger.error(ex, "Cannot schedule job %s", job);
            }
        }
    }
    

    使用此代码,您可以调用 JobScheduler.scheduleMyJob 通过传递正确的调度表达式来更改作业的调度:0 0 2 * * ?每 2 小时一次。

    当作业终止时,_finally 方法将调用设置新调度时间的 scheduleForCRON 方法。

    如果你想强制执行作业,例如通过一个 gui 按钮,你可以创建一个没有 cron 属性定义的实例,这个实例最后不会重新安排自己

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-09
      • 2023-03-19
      相关资源
      最近更新 更多