で非同期呼び出しを取り扱い、私はこのようになります@ManagedAsync
方法のクラスで、リソースClass
を持っている:cleanupDirtyData
への呼び出しは、しばらく時間がかかることができるのでDropwizardでJAX-RS:即時応答
@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
を非同期的に実行し続けることです。
だから、次のことを試みた:
力強いタイムアウトを置くと、クライアントへの時期尚早な応答を与えるが、それは理想的な方法ではないようですし、それが実行を停止します。
@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プレースホルダコードだったので、ジョブが完了した後で応答を返す必要はありません。長時間実行されるタスクには、最大15分かかるディスクI/Oが多数必要です。 – anand