【发布时间】:2020-02-10 20:41:01
【问题描述】:
假设,有一些 scala 代码应该在java quartz library 的帮助下安排。
我们需要将此代码执行的结果存储在作业上下文中,以便在下一次作业执行中访问此结果。
例如,有一些CounterService 有一个inc 函数,应该被调度:
trait CounterService {
def inc(): Int
}
以下quartz-job成功调用inc并将其结果存储在JobDataMap中:
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
class CounterJob extends Job {
val counterService: CounterService = ...
override def execute(context: JobExecutionContext): Unit = {
val newCounterValue: Int = counterService.inc()
val map = context.getJobDetail.getJobDataMap
map.put("counter", newCounterValue)
}
}
我们可以随时在其他地方获得工作结果(如果我们有参考scheduler):
val scheduler: Scheduler = ...
// gets details of our CounterJob which was created and registered in the scheduler
// by the name "counter-job" (it is not shown in our example)
val job = scheduler.getJobDetail(JobKey.jobKey("counter-job"))
// this map will contain the job result which was stored by the key "counter"
val map = job.getJobDataMap.asScala
但是如果我们想从quartz-job 执行async 代码,这个方法就不起作用了。 例如,假设我们的柜台服务如下:
trait AsyncCounterService {
def asyncInc(): Future[Int]
}
我们可以尝试通过以下方式来实现我们的工作。但它不能正常工作,因为
方法CounterJob.execute 可以早于asyncCounterService.asyncInc 执行。
而且我们无法将asyncInc 的结果存储在JobDataMap 中:
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
class CounterJob extends Job {
val counterService: AsyncCounterService = ...
val execContext: ExecutionContext = ...
override def execute(context: JobExecutionContext): Unit = {
// # 1: we can not influence on the execution flow of this future
// from job scheduler.
val counterFuture: Future[Int] = counterService.asyncInc()
counterFuture.map { counterValue: Int =>
val map = context.getJobDetail.getJobDataMap
// #2: this action won't have any effect
map.put("counter", counterValue)
}
}
}
以上代码中标记为#1 ...和#2 ... cmets的这个解决方案至少有两个问题。
有没有更好的做法来解决这个问题?
换句话说,如何从持久石英作业中调度 scala Future,并将 Future's 结果存储在 JobDetailData 映射中?
【问题讨论】:
标签: java scala quartz-scheduler