Play Framework:乔布斯中类似于等待的功能

时间:2011-10-19 16:27:47

标签: playframework scheduled-tasks

我正在尝试使用Play中的异步作业运行长时间运行的任务(不阻止HTTP请求执行池)。 Play中的Jobs完全由框架管理,因此Play将负责数据库连接和事务。这意味着作业在单个事务中作为普通调用运行。这对于大多数用例来说都很棒,但是如果你需要在作业完成之前提交一些数据呢?

嗯,根据Guillaume Bort,一个选项是

  

将您的流程分成几个小工作

他给出了以下例子:

@On("0 0 12 * * ?") 
public class UpdateCounters extends Job { 
   public void doJob() { 
       List<Employee> empList = Employee.find("long and boring SQL :)").fetch(); 
       for(Employee emp : empList) { 
           new UpdateEmployeeJob(emp).now().get(); 
       } 
   } 
}

这很酷......每个新工作都有自己的事务,所以当这个新工作完成时,它会提交数据。干净简单! 但是如果你不想这样做呢?假设您需要等到数据提交后再继续初始作业吗?

通常,您将从新作业中检索Promise并调用await(jobPromise)但这在作业中不起作用(等待仅在扩展Controller时可用且未在作业上实现)...

那么在新的较小作业完成之前暂停初始作业的最佳方法是什么?

3 个答案:

答案 0 :(得分:8)

在查看Job是否完成(不使用数据库)的不同方法之后,我注意到Play Promise实现了Future接口,因此具有isDone()操作,可以使用这个检查任务是否完成。

更好的是,Future接口还定义了一个get()方法

  

等待计算完成所需,然后检索   结果。

因此暂停初始作业直到新的较小作业完成,可以通过调用Promise上的get()来实现,在较小的作业上调用now()时返回(就像Guillaume的例子中所做的那样)

谢谢!

答案 1 :(得分:1)

也许您可以使用以下代码进行批量提交:


        Employee.em().getTransaction().commit();
        Employee.em().getTransaction().begin();
        Employee.em().flush();
        Employee.em().clear();

答案 2 :(得分:0)

考虑到Play的本质,我会说唯一的方法是拥有一些标志(通常在数据库中),“父亲”作业可以在循环中检查并阻止自己等待它。

例如:

//take it as an idea, not as working code as it may have typos and dragons
public void doJob() { 
       String uuid = generateUUID();
       List<Employee> empList = Employee.find("long and boring SQL :)").fetch(); 
       for(Employee emp : empList) { 
           //update employee giving uuid so we know this job is related to this parent
           new UpdateEmployeeJob(emp, uuid).now().get(); 
       } 
       int done = 0;
       while(done < empList.size()) {
          //query db for number of instances updated with this uuid 
          //(assuming instance updated once child job is done)
          done = Update.count("uuid = ?1",uuid);
       }
   }

可以管理它