我有一個資源Class
,具有@ManagedAsync
方法類看起來像這樣:JAX-RS在Dropwizard:處理異步調用與即時響應
@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分鐘。 – anand