【发布时间】:2017-06-02 17:45:09
【问题描述】:
我有一个资源Class,有一个@ManagedAsync 方法类,看起来像这样:
@Path("my-resource")
public class MyResource extends BaseResource{
private DatumDAO datumDAO;
public MyResource(DatumDAO datumDAO){
this.datumDAO = datumDAO;
}
public void cleanDatum(Datum datum){
//time taking operations
}
@GET
@ManagedAsync
@Path("/cleanup/{from}/{till}/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@UnitOfWork
public void cleanupDirtyData(@Suspended final AsyncResponse asyncResponse, @PathParam("from") DateTimeParam from,
@PathParam("till") DateTimeParam till) throws IOException{
logger.debug("will try to cleanup dirty data in range: " + from + " " + till);
List<Datum> data = datumDAO.getALlDirtyDatumInRange(from.get().toDate(), till.get().toDate());
Map<Long,String> cleanupMap = new HashMap<Long,String>();
for(Datum datum: data){
cleanDatum(datum);
cleanupMap.put(datum.getId(), "cleaned");
}
// this response need to be sent [can be ignored]
asyncResponse.resume(Response.status(HttpStatus.OK_200).entity(cleanupMap).build());
}
}
由于对cleanupDirtyData 的调用可能需要一段时间,我不希望客户端完全等待它,我知道执行工作已卸载到不同的工作线程。
我想要实现的是立即响应客户端并继续异步执行函数cleanupDirtyData。
于是尝试了以下方法:
强制超时,并过早地响应客户端,但这似乎不是理想的方式,它会停止执行。
看起来像这样:
@Path("my-resource")
public class MyResource extends BaseResource{
private DatumDAO datumDAO;
public MyResource(DatumDAO datumDAO){
this.datumDAO = datumDAO;
}
public void cleanDatum(Datum datum){
//time taking operations
}
@GET
@ManagedAsync
@Path("/cleanup/{from}/{till}/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@UnitOfWork
public void cleanupDirtyData(@Suspended final AsyncResponse asyncResponse, @PathParam("from") DateTimeParam from,
@PathParam("till") DateTimeParam till) throws IOException{
// Register handler and set timeout
asyncResponse.setTimeoutHandler(new TimeoutHandler() {
public void handleTimeout(AsyncResponse ar) {
asyncResponse.resume(Response.status(SERVICE_UNAVAILABLE).entity(
"Operation timed out -- please try again").build());
}
});
ar.setTimeout(15, TimeUnit.SECONDS);
logger.debug("will try to cleanup dirty data in range: " + from + " " + till);
List<Datum> data = datumDAO.getALlDirtyDatumInRange(from.get().toDate(), till.get().toDate());
Map<Long,String> cleanupMap = new HashMap<Long,String>();
for(Datum datum: data){
cleanDatum(datum);
cleanupMap.put(datum.getId(), "cleaned");
}
// this response need to be sent [can be ignored]
asyncResponse.resume(Response.status(HttpStatus.OK_200).entity(cleanupMap).build());
}
}
【问题讨论】:
-
“由于对 cleanupDirtyData 的调用可能需要一段时间,我不希望客户完全等待它” - 你想知道为什么这没有意义吗?因为在您的代码中,您正在向客户端返回响应正文。如果该响应正文是“长时间运行的执行”的一部分,那么当获取正文的执行未完成时,您如何期望将响应返回给客户端?如果我错了,您的代码中长期运行的任务到底是什么?
-
@peeskillet 这是一个占位符代码,工作完成后我不需要返回任何响应。长时间运行的任务涉及大量磁盘 I/O,可能需要长达 15 分钟。
标签: java jersey-2.0 dropwizard